]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8552 Sanitize api/navigation/* WS
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Tue, 20 Dec 2016 13:49:46 +0000 (14:49 +0100)
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Tue, 20 Dec 2016 15:18:02 +0000 (16:18 +0100)
75 files changed:
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
server/sonar-server/src/main/java/org/sonar/server/ui/ws/ComponentAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/ui/ws/ComponentNavigationAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/ui/ws/GlobalAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/ui/ws/GlobalNavigationAction.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/ui/ws/NavigationWsModule.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/ui/ws/SettingsAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/ui/ws/SettingsNavigationAction.java [deleted file]
server/sonar-server/src/main/resources/org/sonar/server/ui/ws/component-example.json [new file with mode: 0644]
server/sonar-server/src/main/resources/org/sonar/server/ui/ws/example-component.json [deleted file]
server/sonar-server/src/main/resources/org/sonar/server/ui/ws/example-global.json [deleted file]
server/sonar-server/src/main/resources/org/sonar/server/ui/ws/example-settings.json [deleted file]
server/sonar-server/src/main/resources/org/sonar/server/ui/ws/global-example.json [new file with mode: 0644]
server/sonar-server/src/main/resources/org/sonar/server/ui/ws/settings-example.json [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/ui/ws/ComponentActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/ui/ws/ComponentNavigationActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/ui/ws/GlobalActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/ui/ws/GlobalNavigationActionTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/ui/ws/NavigationWsModuleTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/ui/ws/SettingsActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/ui/ws/SettingsNavigationActionTest.java [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_bread_crumbs_on_several_levels.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_breadcrumbs_on_module.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_component_info_when_anonymous_no_snapshot.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_component_info_when_snapshot.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_component_info_with_favourite.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_configuration_for_admin.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_configuration_for_quality_profile_admin.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_configuration_with_all_properties.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_default_quality_gate.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_empty_quality_profiles_when_no_measure.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_extensions.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_extensions_for_admin.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_quality_gate.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_quality_profiles.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_bread_crumbs_on_several_levels.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_breadcrumbs_on_module.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_component_info_when_anonymous_no_snapshot.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_component_info_when_snapshot.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_component_info_with_favourite.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_configuration_for_admin.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_configuration_for_quality_profile_admin.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_configuration_with_all_properties.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_default_quality_gate.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_empty_quality_profiles_when_no_measure.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_extensions.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_extensions_for_admin.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_quality_gate.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_quality_profiles.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/deprecated_logo_settings.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/empty.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/global_pages_for_admin.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/global_pages_for_anonymous.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/global_pages_for_user.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/production_database.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/qualifiers.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/settings.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/version.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/deprecated_logo_settings.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/empty.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/global_pages_for_admin.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/global_pages_for_anonymous.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/global_pages_for_user.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/production_database.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/qualifiers.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/settings.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/version.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/SettingsActionTest/empty.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/SettingsActionTest/with_provisioning.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/SettingsActionTest/with_update_center.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/SettingsActionTest/with_views.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/SettingsNavigationActionTest/empty.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/SettingsNavigationActionTest/with_provisioning.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/SettingsNavigationActionTest/with_update_center.json [deleted file]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/SettingsNavigationActionTest/with_views.json [deleted file]

index 693f6f5976c9d4ee0a1debfede6c567796177293..9d0ae80c37d4b5d56e4bca61a535fbd4848394da 100644 (file)
@@ -197,10 +197,7 @@ import org.sonar.server.text.MacroInterpreter;
 import org.sonar.server.text.RubyTextService;
 import org.sonar.server.ui.PageDecorations;
 import org.sonar.server.ui.Views;
-import org.sonar.server.ui.ws.ComponentNavigationAction;
-import org.sonar.server.ui.ws.GlobalNavigationAction;
-import org.sonar.server.ui.ws.NavigationWs;
-import org.sonar.server.ui.ws.SettingsNavigationAction;
+import org.sonar.server.ui.ws.NavigationWsModule;
 import org.sonar.server.updatecenter.UpdateCenterModule;
 import org.sonar.server.user.DefaultUserFinder;
 import org.sonar.server.user.DefaultUserService;
@@ -518,10 +515,7 @@ public class PlatformLevel4 extends PlatformLevel {
       ProjectSettingsFactory.class,
 
       // UI
-      GlobalNavigationAction.class,
-      SettingsNavigationAction.class,
-      ComponentNavigationAction.class,
-      NavigationWs.class,
+      NavigationWsModule.class,
 
       // root
       RootWsModule.class,
diff --git a/server/sonar-server/src/main/java/org/sonar/server/ui/ws/ComponentAction.java b/server/sonar-server/src/main/java/org/sonar/server/ui/ws/ComponentAction.java
new file mode 100644 (file)
index 0000000..41503bd
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.ui.ws;
+
+import com.google.common.collect.Lists;
+import java.util.Date;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import javax.annotation.Nullable;
+import org.sonar.api.i18n.I18n;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.ResourceType;
+import org.sonar.api.resources.ResourceTypes;
+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.DateUtils;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.api.web.NavigationSection;
+import org.sonar.api.web.Page;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.SnapshotDto;
+import org.sonar.db.measure.MeasureDto;
+import org.sonar.db.measure.MeasureQuery;
+import org.sonar.db.property.PropertyDto;
+import org.sonar.db.property.PropertyQuery;
+import org.sonar.db.qualitygate.QualityGateDto;
+import org.sonar.server.ce.ws.ActivityAction;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.qualitygate.QualityGateFinder;
+import org.sonar.server.qualityprofile.QPMeasureData;
+import org.sonar.server.qualityprofile.QualityProfile;
+import org.sonar.server.ui.ViewProxy;
+import org.sonar.server.ui.Views;
+import org.sonar.server.user.UserSession;
+
+import static java.util.Locale.ENGLISH;
+import static org.sonar.api.measures.CoreMetrics.QUALITY_PROFILES_KEY;
+import static org.sonar.api.web.UserRole.ADMIN;
+import static org.sonar.api.web.UserRole.USER;
+import static org.sonar.core.permission.GlobalPermissions.QUALITY_PROFILE_ADMIN;
+import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
+
+public class ComponentAction implements NavigationWsAction {
+
+  private static final String PARAM_COMPONENT_KEY = "componentKey";
+
+  private static final String PROPERTY_CONFIGURABLE = "configurable";
+  private static final String PROPERTY_HAS_ROLE_POLICY = "hasRolePolicy";
+  private static final String PROPERTY_MODIFIABLE_HISTORY = "modifiable_history";
+  private static final String PROPERTY_UPDATABLE_KEY = "updatable_key";
+
+  private final DbClient dbClient;
+  private final Views views;
+  private final I18n i18n;
+  private final ResourceTypes resourceTypes;
+  private final UserSession userSession;
+  private final ComponentFinder componentFinder;
+  private final QualityGateFinder qualityGateFinder;
+
+  public ComponentAction(DbClient dbClient, Views views, I18n i18n, ResourceTypes resourceTypes, UserSession userSession,
+                         ComponentFinder componentFinder, QualityGateFinder qualityGateFinder) {
+    this.dbClient = dbClient;
+    this.views = views;
+    this.i18n = i18n;
+    this.resourceTypes = resourceTypes;
+    this.userSession = userSession;
+    this.componentFinder = componentFinder;
+    this.qualityGateFinder = qualityGateFinder;
+  }
+
+  @Override
+  public void define(NewController context) {
+    NewAction projectNavigation = context.createAction("component")
+      .setDescription("Get information concerning component navigation for the current user. " +
+        "Requires the 'Browse' permission on the component's project.")
+      .setHandler(this)
+      .setInternal(true)
+      .setResponseExample(getClass().getResource("component-example.json"))
+      .setSince("5.2");
+
+    projectNavigation.createParam(PARAM_COMPONENT_KEY)
+      .setDescription("A component key.")
+      .setExampleValue(KEY_PROJECT_EXAMPLE_001);
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    String componentKey = request.mandatoryParam(PARAM_COMPONENT_KEY);
+    try (DbSession session = dbClient.openSession(false)) {
+      ComponentDto component = componentFinder.getByKey(session, componentKey);
+      if (!(userSession.hasComponentUuidPermission(USER, component.projectUuid()) || userSession.hasComponentUuidPermission(ADMIN, component.projectUuid()))) {
+        throw new ForbiddenException("Insufficient privileges");
+      }
+      Optional<SnapshotDto> analysis = dbClient.snapshotDao().selectLastAnalysisByRootComponentUuid(session, component.projectUuid());
+
+      JsonWriter json = response.newJsonWriter();
+      json.beginObject();
+      writeComponent(json, session, component, analysis.orElse(null));
+      writeProfiles(json, session, component);
+      writeQualityGate(json, session, component);
+      if (userSession.hasComponentUuidPermission(ADMIN, component.projectUuid()) || userSession.hasPermission(QUALITY_PROFILE_ADMIN)) {
+        writeConfiguration(json, component);
+      }
+      writeBreadCrumbs(json, session, component);
+      json.endObject().close();
+    }
+  }
+
+  private void writeComponent(JsonWriter json, DbSession session, ComponentDto component, @Nullable SnapshotDto analysis) {
+    json.prop("key", component.key())
+      .prop("id", component.uuid())
+      .prop("name", component.name())
+      .prop("description", component.description())
+      .prop("isFavorite", isFavourite(session, component));
+
+    if (analysis != null) {
+      json.prop("version", analysis.getVersion())
+        .prop("snapshotDate", DateUtils.formatDateTime(new Date(analysis.getCreatedAt())));
+      List<ViewProxy<Page>> pages = views.getPages(NavigationSection.RESOURCE, component.scope(), component.qualifier(), component.language());
+      writeExtensions(json, component, pages);
+    }
+  }
+
+  private boolean isFavourite(DbSession session, ComponentDto component) {
+    PropertyQuery propertyQuery = PropertyQuery.builder()
+      .setUserId(userSession.getUserId())
+      .setKey("favourite")
+      .setComponentId(component.getId())
+      .build();
+    List<PropertyDto> componentFavourites = dbClient.propertiesDao().selectByQuery(propertyQuery, session);
+    return componentFavourites.size() == 1;
+  }
+
+  private void writeProfiles(JsonWriter json, DbSession session, ComponentDto component) {
+    json.name("qualityProfiles").beginArray();
+    dbClient.measureDao().selectSingle(session, MeasureQuery.builder().setComponentUuid(component.projectUuid()).setMetricKey(QUALITY_PROFILES_KEY).build())
+      .ifPresent(dbMeasure -> Stream.of(dbMeasure)
+        .flatMap(toQualityProfiles())
+        .forEach(writeToJson(json)));
+    json.endArray();
+  }
+
+  private static Consumer<QualityProfile> writeToJson(JsonWriter json) {
+    return profile -> json.beginObject()
+      .prop("key", profile.getQpKey())
+      .prop("name", profile.getQpName())
+      .prop("language", profile.getLanguageKey())
+      .endObject();
+  }
+
+  private static Function<MeasureDto, Stream<QualityProfile>> toQualityProfiles() {
+    return dbMeasure -> QPMeasureData.fromJson(dbMeasure.getData()).getProfiles().stream();
+  }
+
+  private void writeQualityGate(JsonWriter json, DbSession session, ComponentDto component) {
+    Optional<QualityGateFinder.QualityGateData> qualityGateData = qualityGateFinder.getQualityGate(session, component.getId());
+    if (!qualityGateData.isPresent()) {
+      return;
+    }
+    QualityGateDto qualityGateDto = qualityGateData.get().getQualityGate();
+    json.name("qualityGate").beginObject()
+      .prop("key", qualityGateDto.getId())
+      .prop("name", qualityGateDto.getName())
+      .prop("isDefault", qualityGateData.get().isDefault())
+      .endObject();
+  }
+
+  private void writeExtensions(JsonWriter json, ComponentDto component, List<ViewProxy<Page>> pages) {
+    json.name("extensions").beginArray();
+    pages.stream()
+      .filter(page -> page.isUserAuthorized(component))
+      .forEach(page -> writePage(json, page.getId(), i18n.message(ENGLISH, page.getId() + ".page", page.getTitle())));
+    json.endArray();
+  }
+
+  private void writeConfiguration(JsonWriter json, ComponentDto component) {
+    boolean isAdmin = userSession.hasComponentUuidPermission(ADMIN, component.projectUuid());
+
+    json.name("configuration").beginObject();
+    writeConfigPageAccess(json, isAdmin, component);
+
+    if (isAdmin) {
+      json.name("extensions").beginArray();
+      List<ViewProxy<Page>> configPages = views.getPages(NavigationSection.RESOURCE_CONFIGURATION, component.scope(), component.qualifier(), component.language());
+      configPages.forEach(page -> writePage(json, page.getId(), i18n.message(ENGLISH, page.getId() + ".page", page.getTitle())));
+      json.endArray();
+    }
+    json.endObject();
+  }
+
+  private void writeConfigPageAccess(JsonWriter json, boolean isAdmin, ComponentDto component) {
+    boolean isProject = Qualifiers.PROJECT.equals(component.qualifier());
+    boolean showManualMeasures = isAdmin && !Qualifiers.DIRECTORY.equals(component.qualifier());
+
+    json.prop("showSettings", isAdmin && componentTypeHasProperty(component, PROPERTY_CONFIGURABLE));
+    json.prop("showQualityProfiles", isProject);
+    json.prop("showQualityGates", isProject);
+    json.prop("showManualMeasures", showManualMeasures);
+    json.prop("showLinks", isAdmin && isProject);
+    json.prop("showPermissions", isAdmin && componentTypeHasProperty(component, PROPERTY_HAS_ROLE_POLICY));
+    json.prop("showHistory", isAdmin && componentTypeHasProperty(component, PROPERTY_MODIFIABLE_HISTORY));
+    json.prop("showUpdateKey", isAdmin && componentTypeHasProperty(component, PROPERTY_UPDATABLE_KEY));
+    json.prop("showBackgroundTasks", ActivityAction.isAllowedOnComponentUuid(userSession, component.uuid()));
+  }
+
+  private boolean componentTypeHasProperty(ComponentDto component, String resourceTypeProperty) {
+    ResourceType resourceType = resourceTypes.get(component.qualifier());
+    return resourceType != null && resourceType.getBooleanProperty(resourceTypeProperty);
+  }
+
+  private static void writePage(JsonWriter json, String id, String name) {
+    json.beginObject()
+      .prop("id", id)
+      .prop("name", name)
+      .endObject();
+  }
+
+  private void writeBreadCrumbs(JsonWriter json, DbSession session, ComponentDto component) {
+    json.name("breadcrumbs").beginArray();
+
+    List<ComponentDto> breadcrumb = Lists.newArrayList();
+    breadcrumb.addAll(dbClient.componentDao().selectAncestors(session, component));
+    breadcrumb.add(component);
+
+    for (ComponentDto c : breadcrumb) {
+      json.beginObject()
+        .prop("key", c.key())
+        .prop("name", c.name())
+        .prop("qualifier", c.qualifier())
+        .endObject();
+    }
+
+    json.endArray();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/ui/ws/ComponentNavigationAction.java b/server/sonar-server/src/main/java/org/sonar/server/ui/ws/ComponentNavigationAction.java
deleted file mode 100644 (file)
index 6066f48..0000000
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.ui.ws;
-
-import com.google.common.collect.Lists;
-import java.util.Date;
-import java.util.List;
-import java.util.Optional;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.stream.Stream;
-import javax.annotation.Nullable;
-import org.sonar.api.i18n.I18n;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.ResourceType;
-import org.sonar.api.resources.ResourceTypes;
-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.DateUtils;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.api.web.NavigationSection;
-import org.sonar.api.web.Page;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.SnapshotDto;
-import org.sonar.db.measure.MeasureDto;
-import org.sonar.db.measure.MeasureQuery;
-import org.sonar.db.property.PropertyDto;
-import org.sonar.db.property.PropertyQuery;
-import org.sonar.db.qualitygate.QualityGateDto;
-import org.sonar.server.ce.ws.ActivityAction;
-import org.sonar.server.component.ComponentFinder;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.qualitygate.QualityGateFinder;
-import org.sonar.server.qualityprofile.QPMeasureData;
-import org.sonar.server.qualityprofile.QualityProfile;
-import org.sonar.server.ui.ViewProxy;
-import org.sonar.server.ui.Views;
-import org.sonar.server.user.UserSession;
-
-import static java.util.Locale.ENGLISH;
-import static org.sonar.api.measures.CoreMetrics.QUALITY_PROFILES_KEY;
-import static org.sonar.api.web.UserRole.ADMIN;
-import static org.sonar.api.web.UserRole.USER;
-import static org.sonar.core.permission.GlobalPermissions.QUALITY_PROFILE_ADMIN;
-import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
-
-public class ComponentNavigationAction implements NavigationWsAction {
-
-  private static final String PARAM_COMPONENT_KEY = "componentKey";
-
-  private static final String PROPERTY_CONFIGURABLE = "configurable";
-  private static final String PROPERTY_HAS_ROLE_POLICY = "hasRolePolicy";
-  private static final String PROPERTY_MODIFIABLE_HISTORY = "modifiable_history";
-  private static final String PROPERTY_UPDATABLE_KEY = "updatable_key";
-
-  private final DbClient dbClient;
-  private final Views views;
-  private final I18n i18n;
-  private final ResourceTypes resourceTypes;
-  private final UserSession userSession;
-  private final ComponentFinder componentFinder;
-  private final QualityGateFinder qualityGateFinder;
-
-  public ComponentNavigationAction(DbClient dbClient, Views views, I18n i18n, ResourceTypes resourceTypes, UserSession userSession,
-    ComponentFinder componentFinder, QualityGateFinder qualityGateFinder) {
-    this.dbClient = dbClient;
-    this.views = views;
-    this.i18n = i18n;
-    this.resourceTypes = resourceTypes;
-    this.userSession = userSession;
-    this.componentFinder = componentFinder;
-    this.qualityGateFinder = qualityGateFinder;
-  }
-
-  @Override
-  public void define(NewController context) {
-    NewAction projectNavigation = context.createAction("component")
-      .setDescription("Get information concerning component navigation for the current user. " +
-        "Requires the 'Browse' permission on the component's project.")
-      .setHandler(this)
-      .setInternal(true)
-      .setResponseExample(getClass().getResource("example-component.json"))
-      .setSince("5.2");
-
-    projectNavigation.createParam(PARAM_COMPONENT_KEY)
-      .setDescription("A component key.")
-      .setExampleValue(KEY_PROJECT_EXAMPLE_001);
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    String componentKey = request.mandatoryParam(PARAM_COMPONENT_KEY);
-    try (DbSession session = dbClient.openSession(false)) {
-      ComponentDto component = componentFinder.getByKey(session, componentKey);
-      if (!(userSession.hasComponentUuidPermission(USER, component.projectUuid()) || userSession.hasComponentUuidPermission(ADMIN, component.projectUuid()))) {
-        throw new ForbiddenException("Insufficient privileges");
-      }
-      Optional<SnapshotDto> analysis = dbClient.snapshotDao().selectLastAnalysisByRootComponentUuid(session, component.projectUuid());
-
-      JsonWriter json = response.newJsonWriter();
-      json.beginObject();
-      writeComponent(json, session, component, analysis.orElse(null));
-      writeProfiles(json, session, component);
-      writeQualityGate(json, session, component);
-      if (userSession.hasComponentUuidPermission(ADMIN, component.projectUuid()) || userSession.hasPermission(QUALITY_PROFILE_ADMIN)) {
-        writeConfiguration(json, component);
-      }
-      writeBreadCrumbs(json, session, component);
-      json.endObject().close();
-    }
-  }
-
-  private void writeComponent(JsonWriter json, DbSession session, ComponentDto component, @Nullable SnapshotDto analysis) {
-    json.prop("key", component.key())
-      .prop("id", component.uuid())
-      .prop("name", component.name())
-      .prop("description", component.description())
-      .prop("isFavorite", isFavourite(session, component));
-
-    if (analysis != null) {
-      json.prop("version", analysis.getVersion())
-        .prop("snapshotDate", DateUtils.formatDateTime(new Date(analysis.getCreatedAt())));
-      List<ViewProxy<Page>> pages = views.getPages(NavigationSection.RESOURCE, component.scope(), component.qualifier(), component.language());
-      writeExtensions(json, component, pages);
-    }
-  }
-
-  private boolean isFavourite(DbSession session, ComponentDto component) {
-    PropertyQuery propertyQuery = PropertyQuery.builder()
-      .setUserId(userSession.getUserId())
-      .setKey("favourite")
-      .setComponentId(component.getId())
-      .build();
-    List<PropertyDto> componentFavourites = dbClient.propertiesDao().selectByQuery(propertyQuery, session);
-    return componentFavourites.size() == 1;
-  }
-
-  private void writeProfiles(JsonWriter json, DbSession session, ComponentDto component) {
-    json.name("qualityProfiles").beginArray();
-    dbClient.measureDao().selectSingle(session, MeasureQuery.builder().setComponentUuid(component.projectUuid()).setMetricKey(QUALITY_PROFILES_KEY).build())
-      .ifPresent(dbMeasure -> Stream.of(dbMeasure)
-        .flatMap(toQualityProfiles())
-        .forEach(writeToJson(json)));
-    json.endArray();
-  }
-
-  private static Consumer<QualityProfile> writeToJson(JsonWriter json) {
-    return profile -> json.beginObject()
-      .prop("key", profile.getQpKey())
-      .prop("name", profile.getQpName())
-      .prop("language", profile.getLanguageKey())
-      .endObject();
-  }
-
-  private static Function<MeasureDto, Stream<QualityProfile>> toQualityProfiles() {
-    return dbMeasure -> QPMeasureData.fromJson(dbMeasure.getData()).getProfiles().stream();
-  }
-
-  private void writeQualityGate(JsonWriter json, DbSession session, ComponentDto component) {
-    Optional<QualityGateFinder.QualityGateData> qualityGateData = qualityGateFinder.getQualityGate(session, component.getId());
-    if (!qualityGateData.isPresent()) {
-      return;
-    }
-    QualityGateDto qualityGateDto = qualityGateData.get().getQualityGate();
-    json.name("qualityGate").beginObject()
-      .prop("key", qualityGateDto.getId())
-      .prop("name", qualityGateDto.getName())
-      .prop("isDefault", qualityGateData.get().isDefault())
-      .endObject();
-  }
-
-  private void writeExtensions(JsonWriter json, ComponentDto component, List<ViewProxy<Page>> pages) {
-    json.name("extensions").beginArray();
-    pages.stream()
-      .filter(page -> page.isUserAuthorized(component))
-      .forEach(page -> writePage(json, page.getId(), i18n.message(ENGLISH, page.getId() + ".page", page.getTitle())));
-    json.endArray();
-  }
-
-  private void writeConfiguration(JsonWriter json, ComponentDto component) {
-    boolean isAdmin = userSession.hasComponentUuidPermission(ADMIN, component.projectUuid());
-
-    json.name("configuration").beginObject();
-    writeConfigPageAccess(json, isAdmin, component);
-
-    if (isAdmin) {
-      json.name("extensions").beginArray();
-      List<ViewProxy<Page>> configPages = views.getPages(NavigationSection.RESOURCE_CONFIGURATION, component.scope(), component.qualifier(), component.language());
-      configPages.forEach(page -> writePage(json, page.getId(), i18n.message(ENGLISH, page.getId() + ".page", page.getTitle())));
-      json.endArray();
-    }
-    json.endObject();
-  }
-
-  private void writeConfigPageAccess(JsonWriter json, boolean isAdmin, ComponentDto component) {
-    boolean isProject = Qualifiers.PROJECT.equals(component.qualifier());
-    boolean showManualMeasures = isAdmin && !Qualifiers.DIRECTORY.equals(component.qualifier());
-
-    json.prop("showSettings", isAdmin && componentTypeHasProperty(component, PROPERTY_CONFIGURABLE));
-    json.prop("showQualityProfiles", isProject);
-    json.prop("showQualityGates", isProject);
-    json.prop("showManualMeasures", showManualMeasures);
-    json.prop("showLinks", isAdmin && isProject);
-    json.prop("showPermissions", isAdmin && componentTypeHasProperty(component, PROPERTY_HAS_ROLE_POLICY));
-    json.prop("showHistory", isAdmin && componentTypeHasProperty(component, PROPERTY_MODIFIABLE_HISTORY));
-    json.prop("showUpdateKey", isAdmin && componentTypeHasProperty(component, PROPERTY_UPDATABLE_KEY));
-    json.prop("showBackgroundTasks", ActivityAction.isAllowedOnComponentUuid(userSession, component.uuid()));
-  }
-
-  private boolean componentTypeHasProperty(ComponentDto component, String resourceTypeProperty) {
-    ResourceType resourceType = resourceTypes.get(component.qualifier());
-    return resourceType != null && resourceType.getBooleanProperty(resourceTypeProperty);
-  }
-
-  private static void writePage(JsonWriter json, String id, String name) {
-    json.beginObject()
-      .prop("id", id)
-      .prop("name", name)
-      .endObject();
-  }
-
-  private void writeBreadCrumbs(JsonWriter json, DbSession session, ComponentDto component) {
-    json.name("breadcrumbs").beginArray();
-
-    List<ComponentDto> breadcrumb = Lists.newArrayList();
-    breadcrumb.addAll(dbClient.componentDao().selectAncestors(session, component));
-    breadcrumb.add(component);
-
-    for (ComponentDto c : breadcrumb) {
-      json.beginObject()
-        .prop("key", c.key())
-        .prop("name", c.name())
-        .prop("qualifier", c.qualifier())
-        .endObject();
-    }
-
-    json.endArray();
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/ui/ws/GlobalAction.java b/server/sonar-server/src/main/java/org/sonar/server/ui/ws/GlobalAction.java
new file mode 100644 (file)
index 0000000..59ac7b1
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.ui.ws;
+
+import com.google.common.collect.ImmutableSet;
+import java.util.Set;
+import org.sonar.api.config.Settings;
+import org.sonar.api.platform.Server;
+import org.sonar.api.resources.ResourceType;
+import org.sonar.api.resources.ResourceTypes;
+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.api.web.NavigationSection;
+import org.sonar.api.web.Page;
+import org.sonar.db.Database;
+import org.sonar.db.dialect.H2;
+import org.sonar.server.ui.ViewProxy;
+import org.sonar.server.ui.Views;
+
+import static org.sonar.api.CoreProperties.CORE_ALLOW_USERS_TO_SIGNUP_PROPERTY;
+import static org.sonar.api.CoreProperties.HOURS_IN_DAY;
+import static org.sonar.api.CoreProperties.RATING_GRID;
+import static org.sonar.core.config.WebConstants.SONAR_LF_ENABLE_GRAVATAR;
+import static org.sonar.core.config.WebConstants.SONAR_LF_GRAVATAR_SERVER_URL;
+import static org.sonar.core.config.WebConstants.SONAR_LF_LOGO_URL;
+import static org.sonar.core.config.WebConstants.SONAR_LF_LOGO_WIDTH_PX;
+import static org.sonar.core.config.WebConstants.SONAR_UPDATECENTER_ACTIVATE;
+
+public class GlobalAction implements NavigationWsAction {
+
+  private static final Set<String> SETTING_KEYS = ImmutableSet.of(
+    SONAR_LF_LOGO_URL,
+    SONAR_LF_LOGO_WIDTH_PX,
+    SONAR_LF_ENABLE_GRAVATAR,
+    SONAR_LF_GRAVATAR_SERVER_URL,
+    SONAR_UPDATECENTER_ACTIVATE,
+    HOURS_IN_DAY,
+    RATING_GRID,
+    CORE_ALLOW_USERS_TO_SIGNUP_PROPERTY);
+
+  private final Views views;
+  private final Settings settings;
+  private final ResourceTypes resourceTypes;
+  private final Server server;
+  private final Database database;
+
+  public GlobalAction(Views views, Settings settings, ResourceTypes resourceTypes, Server server, Database database) {
+    this.views = views;
+    this.settings = settings;
+    this.resourceTypes = resourceTypes;
+    this.server = server;
+    this.database = database;
+  }
+
+  @Override
+  public void define(NewController context) {
+    context.createAction("global")
+      .setDescription("Get information concerning global navigation for the current user.")
+      .setHandler(this)
+      .setInternal(true)
+      .setResponseExample(getClass().getResource("global-example.json"))
+      .setSince("5.2");
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    JsonWriter json = response.newJsonWriter().beginObject();
+    writePages(json);
+    writeSettings(json);
+    writeDeprecatedLogoProperties(json);
+    writeQualifiers(json);
+    writeVersion(json);
+    writeDatabaseProduction(json);
+    json.endObject().close();
+  }
+
+  private void writePages(JsonWriter json) {
+    json.name("globalPages").beginArray();
+    for (ViewProxy<Page> page : views.getPages(NavigationSection.HOME)) {
+      if (page.isUserAuthorized()) {
+        json.beginObject()
+          .prop("id", page.getId())
+          .prop("name", page.getTitle())
+          .endObject();
+      }
+    }
+    json.endArray();
+  }
+
+  private void writeSettings(JsonWriter json) {
+    json.name("settings").beginObject();
+    for (String settingKey : SETTING_KEYS) {
+      json.prop(settingKey, settings.getString(settingKey));
+    }
+    json.endObject();
+  }
+
+  private void writeDeprecatedLogoProperties(JsonWriter json) {
+    json.prop("logoUrl", settings.getString(SONAR_LF_LOGO_URL));
+    json.prop("logoWidth", settings.getString(SONAR_LF_LOGO_WIDTH_PX));
+  }
+
+  private void writeQualifiers(JsonWriter json) {
+    json.name("qualifiers").beginArray();
+    for (ResourceType rootType : resourceTypes.getRoots()) {
+      json.value(rootType.getQualifier());
+    }
+    json.endArray();
+  }
+
+  private void writeVersion(JsonWriter json) {
+    json.prop("version", server.getVersion());
+  }
+
+  private void writeDatabaseProduction(JsonWriter json) {
+    json.prop("productionDatabase", !database.getDialect().getId().equals(H2.ID));
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/ui/ws/GlobalNavigationAction.java b/server/sonar-server/src/main/java/org/sonar/server/ui/ws/GlobalNavigationAction.java
deleted file mode 100644 (file)
index 8cb8817..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.ui.ws;
-
-import com.google.common.collect.ImmutableSet;
-import java.util.Set;
-import org.sonar.api.config.Settings;
-import org.sonar.api.platform.Server;
-import org.sonar.api.resources.ResourceType;
-import org.sonar.api.resources.ResourceTypes;
-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.api.web.NavigationSection;
-import org.sonar.api.web.Page;
-import org.sonar.db.Database;
-import org.sonar.db.dialect.H2;
-import org.sonar.server.ui.ViewProxy;
-import org.sonar.server.ui.Views;
-
-import static org.sonar.api.CoreProperties.CORE_ALLOW_USERS_TO_SIGNUP_PROPERTY;
-import static org.sonar.api.CoreProperties.HOURS_IN_DAY;
-import static org.sonar.api.CoreProperties.RATING_GRID;
-import static org.sonar.core.config.WebConstants.SONAR_LF_ENABLE_GRAVATAR;
-import static org.sonar.core.config.WebConstants.SONAR_LF_GRAVATAR_SERVER_URL;
-import static org.sonar.core.config.WebConstants.SONAR_LF_LOGO_URL;
-import static org.sonar.core.config.WebConstants.SONAR_LF_LOGO_WIDTH_PX;
-import static org.sonar.core.config.WebConstants.SONAR_UPDATECENTER_ACTIVATE;
-
-public class GlobalNavigationAction implements NavigationWsAction {
-
-  private static final Set<String> SETTING_KEYS = ImmutableSet.of(
-    SONAR_LF_LOGO_URL,
-    SONAR_LF_LOGO_WIDTH_PX,
-    SONAR_LF_ENABLE_GRAVATAR,
-    SONAR_LF_GRAVATAR_SERVER_URL,
-    SONAR_UPDATECENTER_ACTIVATE,
-    HOURS_IN_DAY,
-    RATING_GRID,
-    CORE_ALLOW_USERS_TO_SIGNUP_PROPERTY);
-
-  private final Views views;
-  private final Settings settings;
-  private final ResourceTypes resourceTypes;
-  private final Server server;
-  private final Database database;
-
-  public GlobalNavigationAction(Views views, Settings settings, ResourceTypes resourceTypes, Server server, Database database) {
-    this.views = views;
-    this.settings = settings;
-    this.resourceTypes = resourceTypes;
-    this.server = server;
-    this.database = database;
-  }
-
-  @Override
-  public void define(NewController context) {
-    context.createAction("global")
-      .setDescription("Get information concerning global navigation for the current user.")
-      .setHandler(this)
-      .setInternal(true)
-      .setResponseExample(getClass().getResource("example-global.json"))
-      .setSince("5.2");
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    JsonWriter json = response.newJsonWriter().beginObject();
-    writePages(json);
-    writeSettings(json);
-    writeDeprecatedLogoProperties(json);
-    writeQualifiers(json);
-    writeVersion(json);
-    writeDatabaseProduction(json);
-    json.endObject().close();
-  }
-
-  private void writePages(JsonWriter json) {
-    json.name("globalPages").beginArray();
-    for (ViewProxy<Page> page : views.getPages(NavigationSection.HOME)) {
-      if (page.isUserAuthorized()) {
-        json.beginObject()
-          .prop("id", page.getId())
-          .prop("name", page.getTitle())
-          .endObject();
-      }
-    }
-    json.endArray();
-  }
-
-  private void writeSettings(JsonWriter json) {
-    json.name("settings").beginObject();
-    for (String settingKey : SETTING_KEYS) {
-      json.prop(settingKey, settings.getString(settingKey));
-    }
-    json.endObject();
-  }
-
-  private void writeDeprecatedLogoProperties(JsonWriter json) {
-    json.prop("logoUrl", settings.getString(SONAR_LF_LOGO_URL));
-    json.prop("logoWidth", settings.getString(SONAR_LF_LOGO_WIDTH_PX));
-  }
-
-  private void writeQualifiers(JsonWriter json) {
-    json.name("qualifiers").beginArray();
-    for (ResourceType rootType : resourceTypes.getRoots()) {
-      json.value(rootType.getQualifier());
-    }
-    json.endArray();
-  }
-
-  private void writeVersion(JsonWriter json) {
-    json.prop("version", server.getVersion());
-  }
-
-  private void writeDatabaseProduction(JsonWriter json) {
-    json.prop("productionDatabase", !database.getDialect().getId().equals(H2.ID));
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/ui/ws/NavigationWsModule.java b/server/sonar-server/src/main/java/org/sonar/server/ui/ws/NavigationWsModule.java
new file mode 100644 (file)
index 0000000..304693c
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.ui.ws;
+
+import org.sonar.core.platform.Module;
+
+public class NavigationWsModule extends Module {
+  @Override
+  protected void configureModule() {
+    add(
+      NavigationWs.class,
+      ComponentAction.class,
+      GlobalAction.class,
+      SettingsAction.class);
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/ui/ws/SettingsAction.java b/server/sonar-server/src/main/java/org/sonar/server/ui/ws/SettingsAction.java
new file mode 100644 (file)
index 0000000..d866a73
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.ui.ws;
+
+import java.util.Locale;
+import org.sonar.api.config.Settings;
+import org.sonar.api.i18n.I18n;
+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.api.web.NavigationSection;
+import org.sonar.api.web.Page;
+import org.sonar.core.config.WebConstants;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.server.ui.ViewProxy;
+import org.sonar.server.ui.Views;
+import org.sonar.server.user.UserSession;
+
+public class SettingsAction implements NavigationWsAction {
+
+  private final Settings settings;
+  private final Views views;
+  private final I18n i18n;
+  private final UserSession userSession;
+
+  public SettingsAction(Settings settings, Views views, I18n i18n, UserSession userSession) {
+    this.views = views;
+    this.settings = settings;
+    this.i18n = i18n;
+    this.userSession = userSession;
+  }
+
+  @Override
+  public void define(NewController context) {
+    context.createAction("settings")
+      .setDescription("Get configuration information for the settings page:" +
+        "<ul>" +
+        "  <li>List plugin-contributed pages</li>" +
+        "  <li>Show update center (or not)</li>" +
+        "</ul>")
+      .setHandler(this)
+      .setInternal(true)
+      .setResponseExample(getClass().getResource("settings-example.json"))
+      .setSince("5.2");
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    boolean isAdmin = userSession.hasPermission(GlobalPermissions.SYSTEM_ADMIN);
+
+    JsonWriter json = response.newJsonWriter().beginObject();
+    json.prop("showUpdateCenter", isAdmin && settings.getBoolean(WebConstants.SONAR_UPDATECENTER_ACTIVATE));
+    json.prop("showProvisioning", userSession.hasPermission(GlobalPermissions.PROVISIONING));
+
+    json.name("extensions").beginArray();
+    if (isAdmin) {
+      for (ViewProxy<Page> page : views.getPages(NavigationSection.CONFIGURATION, null, null, null)) {
+        json.beginObject()
+          .prop("id", page.getId())
+          .prop("name", i18n.message(Locale.ENGLISH, String.format("%s.page", page.getTitle()), page.getTitle()))
+          .endObject();
+      }
+    }
+    json.endArray();
+
+    json.endObject().close();
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/ui/ws/SettingsNavigationAction.java b/server/sonar-server/src/main/java/org/sonar/server/ui/ws/SettingsNavigationAction.java
deleted file mode 100644 (file)
index 2e58109..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.ui.ws;
-
-import java.util.Locale;
-import org.sonar.api.config.Settings;
-import org.sonar.api.i18n.I18n;
-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.api.web.NavigationSection;
-import org.sonar.api.web.Page;
-import org.sonar.core.config.WebConstants;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.ui.ViewProxy;
-import org.sonar.server.ui.Views;
-import org.sonar.server.user.UserSession;
-
-public class SettingsNavigationAction implements NavigationWsAction {
-
-  private final Settings settings;
-  private final Views views;
-  private final I18n i18n;
-  private final UserSession userSession;
-
-  public SettingsNavigationAction(Settings settings, Views views, I18n i18n, UserSession userSession) {
-    this.views = views;
-    this.settings = settings;
-    this.i18n = i18n;
-    this.userSession = userSession;
-  }
-
-  @Override
-  public void define(NewController context) {
-    context.createAction("settings")
-      .setDescription("Get configuration information for the settings page:" +
-        "<ul>" +
-        "  <li>List plugin-contributed pages</li>" +
-        "  <li>Show update center (or not)</li>" +
-        "</ul>")
-      .setHandler(this)
-      .setInternal(true)
-      .setResponseExample(getClass().getResource("example-settings.json"))
-      .setSince("5.2");
-  }
-
-  @Override
-  public void handle(Request request, Response response) throws Exception {
-    boolean isAdmin = userSession.hasPermission(GlobalPermissions.SYSTEM_ADMIN);
-
-    JsonWriter json = response.newJsonWriter().beginObject();
-    json.prop("showUpdateCenter", isAdmin && settings.getBoolean(WebConstants.SONAR_UPDATECENTER_ACTIVATE));
-    json.prop("showProvisioning", userSession.hasPermission(GlobalPermissions.PROVISIONING));
-
-    json.name("extensions").beginArray();
-    if (isAdmin) {
-      for (ViewProxy<Page> page : views.getPages(NavigationSection.CONFIGURATION, null, null, null)) {
-        json.beginObject()
-          .prop("id", page.getId())
-          .prop("name", i18n.message(Locale.ENGLISH, String.format("%s.page", page.getTitle()), page.getTitle()))
-          .endObject();
-      }
-    }
-    json.endArray();
-
-    json.endObject().close();
-  }
-}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/ui/ws/component-example.json b/server/sonar-server/src/main/resources/org/sonar/server/ui/ws/component-example.json
new file mode 100644 (file)
index 0000000..40878b2
--- /dev/null
@@ -0,0 +1,59 @@
+{
+  "key": "org.codehaus.sonar:sonar",
+  "id": "ABCD",
+  "name": "Sonarqube",
+  "description": "Open source platform for continuous inspection of code quality",
+  "isFavorite": true,
+  "version": "6.3",
+  "snapshotDate": "2016-12-06T11:44:00+0200",
+  "extensions": [
+    {
+      "id": "/admin/page",
+      "name": "Admin Page"
+    },
+    {
+      "id": "first_page",
+      "name": "First Page"
+    },
+    {
+      "id": "/second/page",
+      "name": "Second Page"
+    }
+  ],
+  "qualityProfiles": [
+    {
+      "key": "qp1",
+      "name": "Sonar Way Java",
+      "language": "java"
+    },
+    {
+      "key": "qp2",
+      "name": "Sonar Way Xoo",
+      "language": "xoo"
+    }
+  ],
+  "qualityGate": {
+    "key": "BCDE",
+    "name": "Sonar way",
+    "isDefault": false
+  },
+  "configuration": {
+    "showSettings": true,
+    "showQualityProfiles": true,
+    "showQualityGates": true,
+    "showManualMeasures": true,
+    "showLinks": true,
+    "showPermissions": true,
+    "showHistory": true,
+    "showUpdateKey": true,
+    "showBackgroundTasks": true,
+    "extensions": []
+  },
+  "breadcrumbs": [
+    {
+      "key": "org.codehaus.sonar:sonar",
+      "name": "Sonarqube",
+      "qualifier": "TRK"
+    }
+  ]
+}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/ui/ws/example-component.json b/server/sonar-server/src/main/resources/org/sonar/server/ui/ws/example-component.json
deleted file mode 100644 (file)
index 40878b2..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-{
-  "key": "org.codehaus.sonar:sonar",
-  "id": "ABCD",
-  "name": "Sonarqube",
-  "description": "Open source platform for continuous inspection of code quality",
-  "isFavorite": true,
-  "version": "6.3",
-  "snapshotDate": "2016-12-06T11:44:00+0200",
-  "extensions": [
-    {
-      "id": "/admin/page",
-      "name": "Admin Page"
-    },
-    {
-      "id": "first_page",
-      "name": "First Page"
-    },
-    {
-      "id": "/second/page",
-      "name": "Second Page"
-    }
-  ],
-  "qualityProfiles": [
-    {
-      "key": "qp1",
-      "name": "Sonar Way Java",
-      "language": "java"
-    },
-    {
-      "key": "qp2",
-      "name": "Sonar Way Xoo",
-      "language": "xoo"
-    }
-  ],
-  "qualityGate": {
-    "key": "BCDE",
-    "name": "Sonar way",
-    "isDefault": false
-  },
-  "configuration": {
-    "showSettings": true,
-    "showQualityProfiles": true,
-    "showQualityGates": true,
-    "showManualMeasures": true,
-    "showLinks": true,
-    "showPermissions": true,
-    "showHistory": true,
-    "showUpdateKey": true,
-    "showBackgroundTasks": true,
-    "extensions": []
-  },
-  "breadcrumbs": [
-    {
-      "key": "org.codehaus.sonar:sonar",
-      "name": "Sonarqube",
-      "qualifier": "TRK"
-    }
-  ]
-}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/ui/ws/example-global.json b/server/sonar-server/src/main/resources/org/sonar/server/ui/ws/example-global.json
deleted file mode 100644 (file)
index 79d5a43..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-{
-  "globalPages": [
-    {
-      "id": "my_plugin_page",
-      "name": "My Plugin Page"
-    },
-    {
-      "id": "my_rails_app",
-      "name": "My Rails App"
-    }
-  ],
-  "settings": {
-    "sonar.lf.logoUrl": "http://example.com/my-custom-logo.png",
-    "sonar.lf.logoWidthPx": "135",
-    "sonar.lf.enableGravatar": "true",
-    "sonar.lf.gravatarServerUrl": "http://some-server.tld/logo.png",
-    "sonar.updatecenter.activate": "false",
-    "sonar.technicalDebt.hoursInDay": "10",
-    "sonar.technicalDebt.ratingGrid": "0.05,0.1,0.2,0.5",
-    "sonar.allowUsersToSignUp": "true"
-  },
-  "logoUrl": "http://example.com/my-custom-logo.png",
-  "logoWidth": "135",
-  "qualifiers": [
-    "PAL",
-    "POL"
-  ],
-  "version": "6.2",
-  "productionDatabase": true
-}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/ui/ws/example-settings.json b/server/sonar-server/src/main/resources/org/sonar/server/ui/ws/example-settings.json
deleted file mode 100644 (file)
index 383b5e0..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-  "showUpdateCenter": true,
-  "extensions": [
-    {
-      "name": "Views",
-      "url": "/plugins/configuration/views"
-    }
-  ]
-}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/ui/ws/global-example.json b/server/sonar-server/src/main/resources/org/sonar/server/ui/ws/global-example.json
new file mode 100644 (file)
index 0000000..79d5a43
--- /dev/null
@@ -0,0 +1,30 @@
+{
+  "globalPages": [
+    {
+      "id": "my_plugin_page",
+      "name": "My Plugin Page"
+    },
+    {
+      "id": "my_rails_app",
+      "name": "My Rails App"
+    }
+  ],
+  "settings": {
+    "sonar.lf.logoUrl": "http://example.com/my-custom-logo.png",
+    "sonar.lf.logoWidthPx": "135",
+    "sonar.lf.enableGravatar": "true",
+    "sonar.lf.gravatarServerUrl": "http://some-server.tld/logo.png",
+    "sonar.updatecenter.activate": "false",
+    "sonar.technicalDebt.hoursInDay": "10",
+    "sonar.technicalDebt.ratingGrid": "0.05,0.1,0.2,0.5",
+    "sonar.allowUsersToSignUp": "true"
+  },
+  "logoUrl": "http://example.com/my-custom-logo.png",
+  "logoWidth": "135",
+  "qualifiers": [
+    "PAL",
+    "POL"
+  ],
+  "version": "6.2",
+  "productionDatabase": true
+}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/ui/ws/settings-example.json b/server/sonar-server/src/main/resources/org/sonar/server/ui/ws/settings-example.json
new file mode 100644 (file)
index 0000000..383b5e0
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  "showUpdateCenter": true,
+  "extensions": [
+    {
+      "name": "Views",
+      "url": "/plugins/configuration/views"
+    }
+  ]
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/ui/ws/ComponentActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/ui/ws/ComponentActionTest.java
new file mode 100644 (file)
index 0000000..49349b3
--- /dev/null
@@ -0,0 +1,474 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.ui.ws;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.i18n.I18n;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.ResourceType;
+import org.sonar.api.resources.ResourceTypes;
+import org.sonar.api.resources.Scopes;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.System2;
+import org.sonar.api.web.NavigationSection;
+import org.sonar.api.web.Page;
+import org.sonar.api.web.ResourceLanguage;
+import org.sonar.api.web.ResourceQualifier;
+import org.sonar.api.web.ResourceScope;
+import org.sonar.api.web.UserRole;
+import org.sonar.api.web.View;
+import org.sonar.core.component.DefaultResourceTypes;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.SnapshotDto;
+import org.sonar.db.metric.MetricDto;
+import org.sonar.db.property.PropertyDbTester;
+import org.sonar.db.property.PropertyDto;
+import org.sonar.db.qualitygate.QualityGateDto;
+import org.sonar.db.user.UserDbTester;
+import org.sonar.db.user.UserDto;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.qualitygate.QualityGateFinder;
+import org.sonar.server.qualityprofile.QPMeasureData;
+import org.sonar.server.qualityprofile.QualityProfile;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ui.Views;
+import org.sonar.server.ws.WsActionTester;
+
+import static java.util.Locale.ENGLISH;
+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.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.api.measures.CoreMetrics.QUALITY_PROFILES_KEY;
+import static org.sonar.core.permission.GlobalPermissions.QUALITY_PROFILE_ADMIN;
+import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
+import static org.sonar.db.component.ComponentTesting.newDirectory;
+import static org.sonar.db.component.ComponentTesting.newFileDto;
+import static org.sonar.db.component.ComponentTesting.newModuleDto;
+import static org.sonar.db.component.ComponentTesting.newProjectDto;
+import static org.sonar.db.component.SnapshotTesting.newAnalysis;
+import static org.sonar.db.measure.MeasureTesting.newMeasureDto;
+import static org.sonar.db.metric.MetricTesting.newMetricDto;
+import static org.sonar.test.JsonAssert.assertJson;
+
+public class ComponentActionTest {
+
+  private static final String PROJECT_KEY = "polop";
+  private static final ComponentDto PROJECT = newProjectDto("abcd")
+    .setKey(PROJECT_KEY)
+    .setName("Polop")
+    .setDescription("test project")
+    .setLanguage("xoo");
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  @Rule
+  public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+
+  private DbClient dbClient = dbTester.getDbClient();
+  private ComponentDbTester componentDbTester = dbTester.components();
+  private UserDbTester userDbTester = dbTester.users();
+  private PropertyDbTester propertyDbTester = new PropertyDbTester(dbTester);
+
+  private I18n i18n = mock(I18n.class);
+
+  private ResourceTypes resourceTypes = mock(ResourceTypes.class);
+
+  private WsActionTester ws;
+
+  @Before
+  public void before() {
+    when(i18n.message(eq(ENGLISH), any(String.class), any(String.class)))
+      .thenAnswer(invocation -> invocation.getArgumentAt(2, String.class));
+  }
+
+  @Test
+  public void fail_on_missing_parameters() throws Exception {
+    init();
+
+    expectedException.expect(IllegalArgumentException.class);
+    ws.newRequest().execute();
+  }
+
+  @Test
+  public void fail_on_unknown_component_key() throws Exception {
+    init();
+
+    expectedException.expect(NotFoundException.class);
+    execute(PROJECT.key());
+  }
+
+  @Test
+  public void fail_on_missing_permission() throws Exception {
+    init();
+    componentDbTester.insertComponent(PROJECT);
+
+    expectedException.expect(ForbiddenException.class);
+    execute(PROJECT.key());
+  }
+
+  @Test
+  public void return_component_info_when_anonymous_no_snapshot() throws Exception {
+    init();
+    componentDbTester.insertComponent(PROJECT);
+    userSessionRule.addProjectUuidPermissions(UserRole.USER, PROJECT.uuid());
+
+    executeAndVerify(PROJECT.key(), "return_component_info_when_anonymous_no_snapshot.json");
+  }
+
+  @Test
+  public void return_component_info_with_favourite() throws Exception {
+    init();
+    UserDto user = userDbTester.insertUser("obiwan");
+    componentDbTester.insertComponent(PROJECT);
+    propertyDbTester.insertProperty(new PropertyDto().setKey("favourite").setResourceId(PROJECT.getId()).setUserId(user.getId()));
+    userSessionRule.login(user).addProjectUuidPermissions(UserRole.USER, PROJECT.uuid());
+
+    executeAndVerify(PROJECT.key(), "return_component_info_with_favourite.json");
+  }
+
+  @Test
+  public void return_component_info_when_snapshot() throws Exception {
+    init();
+    componentDbTester.insertComponent(PROJECT);
+    componentDbTester.insertSnapshot(newAnalysis(PROJECT)
+      .setCreatedAt(DateUtils.parseDateTime("2015-04-22T11:44:00+0200").getTime())
+      .setVersion("3.14")
+      .setLast(true));
+    userSessionRule.addProjectUuidPermissions(UserRole.USER, PROJECT.uuid());
+
+    executeAndVerify(PROJECT.key(), "return_component_info_when_snapshot.json");
+  }
+
+  @Test
+  public void return_quality_profiles() throws Exception {
+    init();
+    componentDbTester.insertComponent(PROJECT);
+    SnapshotDto analysis = componentDbTester.insertSnapshot(newAnalysis(PROJECT));
+    addQualityProfiles(PROJECT, analysis,
+      createQProfile("qp1", "Sonar Way Java", "java"),
+      createQProfile("qp2", "Sonar Way Xoo", "xoo"));
+    userSessionRule.addProjectUuidPermissions(UserRole.USER, PROJECT.uuid());
+
+    executeAndVerify(PROJECT.key(), "return_quality_profiles.json");
+  }
+
+  @Test
+  public void return_empty_quality_profiles_when_no_measure() throws Exception {
+    init();
+    componentDbTester.insertComponent(PROJECT);
+    userSessionRule.addProjectUuidPermissions(UserRole.USER, PROJECT.uuid());
+
+    executeAndVerify(PROJECT.key(), "return_empty_quality_profiles_when_no_measure.json");
+  }
+
+  @Test
+  public void return_quality_gate_defined_on_project() throws Exception {
+    init();
+    componentDbTester.insertComponent(PROJECT);
+    QualityGateDto qualityGateDto = dbTester.qualityGates().insertQualityGate("Sonar way");
+    dbTester.qualityGates().associateProjectToQualityGate(PROJECT, qualityGateDto);
+    userSessionRule.addProjectUuidPermissions(UserRole.USER, PROJECT.uuid());
+
+    executeAndVerify(PROJECT.key(), "return_quality_gate.json");
+  }
+
+  @Test
+  public void return_default_quality_gate() throws Exception {
+    init();
+    componentDbTester.insertComponent(PROJECT);
+    dbTester.qualityGates().createDefaultQualityGate("Sonar way");
+    userSessionRule.addProjectUuidPermissions(UserRole.USER, PROJECT.uuid());
+
+    executeAndVerify(PROJECT.key(), "return_default_quality_gate.json");
+  }
+
+  @Test
+  public void return_no_quality_gate_when_not_defined_on_project_and_no_default_one() throws Exception {
+    init();
+    componentDbTester.insertComponent(PROJECT);
+    userSessionRule.addProjectUuidPermissions(UserRole.USER, PROJECT.uuid());
+
+    String json = execute(PROJECT.key());
+    assertThat(json).doesNotContain("qualityGate");
+  }
+
+  @Test
+  public void return_extensions() throws Exception {
+    init(createViews());
+    componentDbTester.insertProjectAndSnapshot(PROJECT);
+    userSessionRule.anonymous().addProjectUuidPermissions(UserRole.USER, PROJECT.uuid());
+
+    executeAndVerify(PROJECT.key(), "return_extensions.json");
+  }
+
+  @Test
+  public void return_extensions_for_admin() throws Exception {
+    init(createViews());
+    componentDbTester.insertProjectAndSnapshot(PROJECT);
+    userSessionRule.anonymous()
+      .addProjectUuidPermissions(UserRole.USER, PROJECT.uuid())
+      .addProjectUuidPermissions(UserRole.ADMIN, PROJECT.uuid());
+
+    executeAndVerify(PROJECT.key(), "return_extensions_for_admin.json");
+  }
+
+  @Test
+  public void return_configuration_for_admin() throws Exception {
+    UserDto user = userDbTester.insertUser();
+    componentDbTester.insertComponent(PROJECT);
+    userSessionRule.login(user)
+      .addProjectUuidPermissions(UserRole.USER, "abcd")
+      .addProjectUuidPermissions(UserRole.ADMIN, "abcd");
+
+    @NavigationSection(NavigationSection.RESOURCE_CONFIGURATION)
+    @ResourceScope(Scopes.PROJECT)
+    @ResourceQualifier(Qualifiers.PROJECT)
+    @ResourceLanguage("xoo")
+    class FirstPage implements Page {
+      @Override
+      public String getTitle() {
+        return "First Page";
+      }
+
+      @Override
+      public String getId() {
+        return "first_page";
+      }
+    }
+
+    @NavigationSection(NavigationSection.RESOURCE_CONFIGURATION)
+    @ResourceScope(Scopes.PROJECT)
+    @ResourceQualifier(Qualifiers.PROJECT)
+    @ResourceLanguage("xoo")
+    class SecondPage implements Page {
+      @Override
+      public String getTitle() {
+        return "Second Page";
+      }
+
+      @Override
+      public String getId() {
+        return "/second/page";
+      }
+    }
+
+    init(new Page[] {new FirstPage(), new SecondPage()});
+    executeAndVerify(PROJECT.key(), "return_configuration_for_admin.json");
+  }
+
+  @Test
+  public void return_configuration_with_all_properties() throws Exception {
+    init();
+    componentDbTester.insertComponent(PROJECT);
+    userSessionRule.anonymous()
+      .addProjectUuidPermissions(UserRole.USER, "abcd")
+      .addProjectUuidPermissions(UserRole.ADMIN, "abcd");
+
+    ResourceType projectResourceType = ResourceType.builder(PROJECT.qualifier())
+      .setProperty("comparable", true)
+      .setProperty("configurable", true)
+      .setProperty("hasRolePolicy", true)
+      .setProperty("modifiable_history", true)
+      .setProperty("updatable_key", true)
+      .setProperty("deletable", true)
+      .build();
+    when(resourceTypes.get(PROJECT.qualifier()))
+      .thenReturn(projectResourceType);
+
+    executeAndVerify(PROJECT.key(), "return_configuration_with_all_properties.json");
+  }
+
+  @Test
+  public void return_breadcrumbs_on_module() throws Exception {
+    init();
+    ComponentDto project = componentDbTester.insertComponent(PROJECT);
+    ComponentDto module = componentDbTester.insertComponent(newModuleDto("bcde", project).setKey("palap").setName("Palap"));
+    userSessionRule.anonymous()
+      .addProjectUuidPermissions(UserRole.USER, "abcd")
+      .addProjectUuidPermissions(UserRole.ADMIN, "abcd");
+
+    executeAndVerify(module.key(), "return_breadcrumbs_on_module.json");
+  }
+
+  @Test
+  public void return_configuration_for_quality_profile_admin() throws Exception {
+    init();
+    componentDbTester.insertComponent(PROJECT);
+    userSessionRule.anonymous()
+      .addProjectUuidPermissions(UserRole.USER, "abcd")
+      .setGlobalPermissions(QUALITY_PROFILE_ADMIN);
+
+    executeAndVerify(PROJECT.key(), "return_configuration_for_quality_profile_admin.json");
+  }
+
+  @Test
+  public void return_bread_crumbs_on_several_levels() throws Exception {
+    init();
+    ComponentDto project = componentDbTester.insertComponent(PROJECT);
+    ComponentDto module = componentDbTester.insertComponent(newModuleDto("bcde", project).setKey("palap").setName("Palap"));
+    ComponentDto directory = componentDbTester.insertComponent(newDirectory(module, "src/main/xoo"));
+    ComponentDto file = componentDbTester.insertComponent(newFileDto(directory, directory, "cdef").setName("Source.xoo")
+      .setKey("palap:src/main/xoo/Source.xoo")
+      .setPath(directory.path()));
+    userSessionRule.addProjectUuidPermissions(UserRole.USER, project.uuid());
+
+    executeAndVerify(file.key(), "return_bread_crumbs_on_several_levels.json");
+  }
+
+  @Test
+  public void work_with_only_system_admin() throws Exception {
+    init(createViews());
+    componentDbTester.insertProjectAndSnapshot(PROJECT);
+    userSessionRule.setGlobalPermissions(SYSTEM_ADMIN);
+
+    execute(PROJECT.key());
+  }
+
+  @Test
+  public void test_example_response() throws Exception {
+    init(createViews());
+    ComponentDto project = newProjectDto("ABCD").setKey("org.codehaus.sonar:sonar").setName("Sonarqube").setDescription("Open source platform for continuous inspection of code quality");
+    componentDbTester.insertComponent(project);
+    SnapshotDto analysis = newAnalysis(project)
+      .setCreatedAt(DateUtils.parseDateTime("2016-12-06T11:44:00+0200").getTime())
+      .setVersion("6.3")
+      .setLast(true);
+    componentDbTester.insertSnapshot(analysis);
+    when(resourceTypes.get(project.qualifier())).thenReturn(DefaultResourceTypes.get().getRootType());
+    UserDto user = userDbTester.insertUser("obiwan");
+    propertyDbTester.insertProperty(new PropertyDto().setKey("favourite").setResourceId(project.getId()).setUserId(user.getId()));
+    addQualityProfiles(project, analysis,
+      createQProfile("qp1", "Sonar Way Java", "java"),
+      createQProfile("qp2", "Sonar Way Xoo", "xoo"));
+    QualityGateDto qualityGateDto = dbTester.qualityGates().insertQualityGate("Sonar way");
+    dbTester.qualityGates().associateProjectToQualityGate(project, qualityGateDto);
+    userSessionRule.login(user).addProjectUuidPermissions(UserRole.ADMIN, project.uuid());
+
+    String result = execute(project.key());
+    assertJson(ws.getDef().responseExampleAsString()).ignoreFields("snapshotDate", "key").isSimilarTo(result);
+  }
+
+  private void init(View... views) {
+    ws = new WsActionTester(new ComponentAction(dbClient, new Views(userSessionRule, views), i18n, resourceTypes, userSessionRule, new ComponentFinder(dbClient),
+      new QualityGateFinder(dbClient)));
+  }
+
+  private String execute(String componentKey) {
+    return ws.newRequest().setParam("componentKey", componentKey).execute().getInput();
+  }
+
+  private void verify(String json, String expectedJson) {
+    assertJson(json).isSimilarTo(getClass().getResource(ComponentActionTest.class.getSimpleName() + "/" + expectedJson));
+  }
+
+  private void executeAndVerify(String componentKey, String expectedJson) {
+    verify(execute(componentKey), expectedJson);
+  }
+
+  private void addQualityProfiles(ComponentDto project, SnapshotDto analysis, QualityProfile... qps) {
+    MetricDto metricDto = newMetricDto().setKey(QUALITY_PROFILES_KEY);
+    dbClient.metricDao().insert(dbTester.getSession(), metricDto);
+    dbClient.measureDao().insert(dbTester.getSession(),
+      newMeasureDto(metricDto, project, analysis)
+        .setData(qualityProfilesToJson(qps)));
+    dbTester.commit();
+  }
+
+  private static QualityProfile createQProfile(String qpKey, String qpName, String languageKey) {
+    return new QualityProfile(qpKey, qpName, languageKey, new Date());
+  }
+
+  private static String qualityProfilesToJson(QualityProfile... qps) {
+    List<QualityProfile> qualityProfiles = Arrays.asList(qps);
+    return QPMeasureData.toJson(new QPMeasureData(qualityProfiles));
+  }
+
+  private View[] createViews() {
+    @NavigationSection(NavigationSection.RESOURCE)
+    @ResourceScope(Scopes.PROJECT)
+    @ResourceQualifier(Qualifiers.PROJECT)
+    @ResourceLanguage("xoo")
+    class FirstPage implements Page {
+      @Override
+      public String getTitle() {
+        return "First Page";
+      }
+
+      @Override
+      public String getId() {
+        return "first_page";
+      }
+    }
+    Page page1 = new FirstPage();
+
+    @NavigationSection(NavigationSection.RESOURCE)
+    @ResourceScope(Scopes.PROJECT)
+    @ResourceQualifier(Qualifiers.PROJECT)
+    @ResourceLanguage("xoo")
+    class SecondPage implements Page {
+      @Override
+      public String getTitle() {
+        return "Second Page";
+      }
+
+      @Override
+      public String getId() {
+        return "/second/page";
+      }
+    }
+    Page page2 = new SecondPage();
+
+    @NavigationSection(NavigationSection.RESOURCE)
+    @ResourceScope(Scopes.PROJECT)
+    @ResourceQualifier(Qualifiers.PROJECT)
+    @ResourceLanguage("xoo")
+    @UserRole(UserRole.ADMIN)
+    class AdminPage implements Page {
+      @Override
+      public String getTitle() {
+        return "Admin Page";
+      }
+
+      @Override
+      public String getId() {
+        return "/admin/page";
+      }
+    }
+    Page adminPage = new AdminPage();
+    return new Page[] {page1, page2, adminPage};
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/ui/ws/ComponentNavigationActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/ui/ws/ComponentNavigationActionTest.java
deleted file mode 100644 (file)
index a01eb4a..0000000
+++ /dev/null
@@ -1,474 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.ui.ws;
-
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.i18n.I18n;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.ResourceType;
-import org.sonar.api.resources.ResourceTypes;
-import org.sonar.api.resources.Scopes;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.api.utils.System2;
-import org.sonar.api.web.NavigationSection;
-import org.sonar.api.web.Page;
-import org.sonar.api.web.ResourceLanguage;
-import org.sonar.api.web.ResourceQualifier;
-import org.sonar.api.web.ResourceScope;
-import org.sonar.api.web.UserRole;
-import org.sonar.api.web.View;
-import org.sonar.core.component.DefaultResourceTypes;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbTester;
-import org.sonar.db.component.ComponentDbTester;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.SnapshotDto;
-import org.sonar.db.metric.MetricDto;
-import org.sonar.db.property.PropertyDbTester;
-import org.sonar.db.property.PropertyDto;
-import org.sonar.db.qualitygate.QualityGateDto;
-import org.sonar.db.user.UserDbTester;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.component.ComponentFinder;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.qualitygate.QualityGateFinder;
-import org.sonar.server.qualityprofile.QPMeasureData;
-import org.sonar.server.qualityprofile.QualityProfile;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ui.Views;
-import org.sonar.server.ws.WsActionTester;
-
-import static java.util.Locale.ENGLISH;
-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.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.api.measures.CoreMetrics.QUALITY_PROFILES_KEY;
-import static org.sonar.core.permission.GlobalPermissions.QUALITY_PROFILE_ADMIN;
-import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
-import static org.sonar.db.component.ComponentTesting.newDirectory;
-import static org.sonar.db.component.ComponentTesting.newFileDto;
-import static org.sonar.db.component.ComponentTesting.newModuleDto;
-import static org.sonar.db.component.ComponentTesting.newProjectDto;
-import static org.sonar.db.component.SnapshotTesting.newAnalysis;
-import static org.sonar.db.measure.MeasureTesting.newMeasureDto;
-import static org.sonar.db.metric.MetricTesting.newMetricDto;
-import static org.sonar.test.JsonAssert.assertJson;
-
-public class ComponentNavigationActionTest {
-
-  private static final String PROJECT_KEY = "polop";
-  private static final ComponentDto PROJECT = newProjectDto("abcd")
-    .setKey(PROJECT_KEY)
-    .setName("Polop")
-    .setDescription("test project")
-    .setLanguage("xoo");
-
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  @Rule
-  public DbTester dbTester = DbTester.create(System2.INSTANCE);
-
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
-
-  private DbClient dbClient = dbTester.getDbClient();
-  private ComponentDbTester componentDbTester = dbTester.components();
-  private UserDbTester userDbTester = dbTester.users();
-  private PropertyDbTester propertyDbTester = new PropertyDbTester(dbTester);
-
-  private I18n i18n = mock(I18n.class);
-
-  private ResourceTypes resourceTypes = mock(ResourceTypes.class);
-
-  private WsActionTester ws;
-
-  @Before
-  public void before() {
-    when(i18n.message(eq(ENGLISH), any(String.class), any(String.class)))
-      .thenAnswer(invocation -> invocation.getArgumentAt(2, String.class));
-  }
-
-  @Test
-  public void fail_on_missing_parameters() throws Exception {
-    init();
-
-    expectedException.expect(IllegalArgumentException.class);
-    ws.newRequest().execute();
-  }
-
-  @Test
-  public void fail_on_unknown_component_key() throws Exception {
-    init();
-
-    expectedException.expect(NotFoundException.class);
-    execute(PROJECT.key());
-  }
-
-  @Test
-  public void fail_on_missing_permission() throws Exception {
-    init();
-    componentDbTester.insertComponent(PROJECT);
-
-    expectedException.expect(ForbiddenException.class);
-    execute(PROJECT.key());
-  }
-
-  @Test
-  public void return_component_info_when_anonymous_no_snapshot() throws Exception {
-    init();
-    componentDbTester.insertComponent(PROJECT);
-    userSessionRule.addProjectUuidPermissions(UserRole.USER, PROJECT.uuid());
-
-    executeAndVerify(PROJECT.key(), "return_component_info_when_anonymous_no_snapshot.json");
-  }
-
-  @Test
-  public void return_component_info_with_favourite() throws Exception {
-    init();
-    UserDto user = userDbTester.insertUser("obiwan");
-    componentDbTester.insertComponent(PROJECT);
-    propertyDbTester.insertProperty(new PropertyDto().setKey("favourite").setResourceId(PROJECT.getId()).setUserId(user.getId()));
-    userSessionRule.login(user).addProjectUuidPermissions(UserRole.USER, PROJECT.uuid());
-
-    executeAndVerify(PROJECT.key(), "return_component_info_with_favourite.json");
-  }
-
-  @Test
-  public void return_component_info_when_snapshot() throws Exception {
-    init();
-    componentDbTester.insertComponent(PROJECT);
-    componentDbTester.insertSnapshot(newAnalysis(PROJECT)
-      .setCreatedAt(DateUtils.parseDateTime("2015-04-22T11:44:00+0200").getTime())
-      .setVersion("3.14")
-      .setLast(true));
-    userSessionRule.addProjectUuidPermissions(UserRole.USER, PROJECT.uuid());
-
-    executeAndVerify(PROJECT.key(), "return_component_info_when_snapshot.json");
-  }
-
-  @Test
-  public void return_quality_profiles() throws Exception {
-    init();
-    componentDbTester.insertComponent(PROJECT);
-    SnapshotDto analysis = componentDbTester.insertSnapshot(newAnalysis(PROJECT));
-    addQualityProfiles(PROJECT, analysis,
-      createQProfile("qp1", "Sonar Way Java", "java"),
-      createQProfile("qp2", "Sonar Way Xoo", "xoo"));
-    userSessionRule.addProjectUuidPermissions(UserRole.USER, PROJECT.uuid());
-
-    executeAndVerify(PROJECT.key(), "return_quality_profiles.json");
-  }
-
-  @Test
-  public void return_empty_quality_profiles_when_no_measure() throws Exception {
-    init();
-    componentDbTester.insertComponent(PROJECT);
-    userSessionRule.addProjectUuidPermissions(UserRole.USER, PROJECT.uuid());
-
-    executeAndVerify(PROJECT.key(), "return_empty_quality_profiles_when_no_measure.json");
-  }
-
-  @Test
-  public void return_quality_gate_defined_on_project() throws Exception {
-    init();
-    componentDbTester.insertComponent(PROJECT);
-    QualityGateDto qualityGateDto = dbTester.qualityGates().insertQualityGate("Sonar way");
-    dbTester.qualityGates().associateProjectToQualityGate(PROJECT, qualityGateDto);
-    userSessionRule.addProjectUuidPermissions(UserRole.USER, PROJECT.uuid());
-
-    executeAndVerify(PROJECT.key(), "return_quality_gate.json");
-  }
-
-  @Test
-  public void return_default_quality_gate() throws Exception {
-    init();
-    componentDbTester.insertComponent(PROJECT);
-    dbTester.qualityGates().createDefaultQualityGate("Sonar way");
-    userSessionRule.addProjectUuidPermissions(UserRole.USER, PROJECT.uuid());
-
-    executeAndVerify(PROJECT.key(), "return_default_quality_gate.json");
-  }
-
-  @Test
-  public void return_no_quality_gate_when_not_defined_on_project_and_no_default_one() throws Exception {
-    init();
-    componentDbTester.insertComponent(PROJECT);
-    userSessionRule.addProjectUuidPermissions(UserRole.USER, PROJECT.uuid());
-
-    String json = execute(PROJECT.key());
-    assertThat(json).doesNotContain("qualityGate");
-  }
-
-  @Test
-  public void return_extensions() throws Exception {
-    init(createViews());
-    componentDbTester.insertProjectAndSnapshot(PROJECT);
-    userSessionRule.anonymous().addProjectUuidPermissions(UserRole.USER, PROJECT.uuid());
-
-    executeAndVerify(PROJECT.key(), "return_extensions.json");
-  }
-
-  @Test
-  public void return_extensions_for_admin() throws Exception {
-    init(createViews());
-    componentDbTester.insertProjectAndSnapshot(PROJECT);
-    userSessionRule.anonymous()
-      .addProjectUuidPermissions(UserRole.USER, PROJECT.uuid())
-      .addProjectUuidPermissions(UserRole.ADMIN, PROJECT.uuid());
-
-    executeAndVerify(PROJECT.key(), "return_extensions_for_admin.json");
-  }
-
-  @Test
-  public void return_configuration_for_admin() throws Exception {
-    UserDto user = userDbTester.insertUser();
-    componentDbTester.insertComponent(PROJECT);
-    userSessionRule.login(user)
-      .addProjectUuidPermissions(UserRole.USER, "abcd")
-      .addProjectUuidPermissions(UserRole.ADMIN, "abcd");
-
-    @NavigationSection(NavigationSection.RESOURCE_CONFIGURATION)
-    @ResourceScope(Scopes.PROJECT)
-    @ResourceQualifier(Qualifiers.PROJECT)
-    @ResourceLanguage("xoo")
-    class FirstPage implements Page {
-      @Override
-      public String getTitle() {
-        return "First Page";
-      }
-
-      @Override
-      public String getId() {
-        return "first_page";
-      }
-    }
-
-    @NavigationSection(NavigationSection.RESOURCE_CONFIGURATION)
-    @ResourceScope(Scopes.PROJECT)
-    @ResourceQualifier(Qualifiers.PROJECT)
-    @ResourceLanguage("xoo")
-    class SecondPage implements Page {
-      @Override
-      public String getTitle() {
-        return "Second Page";
-      }
-
-      @Override
-      public String getId() {
-        return "/second/page";
-      }
-    }
-
-    init(new Page[] {new FirstPage(), new SecondPage()});
-    executeAndVerify(PROJECT.key(), "return_configuration_for_admin.json");
-  }
-
-  @Test
-  public void return_configuration_with_all_properties() throws Exception {
-    init();
-    componentDbTester.insertComponent(PROJECT);
-    userSessionRule.anonymous()
-      .addProjectUuidPermissions(UserRole.USER, "abcd")
-      .addProjectUuidPermissions(UserRole.ADMIN, "abcd");
-
-    ResourceType projectResourceType = ResourceType.builder(PROJECT.qualifier())
-      .setProperty("comparable", true)
-      .setProperty("configurable", true)
-      .setProperty("hasRolePolicy", true)
-      .setProperty("modifiable_history", true)
-      .setProperty("updatable_key", true)
-      .setProperty("deletable", true)
-      .build();
-    when(resourceTypes.get(PROJECT.qualifier()))
-      .thenReturn(projectResourceType);
-
-    executeAndVerify(PROJECT.key(), "return_configuration_with_all_properties.json");
-  }
-
-  @Test
-  public void return_breadcrumbs_on_module() throws Exception {
-    init();
-    ComponentDto project = componentDbTester.insertComponent(PROJECT);
-    ComponentDto module = componentDbTester.insertComponent(newModuleDto("bcde", project).setKey("palap").setName("Palap"));
-    userSessionRule.anonymous()
-      .addProjectUuidPermissions(UserRole.USER, "abcd")
-      .addProjectUuidPermissions(UserRole.ADMIN, "abcd");
-
-    executeAndVerify(module.key(), "return_breadcrumbs_on_module.json");
-  }
-
-  @Test
-  public void return_configuration_for_quality_profile_admin() throws Exception {
-    init();
-    componentDbTester.insertComponent(PROJECT);
-    userSessionRule.anonymous()
-      .addProjectUuidPermissions(UserRole.USER, "abcd")
-      .setGlobalPermissions(QUALITY_PROFILE_ADMIN);
-
-    executeAndVerify(PROJECT.key(), "return_configuration_for_quality_profile_admin.json");
-  }
-
-  @Test
-  public void return_bread_crumbs_on_several_levels() throws Exception {
-    init();
-    ComponentDto project = componentDbTester.insertComponent(PROJECT);
-    ComponentDto module = componentDbTester.insertComponent(newModuleDto("bcde", project).setKey("palap").setName("Palap"));
-    ComponentDto directory = componentDbTester.insertComponent(newDirectory(module, "src/main/xoo"));
-    ComponentDto file = componentDbTester.insertComponent(newFileDto(directory, directory, "cdef").setName("Source.xoo")
-      .setKey("palap:src/main/xoo/Source.xoo")
-      .setPath(directory.path()));
-    userSessionRule.addProjectUuidPermissions(UserRole.USER, project.uuid());
-
-    executeAndVerify(file.key(), "return_bread_crumbs_on_several_levels.json");
-  }
-
-  @Test
-  public void work_with_only_system_admin() throws Exception {
-    init(createViews());
-    componentDbTester.insertProjectAndSnapshot(PROJECT);
-    userSessionRule.setGlobalPermissions(SYSTEM_ADMIN);
-
-    execute(PROJECT.key());
-  }
-
-  @Test
-  public void test_example_response() throws Exception {
-    init(createViews());
-    ComponentDto project = newProjectDto("ABCD").setKey("org.codehaus.sonar:sonar").setName("Sonarqube").setDescription("Open source platform for continuous inspection of code quality");
-    componentDbTester.insertComponent(project);
-    SnapshotDto analysis = newAnalysis(project)
-      .setCreatedAt(DateUtils.parseDateTime("2016-12-06T11:44:00+0200").getTime())
-      .setVersion("6.3")
-      .setLast(true);
-    componentDbTester.insertSnapshot(analysis);
-    when(resourceTypes.get(project.qualifier())).thenReturn(DefaultResourceTypes.get().getRootType());
-    UserDto user = userDbTester.insertUser("obiwan");
-    propertyDbTester.insertProperty(new PropertyDto().setKey("favourite").setResourceId(project.getId()).setUserId(user.getId()));
-    addQualityProfiles(project, analysis,
-      createQProfile("qp1", "Sonar Way Java", "java"),
-      createQProfile("qp2", "Sonar Way Xoo", "xoo"));
-    QualityGateDto qualityGateDto = dbTester.qualityGates().insertQualityGate("Sonar way");
-    dbTester.qualityGates().associateProjectToQualityGate(project, qualityGateDto);
-    userSessionRule.login(user).addProjectUuidPermissions(UserRole.ADMIN, project.uuid());
-
-    String result = execute(project.key());
-    assertJson(ws.getDef().responseExampleAsString()).ignoreFields("snapshotDate", "key").isSimilarTo(result);
-  }
-
-  private void init(View... views) {
-    ws = new WsActionTester(new ComponentNavigationAction(dbClient, new Views(userSessionRule, views), i18n, resourceTypes, userSessionRule, new ComponentFinder(dbClient),
-      new QualityGateFinder(dbClient)));
-  }
-
-  private String execute(String componentKey) {
-    return ws.newRequest().setParam("componentKey", componentKey).execute().getInput();
-  }
-
-  private void verify(String json, String expectedJson) {
-    assertJson(json).isSimilarTo(getClass().getResource(ComponentNavigationActionTest.class.getSimpleName() + "/" + expectedJson));
-  }
-
-  private void executeAndVerify(String componentKey, String expectedJson) {
-    verify(execute(componentKey), expectedJson);
-  }
-
-  private void addQualityProfiles(ComponentDto project, SnapshotDto analysis, QualityProfile... qps) {
-    MetricDto metricDto = newMetricDto().setKey(QUALITY_PROFILES_KEY);
-    dbClient.metricDao().insert(dbTester.getSession(), metricDto);
-    dbClient.measureDao().insert(dbTester.getSession(),
-      newMeasureDto(metricDto, project, analysis)
-        .setData(qualityProfilesToJson(qps)));
-    dbTester.commit();
-  }
-
-  private static QualityProfile createQProfile(String qpKey, String qpName, String languageKey) {
-    return new QualityProfile(qpKey, qpName, languageKey, new Date());
-  }
-
-  private static String qualityProfilesToJson(QualityProfile... qps) {
-    List<QualityProfile> qualityProfiles = Arrays.asList(qps);
-    return QPMeasureData.toJson(new QPMeasureData(qualityProfiles));
-  }
-
-  private View[] createViews() {
-    @NavigationSection(NavigationSection.RESOURCE)
-    @ResourceScope(Scopes.PROJECT)
-    @ResourceQualifier(Qualifiers.PROJECT)
-    @ResourceLanguage("xoo")
-    class FirstPage implements Page {
-      @Override
-      public String getTitle() {
-        return "First Page";
-      }
-
-      @Override
-      public String getId() {
-        return "first_page";
-      }
-    }
-    Page page1 = new FirstPage();
-
-    @NavigationSection(NavigationSection.RESOURCE)
-    @ResourceScope(Scopes.PROJECT)
-    @ResourceQualifier(Qualifiers.PROJECT)
-    @ResourceLanguage("xoo")
-    class SecondPage implements Page {
-      @Override
-      public String getTitle() {
-        return "Second Page";
-      }
-
-      @Override
-      public String getId() {
-        return "/second/page";
-      }
-    }
-    Page page2 = new SecondPage();
-
-    @NavigationSection(NavigationSection.RESOURCE)
-    @ResourceScope(Scopes.PROJECT)
-    @ResourceQualifier(Qualifiers.PROJECT)
-    @ResourceLanguage("xoo")
-    @UserRole(UserRole.ADMIN)
-    class AdminPage implements Page {
-      @Override
-      public String getTitle() {
-        return "Admin Page";
-      }
-
-      @Override
-      public String getId() {
-        return "/admin/page";
-      }
-    }
-    Page adminPage = new AdminPage();
-    return new Page[] {page1, page2, adminPage};
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/ui/ws/GlobalActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/ui/ws/GlobalActionTest.java
new file mode 100644 (file)
index 0000000..61b13e5
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.ui.ws;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.config.MapSettings;
+import org.sonar.api.config.Settings;
+import org.sonar.api.platform.Server;
+import org.sonar.api.resources.ResourceType;
+import org.sonar.api.resources.ResourceTypeTree;
+import org.sonar.api.resources.ResourceTypes;
+import org.sonar.api.web.NavigationSection;
+import org.sonar.api.web.Page;
+import org.sonar.api.web.UserRole;
+import org.sonar.api.web.View;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.db.Database;
+import org.sonar.db.dialect.H2;
+import org.sonar.db.dialect.MySql;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ui.Views;
+import org.sonar.server.ws.WsActionTester;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.test.JsonAssert.assertJson;
+
+public class GlobalActionTest {
+
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+
+  private Settings settings = new MapSettings();
+
+  private Server server = mock(Server.class);
+  private Database database = mock(Database.class);
+
+  private WsActionTester ws;
+
+  @Test
+  public void empty_call() throws Exception {
+    init();
+
+    executeAndVerify("empty.json");
+  }
+
+  @Test
+  public void return_qualifiers() throws Exception {
+    init(new View[] {}, new ResourceTypeTree[] {
+      ResourceTypeTree.builder()
+        .addType(ResourceType.builder("POL").build())
+        .addType(ResourceType.builder("LOP").build())
+        .addRelations("POL", "LOP")
+        .build(),
+      ResourceTypeTree.builder()
+        .addType(ResourceType.builder("PAL").build())
+        .addType(ResourceType.builder("LAP").build())
+        .addRelations("PAL", "LAP")
+        .build()
+    });
+
+    executeAndVerify("qualifiers.json");
+  }
+
+  @Test
+  public void return_settings() throws Exception {
+    init();
+    settings.setProperty("sonar.lf.logoUrl", "http://example.com/my-custom-logo.png");
+    settings.setProperty("sonar.lf.logoWidthPx", 135);
+    settings.setProperty("sonar.lf.gravatarServerUrl", "https://secure.gravatar.com/avatar/{EMAIL_MD5}.jpg?s={SIZE}&d=identicon");
+    settings.setProperty("sonar.lf.enableGravatar", true);
+    settings.setProperty("sonar.updatecenter.activate", false);
+    settings.setProperty("sonar.technicalDebt.hoursInDay", "10");
+    settings.setProperty("sonar.technicalDebt.ratingGrid", "0.05,0.1,0.2,0.5");
+    settings.setProperty("sonar.allowUsersToSignUp", true);
+    // This setting should be ignored as it's not needed
+    settings.setProperty("sonar.defaultGroup", "sonar-users");
+
+    executeAndVerify("settings.json");
+  }
+
+  @Test
+  public void return_deprecated_logo_settings() throws Exception {
+    init();
+    settings.setProperty("sonar.lf.logoUrl", "http://example.com/my-custom-logo.png");
+    settings.setProperty("sonar.lf.logoWidthPx", 135);
+
+    executeAndVerify("deprecated_logo_settings.json");
+  }
+
+  @Test
+  public void return_global_pages_for_anonymous() throws Exception {
+    init(createViews(), new ResourceTypeTree[] {});
+
+    executeAndVerify("global_pages_for_anonymous.json");
+  }
+
+  @Test
+  public void return_global_pages_for_user() throws Exception {
+    init(createViews(), new ResourceTypeTree[] {});
+    userSessionRule.login("obiwan");
+
+    executeAndVerify("global_pages_for_user.json");
+  }
+
+  @Test
+  public void return_global_pages_for_admin() throws Exception {
+    init(createViews(), new ResourceTypeTree[] {});
+    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+
+    executeAndVerify("global_pages_for_admin.json");
+  }
+
+  @Test
+  public void return_sonarqube_version() throws Exception {
+    init();
+    when(server.getVersion()).thenReturn("6.2");
+
+    executeAndVerify("version.json");
+  }
+
+  @Test
+  public void return_if_production_database_or_not() throws Exception {
+    init();
+    when(database.getDialect()).thenReturn(new MySql());
+
+    executeAndVerify("production_database.json");
+  }
+
+  @Test
+  public void test_example_response() throws Exception {
+    init(createViews(), new ResourceTypeTree[] {
+      ResourceTypeTree.builder()
+        .addType(ResourceType.builder("POL").build())
+        .addType(ResourceType.builder("LOP").build())
+        .addRelations("POL", "LOP")
+        .build(),
+      ResourceTypeTree.builder()
+        .addType(ResourceType.builder("PAL").build())
+        .addType(ResourceType.builder("LAP").build())
+        .addRelations("PAL", "LAP")
+        .build()
+    });
+    settings.setProperty("sonar.lf.logoUrl", "http://example.com/my-custom-logo.png");
+    settings.setProperty("sonar.lf.logoWidthPx", 135);
+    settings.setProperty("sonar.lf.gravatarServerUrl", "http://some-server.tld/logo.png");
+    settings.setProperty("sonar.lf.enableGravatar", true);
+    settings.setProperty("sonar.updatecenter.activate", false);
+    settings.setProperty("sonar.technicalDebt.hoursInDay", "10");
+    settings.setProperty("sonar.technicalDebt.ratingGrid", "0.05,0.1,0.2,0.5");
+    settings.setProperty("sonar.allowUsersToSignUp", true);
+    when(server.getVersion()).thenReturn("6.2");
+    when(database.getDialect()).thenReturn(new MySql());
+
+    String result = ws.newRequest().execute().getInput();
+    assertJson(ws.getDef().responseExampleAsString()).isSimilarTo(result);
+  }
+
+  private void init() {
+    init(new View[] {}, new ResourceTypeTree[] {});
+  }
+
+  private void init(View[] views, ResourceTypeTree[] resourceTypeTrees) {
+    when(database.getDialect()).thenReturn(new H2());
+    ws = new WsActionTester(new GlobalAction(new Views(userSessionRule, views), settings, new ResourceTypes(resourceTypeTrees), server, database));
+  }
+
+  private void executeAndVerify(String json) {
+    assertJson(ws.newRequest().execute().getInput()).isSimilarTo(getClass().getResource(GlobalActionTest.class.getSimpleName() + "/" + json));
+  }
+
+  private View[] createViews() {
+    Page page = new Page() {
+      @Override
+      public String getTitle() {
+        return "My Plugin Page";
+      }
+
+      @Override
+      public String getId() {
+        return "my_plugin_page";
+      }
+    };
+
+    Page controller = new Page() {
+      @Override
+      public String getTitle() {
+        return "My Rails App";
+      }
+
+      @Override
+      public String getId() {
+        return "my_rails_app";
+      }
+    };
+
+    @NavigationSection(NavigationSection.HOME)
+    @UserRole(GlobalPermissions.SYSTEM_ADMIN)
+    class AdminPage implements Page {
+      @Override
+      public String getTitle() {
+        return "Admin Page";
+      }
+
+      @Override
+      public String getId() {
+        return "admin_page";
+      }
+    }
+    return new View[] {page, controller, new AdminPage()};
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/ui/ws/GlobalNavigationActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/ui/ws/GlobalNavigationActionTest.java
deleted file mode 100644 (file)
index 4613abb..0000000
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.ui.ws;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.config.MapSettings;
-import org.sonar.api.config.Settings;
-import org.sonar.api.platform.Server;
-import org.sonar.api.resources.ResourceType;
-import org.sonar.api.resources.ResourceTypeTree;
-import org.sonar.api.resources.ResourceTypes;
-import org.sonar.api.web.NavigationSection;
-import org.sonar.api.web.Page;
-import org.sonar.api.web.UserRole;
-import org.sonar.api.web.View;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.db.Database;
-import org.sonar.db.dialect.H2;
-import org.sonar.db.dialect.MySql;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ui.Views;
-import org.sonar.server.ws.WsActionTester;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.test.JsonAssert.assertJson;
-
-public class GlobalNavigationActionTest {
-
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
-
-  private Settings settings = new MapSettings();
-
-  private Server server = mock(Server.class);
-  private Database database = mock(Database.class);
-
-  private WsActionTester ws;
-
-  @Test
-  public void empty_call() throws Exception {
-    init();
-
-    executeAndVerify("empty.json");
-  }
-
-  @Test
-  public void return_qualifiers() throws Exception {
-    init(new View[] {}, new ResourceTypeTree[] {
-      ResourceTypeTree.builder()
-        .addType(ResourceType.builder("POL").build())
-        .addType(ResourceType.builder("LOP").build())
-        .addRelations("POL", "LOP")
-        .build(),
-      ResourceTypeTree.builder()
-        .addType(ResourceType.builder("PAL").build())
-        .addType(ResourceType.builder("LAP").build())
-        .addRelations("PAL", "LAP")
-        .build()
-    });
-
-    executeAndVerify("qualifiers.json");
-  }
-
-  @Test
-  public void return_settings() throws Exception {
-    init();
-    settings.setProperty("sonar.lf.logoUrl", "http://example.com/my-custom-logo.png");
-    settings.setProperty("sonar.lf.logoWidthPx", 135);
-    settings.setProperty("sonar.lf.gravatarServerUrl", "https://secure.gravatar.com/avatar/{EMAIL_MD5}.jpg?s={SIZE}&d=identicon");
-    settings.setProperty("sonar.lf.enableGravatar", true);
-    settings.setProperty("sonar.updatecenter.activate", false);
-    settings.setProperty("sonar.technicalDebt.hoursInDay", "10");
-    settings.setProperty("sonar.technicalDebt.ratingGrid", "0.05,0.1,0.2,0.5");
-    settings.setProperty("sonar.allowUsersToSignUp", true);
-    // This setting should be ignored as it's not needed
-    settings.setProperty("sonar.defaultGroup", "sonar-users");
-
-    executeAndVerify("settings.json");
-  }
-
-  @Test
-  public void return_deprecated_logo_settings() throws Exception {
-    init();
-    settings.setProperty("sonar.lf.logoUrl", "http://example.com/my-custom-logo.png");
-    settings.setProperty("sonar.lf.logoWidthPx", 135);
-
-    executeAndVerify("deprecated_logo_settings.json");
-  }
-
-  @Test
-  public void return_global_pages_for_anonymous() throws Exception {
-    init(createViews(), new ResourceTypeTree[] {});
-
-    executeAndVerify("global_pages_for_anonymous.json");
-  }
-
-  @Test
-  public void return_global_pages_for_user() throws Exception {
-    init(createViews(), new ResourceTypeTree[] {});
-    userSessionRule.login("obiwan");
-
-    executeAndVerify("global_pages_for_user.json");
-  }
-
-  @Test
-  public void return_global_pages_for_admin() throws Exception {
-    init(createViews(), new ResourceTypeTree[] {});
-    userSessionRule.login("obiwan").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-
-    executeAndVerify("global_pages_for_admin.json");
-  }
-
-  @Test
-  public void return_sonarqube_version() throws Exception {
-    init();
-    when(server.getVersion()).thenReturn("6.2");
-
-    executeAndVerify("version.json");
-  }
-
-  @Test
-  public void return_if_production_database_or_not() throws Exception {
-    init();
-    when(database.getDialect()).thenReturn(new MySql());
-
-    executeAndVerify("production_database.json");
-  }
-
-  @Test
-  public void test_example_response() throws Exception {
-    init(createViews(), new ResourceTypeTree[] {
-      ResourceTypeTree.builder()
-        .addType(ResourceType.builder("POL").build())
-        .addType(ResourceType.builder("LOP").build())
-        .addRelations("POL", "LOP")
-        .build(),
-      ResourceTypeTree.builder()
-        .addType(ResourceType.builder("PAL").build())
-        .addType(ResourceType.builder("LAP").build())
-        .addRelations("PAL", "LAP")
-        .build()
-    });
-    settings.setProperty("sonar.lf.logoUrl", "http://example.com/my-custom-logo.png");
-    settings.setProperty("sonar.lf.logoWidthPx", 135);
-    settings.setProperty("sonar.lf.gravatarServerUrl", "http://some-server.tld/logo.png");
-    settings.setProperty("sonar.lf.enableGravatar", true);
-    settings.setProperty("sonar.updatecenter.activate", false);
-    settings.setProperty("sonar.technicalDebt.hoursInDay", "10");
-    settings.setProperty("sonar.technicalDebt.ratingGrid", "0.05,0.1,0.2,0.5");
-    settings.setProperty("sonar.allowUsersToSignUp", true);
-    when(server.getVersion()).thenReturn("6.2");
-    when(database.getDialect()).thenReturn(new MySql());
-
-    String result = ws.newRequest().execute().getInput();
-    assertJson(ws.getDef().responseExampleAsString()).isSimilarTo(result);
-  }
-
-  private void init() {
-    init(new View[] {}, new ResourceTypeTree[] {});
-  }
-
-  private void init(View[] views, ResourceTypeTree[] resourceTypeTrees) {
-    when(database.getDialect()).thenReturn(new H2());
-    ws = new WsActionTester(new GlobalNavigationAction(new Views(userSessionRule, views), settings, new ResourceTypes(resourceTypeTrees), server, database));
-  }
-
-  private void executeAndVerify(String json) {
-    assertJson(ws.newRequest().execute().getInput()).isSimilarTo(getClass().getResource(GlobalNavigationActionTest.class.getSimpleName() + "/" + json));
-  }
-
-  private View[] createViews() {
-    Page page = new Page() {
-      @Override
-      public String getTitle() {
-        return "My Plugin Page";
-      }
-
-      @Override
-      public String getId() {
-        return "my_plugin_page";
-      }
-    };
-
-    Page controller = new Page() {
-      @Override
-      public String getTitle() {
-        return "My Rails App";
-      }
-
-      @Override
-      public String getId() {
-        return "my_rails_app";
-      }
-    };
-
-    @NavigationSection(NavigationSection.HOME)
-    @UserRole(GlobalPermissions.SYSTEM_ADMIN)
-    class AdminPage implements Page {
-      @Override
-      public String getTitle() {
-        return "Admin Page";
-      }
-
-      @Override
-      public String getId() {
-        return "admin_page";
-      }
-    }
-    return new View[] {page, controller, new AdminPage()};
-  }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/ui/ws/NavigationWsModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/ui/ws/NavigationWsModuleTest.java
new file mode 100644 (file)
index 0000000..214596a
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.ui.ws;
+
+import org.junit.Test;
+import org.sonar.core.platform.ComponentContainer;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class NavigationWsModuleTest {
+  @Test
+  public void verify_count_of_added_components() {
+    ComponentContainer container = new ComponentContainer();
+    new NavigationWsModule().configure(container);
+    assertThat(container.size()).isEqualTo(4 + 2);
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/ui/ws/SettingsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/ui/ws/SettingsActionTest.java
new file mode 100644 (file)
index 0000000..647af7a
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.ui.ws;
+
+import java.util.Locale;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.config.MapSettings;
+import org.sonar.api.config.Settings;
+import org.sonar.api.i18n.I18n;
+import org.sonar.api.web.NavigationSection;
+import org.sonar.api.web.Page;
+import org.sonar.api.web.View;
+import org.sonar.core.config.WebConstants;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ui.Views;
+import org.sonar.server.ws.WsActionTester;
+import org.sonar.test.JsonAssert;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class SettingsActionTest {
+
+  @Rule
+  public UserSessionRule userSessionRule = UserSessionRule.standalone();
+
+  private Settings settings = new MapSettings();
+
+  private I18n i18n = mock(I18n.class);
+
+  private WsActionTester ws;
+
+  @Before
+  public void before() {
+    when(i18n.message(any(Locale.class), anyString(), anyString())).thenAnswer(invocation -> invocation.getArgumentAt(2, String.class));
+  }
+
+  @Test
+  public void empty() throws Exception {
+    init();
+    userSessionRule.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+
+    executeAndVerify("empty.json");
+  }
+
+  @Test
+  public void with_provisioning() throws Exception {
+    init();
+    userSessionRule.setGlobalPermissions(GlobalPermissions.PROVISIONING);
+
+    executeAndVerify("with_provisioning.json");
+  }
+
+  @Test
+  public void with_views() throws Exception {
+    init(createViews());
+    userSessionRule.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+
+    executeAndVerify("with_views.json");
+  }
+
+  @Test
+  public void with_update_center() throws Exception {
+    init();
+    settings.setProperty(WebConstants.SONAR_UPDATECENTER_ACTIVATE, true);
+    userSessionRule.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+
+    executeAndVerify("with_update_center.json");
+  }
+
+  @Test
+  public void with_views_and_update_center_but_not_admin() throws Exception {
+    init(createViews());
+    settings.setProperty(WebConstants.SONAR_UPDATECENTER_ACTIVATE, true);
+
+    executeAndVerify("empty.json");
+  }
+
+  private void init(View... views) {
+    ws = new WsActionTester(new SettingsAction(settings, new Views(userSessionRule, views), i18n, userSessionRule));
+  }
+
+  private void executeAndVerify(String json) {
+    JsonAssert.assertJson(ws.newRequest().execute().getInput()).isSimilarTo(getClass().getResource("SettingsActionTest/" + json));
+  }
+
+  private View[] createViews() {
+
+    @NavigationSection(NavigationSection.CONFIGURATION)
+    class FirstPage implements Page {
+      @Override
+      public String getTitle() {
+        return "First Page";
+      }
+
+      @Override
+      public String getId() {
+        return "first_page";
+      }
+    }
+
+    @NavigationSection(NavigationSection.CONFIGURATION)
+    class SecondPage implements Page {
+      @Override
+      public String getTitle() {
+        return "Second Page";
+      }
+
+      @Override
+      public String getId() {
+        return "second_page";
+      }
+    }
+
+    Page page = new FirstPage();
+    Page controller = new SecondPage();
+    return new View[] {page, controller};
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/ui/ws/SettingsNavigationActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/ui/ws/SettingsNavigationActionTest.java
deleted file mode 100644 (file)
index d3d671b..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.server.ui.ws;
-
-import java.util.Locale;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.config.MapSettings;
-import org.sonar.api.config.Settings;
-import org.sonar.api.i18n.I18n;
-import org.sonar.api.web.NavigationSection;
-import org.sonar.api.web.Page;
-import org.sonar.api.web.View;
-import org.sonar.core.config.WebConstants;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ui.Views;
-import org.sonar.server.ws.WsActionTester;
-import org.sonar.test.JsonAssert;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class SettingsNavigationActionTest {
-
-  @Rule
-  public UserSessionRule userSessionRule = UserSessionRule.standalone();
-
-  private Settings settings = new MapSettings();
-
-  private I18n i18n = mock(I18n.class);
-
-  private WsActionTester ws;
-
-  @Before
-  public void before() {
-    when(i18n.message(any(Locale.class), anyString(), anyString())).thenAnswer(invocation -> invocation.getArgumentAt(2, String.class));
-  }
-
-  @Test
-  public void empty() throws Exception {
-    init();
-    userSessionRule.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-
-    executeAndVerify("empty.json");
-  }
-
-  @Test
-  public void with_provisioning() throws Exception {
-    init();
-    userSessionRule.setGlobalPermissions(GlobalPermissions.PROVISIONING);
-
-    executeAndVerify("with_provisioning.json");
-  }
-
-  @Test
-  public void with_views() throws Exception {
-    init(createViews());
-    userSessionRule.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-
-    executeAndVerify("with_views.json");
-  }
-
-  @Test
-  public void with_update_center() throws Exception {
-    init();
-    settings.setProperty(WebConstants.SONAR_UPDATECENTER_ACTIVATE, true);
-    userSessionRule.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-
-    executeAndVerify("with_update_center.json");
-  }
-
-  @Test
-  public void with_views_and_update_center_but_not_admin() throws Exception {
-    init(createViews());
-    settings.setProperty(WebConstants.SONAR_UPDATECENTER_ACTIVATE, true);
-
-    executeAndVerify("empty.json");
-  }
-
-  private void init(View... views) {
-    ws = new WsActionTester(new SettingsNavigationAction(settings, new Views(userSessionRule, views), i18n, userSessionRule));
-  }
-
-  private void executeAndVerify(String json) {
-    JsonAssert.assertJson(ws.newRequest().execute().getInput()).isSimilarTo(getClass().getResource("SettingsNavigationActionTest/" + json));
-  }
-
-  private View[] createViews() {
-
-    @NavigationSection(NavigationSection.CONFIGURATION)
-    class FirstPage implements Page {
-      @Override
-      public String getTitle() {
-        return "First Page";
-      }
-
-      @Override
-      public String getId() {
-        return "first_page";
-      }
-    }
-
-    @NavigationSection(NavigationSection.CONFIGURATION)
-    class SecondPage implements Page {
-      @Override
-      public String getTitle() {
-        return "Second Page";
-      }
-
-      @Override
-      public String getId() {
-        return "second_page";
-      }
-    }
-
-    Page page = new FirstPage();
-    Page controller = new SecondPage();
-    return new View[] {page, controller};
-  }
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_bread_crumbs_on_several_levels.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_bread_crumbs_on_several_levels.json
new file mode 100644 (file)
index 0000000..fe5e866
--- /dev/null
@@ -0,0 +1,28 @@
+{
+  "key": "palap:src/main/xoo/Source.xoo",
+  "id": "cdef",
+  "name": "Source.xoo",
+  "isFavorite": false,
+  "breadcrumbs": [
+    {
+      "key": "polop",
+      "name": "Polop",
+      "qualifier": "TRK"
+    },
+    {
+      "key": "palap",
+      "name": "Palap",
+      "qualifier": "BRC"
+    },
+    {
+      "key": "palap:src/main/xoo",
+      "name": "src/main/xoo",
+      "qualifier": "DIR"
+    },
+    {
+      "key": "palap:src/main/xoo/Source.xoo",
+      "name": "Source.xoo",
+      "qualifier": "FIL"
+    }
+  ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_breadcrumbs_on_module.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_breadcrumbs_on_module.json
new file mode 100644 (file)
index 0000000..5054f14
--- /dev/null
@@ -0,0 +1,14 @@
+{
+  "breadcrumbs": [
+    {
+      "key": "polop",
+      "name": "Polop",
+      "qualifier": "TRK"
+    },
+    {
+      "key": "palap",
+      "name": "Palap",
+      "qualifier": "BRC"
+    }
+  ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_component_info_when_anonymous_no_snapshot.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_component_info_when_anonymous_no_snapshot.json
new file mode 100644 (file)
index 0000000..ede37f6
--- /dev/null
@@ -0,0 +1,14 @@
+{
+  "key": "polop",
+  "id": "abcd",
+  "name": "Polop",
+  "description": "test project",
+  "isFavorite": false,
+  "breadcrumbs": [
+    {
+      "key": "polop",
+      "name": "Polop",
+      "qualifier": "TRK"
+    }
+  ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_component_info_when_snapshot.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_component_info_when_snapshot.json
new file mode 100644 (file)
index 0000000..90752cb
--- /dev/null
@@ -0,0 +1,16 @@
+{
+  "key": "polop",
+  "id": "abcd",
+  "name": "Polop",
+  "description": "test project",
+  "isFavorite": false,
+  "snapshotDate": "2015-04-22T11:44:00+0200",
+  "version": "3.14",
+  "breadcrumbs": [
+    {
+      "key": "polop",
+      "name": "Polop",
+      "qualifier": "TRK"
+    }
+  ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_component_info_with_favourite.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_component_info_with_favourite.json
new file mode 100644 (file)
index 0000000..1eea206
--- /dev/null
@@ -0,0 +1,14 @@
+{
+  "key": "polop",
+  "id": "abcd",
+  "name": "Polop",
+  "description": "test project",
+  "isFavorite": true,
+  "breadcrumbs": [
+    {
+      "key": "polop",
+      "name": "Polop",
+      "qualifier": "TRK"
+    }
+  ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_configuration_for_admin.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_configuration_for_admin.json
new file mode 100644 (file)
index 0000000..b68d79e
--- /dev/null
@@ -0,0 +1,22 @@
+{
+  "configuration": {
+    "showSettings": false,
+    "showQualityProfiles": true,
+    "showQualityGates": true,
+    "showManualMeasures": true,
+    "showLinks": true,
+    "showPermissions": false,
+    "showHistory": false,
+    "showUpdateKey": false,
+    "extensions": [
+      {
+        "id": "first_page",
+        "name": "First Page"
+      },
+      {
+        "id": "/second/page",
+        "name": "Second Page"
+      }
+    ]
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_configuration_for_quality_profile_admin.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_configuration_for_quality_profile_admin.json
new file mode 100644 (file)
index 0000000..0b8a1b3
--- /dev/null
@@ -0,0 +1,12 @@
+{
+  "configuration": {
+    "showSettings": false,
+    "showQualityProfiles": true,
+    "showQualityGates": true,
+    "showManualMeasures": false,
+    "showLinks": false,
+    "showPermissions": false,
+    "showHistory": false,
+    "showUpdateKey": false
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_configuration_with_all_properties.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_configuration_with_all_properties.json
new file mode 100644 (file)
index 0000000..3384808
--- /dev/null
@@ -0,0 +1,13 @@
+{
+  "configuration": {
+    "showSettings": true,
+    "showQualityProfiles": true,
+    "showQualityGates": true,
+    "showManualMeasures": true,
+    "showLinks": true,
+    "showPermissions": true,
+    "showHistory": true,
+    "showUpdateKey": true,
+    "extensions": []
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_default_quality_gate.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_default_quality_gate.json
new file mode 100644 (file)
index 0000000..e721b5c
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "qualityGate": {
+    "name": "Sonar way",
+    "isDefault": true
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_empty_quality_profiles_when_no_measure.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_empty_quality_profiles_when_no_measure.json
new file mode 100644 (file)
index 0000000..d825b57
--- /dev/null
@@ -0,0 +1,3 @@
+{
+  "qualityProfiles": []
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_extensions.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_extensions.json
new file mode 100644 (file)
index 0000000..e470ef4
--- /dev/null
@@ -0,0 +1,12 @@
+{
+  "extensions": [
+    {
+      "id": "first_page",
+      "name": "First Page"
+    },
+    {
+      "id": "/second/page",
+      "name": "Second Page"
+    }
+  ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_extensions_for_admin.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_extensions_for_admin.json
new file mode 100644 (file)
index 0000000..7301a92
--- /dev/null
@@ -0,0 +1,16 @@
+{
+  "extensions": [
+    {
+      "id": "first_page",
+      "name": "First Page"
+    },
+    {
+      "id": "/second/page",
+      "name": "Second Page"
+    },
+    {
+      "id": "/admin/page",
+      "name": "Admin Page"
+    }
+  ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_quality_gate.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_quality_gate.json
new file mode 100644 (file)
index 0000000..6a016b8
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "qualityGate": {
+    "name": "Sonar way",
+    "isDefault": false
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_quality_profiles.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_quality_profiles.json
new file mode 100644 (file)
index 0000000..10865b0
--- /dev/null
@@ -0,0 +1,14 @@
+{
+  "qualityProfiles": [
+    {
+      "key": "qp1",
+      "name": "Sonar Way Java",
+      "language": "java"
+    },
+    {
+      "key": "qp2",
+      "name": "Sonar Way Xoo",
+      "language": "xoo"
+    }
+  ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_bread_crumbs_on_several_levels.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_bread_crumbs_on_several_levels.json
deleted file mode 100644 (file)
index fe5e866..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-{
-  "key": "palap:src/main/xoo/Source.xoo",
-  "id": "cdef",
-  "name": "Source.xoo",
-  "isFavorite": false,
-  "breadcrumbs": [
-    {
-      "key": "polop",
-      "name": "Polop",
-      "qualifier": "TRK"
-    },
-    {
-      "key": "palap",
-      "name": "Palap",
-      "qualifier": "BRC"
-    },
-    {
-      "key": "palap:src/main/xoo",
-      "name": "src/main/xoo",
-      "qualifier": "DIR"
-    },
-    {
-      "key": "palap:src/main/xoo/Source.xoo",
-      "name": "Source.xoo",
-      "qualifier": "FIL"
-    }
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_breadcrumbs_on_module.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_breadcrumbs_on_module.json
deleted file mode 100644 (file)
index 5054f14..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "breadcrumbs": [
-    {
-      "key": "polop",
-      "name": "Polop",
-      "qualifier": "TRK"
-    },
-    {
-      "key": "palap",
-      "name": "Palap",
-      "qualifier": "BRC"
-    }
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_component_info_when_anonymous_no_snapshot.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_component_info_when_anonymous_no_snapshot.json
deleted file mode 100644 (file)
index ede37f6..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "key": "polop",
-  "id": "abcd",
-  "name": "Polop",
-  "description": "test project",
-  "isFavorite": false,
-  "breadcrumbs": [
-    {
-      "key": "polop",
-      "name": "Polop",
-      "qualifier": "TRK"
-    }
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_component_info_when_snapshot.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_component_info_when_snapshot.json
deleted file mode 100644 (file)
index 90752cb..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "key": "polop",
-  "id": "abcd",
-  "name": "Polop",
-  "description": "test project",
-  "isFavorite": false,
-  "snapshotDate": "2015-04-22T11:44:00+0200",
-  "version": "3.14",
-  "breadcrumbs": [
-    {
-      "key": "polop",
-      "name": "Polop",
-      "qualifier": "TRK"
-    }
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_component_info_with_favourite.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_component_info_with_favourite.json
deleted file mode 100644 (file)
index 1eea206..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "key": "polop",
-  "id": "abcd",
-  "name": "Polop",
-  "description": "test project",
-  "isFavorite": true,
-  "breadcrumbs": [
-    {
-      "key": "polop",
-      "name": "Polop",
-      "qualifier": "TRK"
-    }
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_configuration_for_admin.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_configuration_for_admin.json
deleted file mode 100644 (file)
index b68d79e..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-  "configuration": {
-    "showSettings": false,
-    "showQualityProfiles": true,
-    "showQualityGates": true,
-    "showManualMeasures": true,
-    "showLinks": true,
-    "showPermissions": false,
-    "showHistory": false,
-    "showUpdateKey": false,
-    "extensions": [
-      {
-        "id": "first_page",
-        "name": "First Page"
-      },
-      {
-        "id": "/second/page",
-        "name": "Second Page"
-      }
-    ]
-  }
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_configuration_for_quality_profile_admin.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_configuration_for_quality_profile_admin.json
deleted file mode 100644 (file)
index 0b8a1b3..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "configuration": {
-    "showSettings": false,
-    "showQualityProfiles": true,
-    "showQualityGates": true,
-    "showManualMeasures": false,
-    "showLinks": false,
-    "showPermissions": false,
-    "showHistory": false,
-    "showUpdateKey": false
-  }
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_configuration_with_all_properties.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_configuration_with_all_properties.json
deleted file mode 100644 (file)
index 3384808..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-  "configuration": {
-    "showSettings": true,
-    "showQualityProfiles": true,
-    "showQualityGates": true,
-    "showManualMeasures": true,
-    "showLinks": true,
-    "showPermissions": true,
-    "showHistory": true,
-    "showUpdateKey": true,
-    "extensions": []
-  }
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_default_quality_gate.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_default_quality_gate.json
deleted file mode 100644 (file)
index e721b5c..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "qualityGate": {
-    "name": "Sonar way",
-    "isDefault": true
-  }
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_empty_quality_profiles_when_no_measure.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_empty_quality_profiles_when_no_measure.json
deleted file mode 100644 (file)
index d825b57..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "qualityProfiles": []
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_extensions.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_extensions.json
deleted file mode 100644 (file)
index e470ef4..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "extensions": [
-    {
-      "id": "first_page",
-      "name": "First Page"
-    },
-    {
-      "id": "/second/page",
-      "name": "Second Page"
-    }
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_extensions_for_admin.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_extensions_for_admin.json
deleted file mode 100644 (file)
index 7301a92..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "extensions": [
-    {
-      "id": "first_page",
-      "name": "First Page"
-    },
-    {
-      "id": "/second/page",
-      "name": "Second Page"
-    },
-    {
-      "id": "/admin/page",
-      "name": "Admin Page"
-    }
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_quality_gate.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_quality_gate.json
deleted file mode 100644 (file)
index 6a016b8..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "qualityGate": {
-    "name": "Sonar way",
-    "isDefault": false
-  }
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_quality_profiles.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentNavigationActionTest/return_quality_profiles.json
deleted file mode 100644 (file)
index 10865b0..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "qualityProfiles": [
-    {
-      "key": "qp1",
-      "name": "Sonar Way Java",
-      "language": "java"
-    },
-    {
-      "key": "qp2",
-      "name": "Sonar Way Xoo",
-      "language": "xoo"
-    }
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/deprecated_logo_settings.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/deprecated_logo_settings.json
new file mode 100644 (file)
index 0000000..13930da
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  "settings": {
+    "sonar.lf.logoUrl": "http://example.com/my-custom-logo.png",
+    "sonar.lf.logoWidthPx": "135"
+  },
+  "logoUrl": "http://example.com/my-custom-logo.png",
+  "logoWidth": "135"
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/empty.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/empty.json
new file mode 100644 (file)
index 0000000..cc5448c
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  "globalPages": [],
+  "settings": {},
+  "qualifiers": []
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/global_pages_for_admin.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/global_pages_for_admin.json
new file mode 100644 (file)
index 0000000..664b126
--- /dev/null
@@ -0,0 +1,16 @@
+{
+  "globalPages": [
+    {
+      "id": "my_plugin_page",
+      "name": "My Plugin Page"
+    },
+    {
+      "id": "my_rails_app",
+      "name": "My Rails App"
+    },
+    {
+      "id": "admin_page",
+      "name": "Admin Page"
+    }
+  ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/global_pages_for_anonymous.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/global_pages_for_anonymous.json
new file mode 100644 (file)
index 0000000..ab7722b
--- /dev/null
@@ -0,0 +1,12 @@
+{
+  "globalPages": [
+    {
+      "id": "my_plugin_page",
+      "name": "My Plugin Page"
+    },
+    {
+      "id": "my_rails_app",
+      "name": "My Rails App"
+    }
+  ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/global_pages_for_user.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/global_pages_for_user.json
new file mode 100644 (file)
index 0000000..ab7722b
--- /dev/null
@@ -0,0 +1,12 @@
+{
+  "globalPages": [
+    {
+      "id": "my_plugin_page",
+      "name": "My Plugin Page"
+    },
+    {
+      "id": "my_rails_app",
+      "name": "My Rails App"
+    }
+  ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/production_database.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/production_database.json
new file mode 100644 (file)
index 0000000..ae8359c
--- /dev/null
@@ -0,0 +1,3 @@
+{
+  "productionDatabase": true
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/qualifiers.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/qualifiers.json
new file mode 100644 (file)
index 0000000..ef2107c
--- /dev/null
@@ -0,0 +1,3 @@
+{
+  "qualifiers": ["POL", "PAL"]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/settings.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/settings.json
new file mode 100644 (file)
index 0000000..d6d1fd2
--- /dev/null
@@ -0,0 +1,12 @@
+{
+  "settings": {
+    "sonar.lf.logoUrl": "http://example.com/my-custom-logo.png",
+    "sonar.lf.logoWidthPx": "135",
+    "sonar.lf.gravatarServerUrl": "https://secure.gravatar.com/avatar/{EMAIL_MD5}.jpg?s={SIZE}&d=identicon",
+    "sonar.lf.enableGravatar": "true",
+    "sonar.updatecenter.activate": "false",
+    "sonar.technicalDebt.hoursInDay": "10",
+    "sonar.technicalDebt.ratingGrid": "0.05,0.1,0.2,0.5",
+    "sonar.allowUsersToSignUp": "true"
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/version.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalActionTest/version.json
new file mode 100644 (file)
index 0000000..21cd139
--- /dev/null
@@ -0,0 +1,3 @@
+{
+  "version": "6.2"
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/deprecated_logo_settings.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/deprecated_logo_settings.json
deleted file mode 100644 (file)
index 13930da..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "settings": {
-    "sonar.lf.logoUrl": "http://example.com/my-custom-logo.png",
-    "sonar.lf.logoWidthPx": "135"
-  },
-  "logoUrl": "http://example.com/my-custom-logo.png",
-  "logoWidth": "135"
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/empty.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/empty.json
deleted file mode 100644 (file)
index cc5448c..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "globalPages": [],
-  "settings": {},
-  "qualifiers": []
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/global_pages_for_admin.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/global_pages_for_admin.json
deleted file mode 100644 (file)
index 664b126..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "globalPages": [
-    {
-      "id": "my_plugin_page",
-      "name": "My Plugin Page"
-    },
-    {
-      "id": "my_rails_app",
-      "name": "My Rails App"
-    },
-    {
-      "id": "admin_page",
-      "name": "Admin Page"
-    }
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/global_pages_for_anonymous.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/global_pages_for_anonymous.json
deleted file mode 100644 (file)
index ab7722b..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "globalPages": [
-    {
-      "id": "my_plugin_page",
-      "name": "My Plugin Page"
-    },
-    {
-      "id": "my_rails_app",
-      "name": "My Rails App"
-    }
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/global_pages_for_user.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/global_pages_for_user.json
deleted file mode 100644 (file)
index ab7722b..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "globalPages": [
-    {
-      "id": "my_plugin_page",
-      "name": "My Plugin Page"
-    },
-    {
-      "id": "my_rails_app",
-      "name": "My Rails App"
-    }
-  ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/production_database.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/production_database.json
deleted file mode 100644 (file)
index ae8359c..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "productionDatabase": true
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/qualifiers.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/qualifiers.json
deleted file mode 100644 (file)
index ef2107c..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "qualifiers": ["POL", "PAL"]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/settings.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/settings.json
deleted file mode 100644 (file)
index d6d1fd2..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "settings": {
-    "sonar.lf.logoUrl": "http://example.com/my-custom-logo.png",
-    "sonar.lf.logoWidthPx": "135",
-    "sonar.lf.gravatarServerUrl": "https://secure.gravatar.com/avatar/{EMAIL_MD5}.jpg?s={SIZE}&d=identicon",
-    "sonar.lf.enableGravatar": "true",
-    "sonar.updatecenter.activate": "false",
-    "sonar.technicalDebt.hoursInDay": "10",
-    "sonar.technicalDebt.ratingGrid": "0.05,0.1,0.2,0.5",
-    "sonar.allowUsersToSignUp": "true"
-  }
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/version.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/version.json
deleted file mode 100644 (file)
index 21cd139..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "version": "6.2"
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/SettingsActionTest/empty.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/SettingsActionTest/empty.json
new file mode 100644 (file)
index 0000000..f163908
--- /dev/null
@@ -0,0 +1,4 @@
+{
+  "showUpdateCenter": false,
+  "extensions": []
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/SettingsActionTest/with_provisioning.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/SettingsActionTest/with_provisioning.json
new file mode 100644 (file)
index 0000000..decc9c5
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  "showUpdateCenter": false,
+  "showProvisioning": true,
+  "extensions": []
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/SettingsActionTest/with_update_center.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/SettingsActionTest/with_update_center.json
new file mode 100644 (file)
index 0000000..c0e33fb
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  "showUpdateCenter": true,
+  "showProvisioning": false,
+  "extensions": []
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/SettingsActionTest/with_views.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/SettingsActionTest/with_views.json
new file mode 100644 (file)
index 0000000..44d4bd3
--- /dev/null
@@ -0,0 +1,14 @@
+{
+  "showUpdateCenter": false,
+  "showProvisioning": false,
+  "extensions": [
+    {
+      "id": "first_page",
+      "name": "First Page"
+    },
+    {
+      "id": "second_page",
+      "name": "Second Page"
+    }
+  ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/SettingsNavigationActionTest/empty.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/SettingsNavigationActionTest/empty.json
deleted file mode 100644 (file)
index f163908..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "showUpdateCenter": false,
-  "extensions": []
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/SettingsNavigationActionTest/with_provisioning.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/SettingsNavigationActionTest/with_provisioning.json
deleted file mode 100644 (file)
index decc9c5..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "showUpdateCenter": false,
-  "showProvisioning": true,
-  "extensions": []
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/SettingsNavigationActionTest/with_update_center.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/SettingsNavigationActionTest/with_update_center.json
deleted file mode 100644 (file)
index c0e33fb..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "showUpdateCenter": true,
-  "showProvisioning": false,
-  "extensions": []
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/SettingsNavigationActionTest/with_views.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/SettingsNavigationActionTest/with_views.json
deleted file mode 100644 (file)
index 44d4bd3..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "showUpdateCenter": false,
-  "showProvisioning": false,
-  "extensions": [
-    {
-      "id": "first_page",
-      "name": "First Page"
-    },
-    {
-      "id": "second_page",
-      "name": "Second Page"
-    }
-  ]
-}