]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7277 Create a route to redirect profiles/export to api/qualityprofiles/export
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Wed, 18 Jan 2017 18:07:20 +0000 (19:07 +0100)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Tue, 24 Jan 2017 17:36:48 +0000 (18:36 +0100)
it/it-tests/src/test/java/it/ws/RoutesTest.java [new file with mode: 0644]
it/it-tests/src/test/java/it/ws/WsLocalCallTest.java
server/sonar-server/src/main/java/org/sonar/server/platform/web/RoutesFilter.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ExportAction.java
server/sonar-server/src/test/java/org/sonar/server/platform/web/RoutesFilterTest.java

diff --git a/it/it-tests/src/test/java/it/ws/RoutesTest.java b/it/it-tests/src/test/java/it/ws/RoutesTest.java
new file mode 100644 (file)
index 0000000..0acd03f
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * 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 it.ws;
+
+import com.sonar.orchestrator.Orchestrator;
+import it.Category4Suite;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonarqube.ws.client.GetRequest;
+import org.sonarqube.ws.client.WsResponse;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static util.ItUtils.newWsClient;
+
+public class RoutesTest {
+
+  @ClassRule
+  public static final Orchestrator orchestrator = Category4Suite.ORCHESTRATOR;
+
+  @Test
+  public void redirect_profiles_export_to_api_qualityprofiles_export() {
+    WsResponse response = newWsClient(orchestrator).wsConnector().call(new GetRequest("profiles/export?language=xoo&format=XooFakeExporter"));
+    assertThat(response.isSuccessful()).isTrue();
+    assertThat(response.requestUrl()).endsWith("/api/qualityprofiles/export?language=xoo&format=XooFakeExporter");
+    assertThat(response.content()).isEqualTo("xoo -> Basic -> 1");
+
+    // Check 'name' parameter is taken into account
+    assertThat(newWsClient(orchestrator).wsConnector().call(new GetRequest("profiles/export?language=xoo&name=empty&format=XooFakeExporter")).content()).isEqualTo("xoo -> empty -> 0");
+  }
+
+}
index 8b6ee43c43d93166c74846271426655b80753859..8a7daf8be3e65c7b0d27b200563bf5ce273d00be 100644 (file)
@@ -30,6 +30,7 @@ import org.sonarqube.ws.client.WsClientFactories;
 import org.sonarqube.ws.client.WsResponse;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static util.ItUtils.newWsClient;
 
 /**
  * Tests the ability for a web service to call another web services.
@@ -41,13 +42,13 @@ public class WsLocalCallTest {
 
   @Test
   public void gets_protobuf() {
-    WsResponse response = newAnonymousClient().wsConnector().call(new GetRequest("local_ws_call/protobuf_data"));
+    WsResponse response = newWsClient(orchestrator).wsConnector().call(new GetRequest("local_ws_call/protobuf_data"));
     assertThat(response.isSuccessful()).isTrue();
   }
 
   @Test
   public void gets_json() {
-    WsResponse response = newAnonymousClient().wsConnector().call(new GetRequest("local_ws_call/json_data"));
+    WsResponse response = newWsClient(orchestrator).wsConnector().call(new GetRequest("local_ws_call/json_data"));
     assertThat(response.isSuccessful()).isTrue();
   }
 
@@ -63,13 +64,10 @@ public class WsLocalCallTest {
 
   @Test
   public void fails_if_requires_permissions() {
-    WsResponse response = newAnonymousClient().wsConnector().call(new GetRequest("local_ws_call/require_permission"));
+    WsResponse response = newWsClient(orchestrator).wsConnector().call(new GetRequest("local_ws_call/require_permission"));
 
     // this is not the unauthorized code as plugin forces it to 500
     assertThat(response.code()).isEqualTo(500);
   }
 
-  private static WsClient newAnonymousClient() {
-    return WsClientFactories.getDefault().newClient(HttpConnector.newBuilder().url(orchestrator.getServer().getUrl()).build());
-  }
 }
index d7ed5d8dab6534d68189e5676e74780056709c36..dff0f867a28a95c7567f0bc2c7d89b6a39fb6589 100644 (file)
@@ -44,7 +44,8 @@ public class RoutesFilter implements Filter {
   private static final List<Route> ROUTES = ImmutableList.of(
     new BatchRoute(),
     new BatchBootstrapRoute(),
-    new ApiSourcesRoute());
+    new ApiSourcesRoute(),
+    new ProfilesExportRoute());
 
   @Override
   public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
@@ -133,6 +134,25 @@ public class RoutesFilter implements Filter {
     }
   }
 
+  /**
+   * Old scanners were using /profiles/export url (see SVS-130)
+   */
+  private static class ProfilesExportRoute implements Route {
+
+    private static final String PROFILES_EXPORT = "/profiles/export";
+    private static final String API_QUALITY_PROFILE_EXPORT = "/api/qualityprofiles/export";
+
+    @Override
+    public boolean test(String path) {
+      return PROFILES_EXPORT.equals(path);
+    }
+
+    @Override
+    public String apply(HttpServletRequest request) {
+      return format("%s%s?%s", request.getContextPath(), API_QUALITY_PROFILE_EXPORT, request.getQueryString());
+    }
+  }
+
   private static String extractPath(HttpServletRequest request) {
     return request.getRequestURI().replaceFirst(request.getContextPath(), EMPTY);
   }
index 04605c9d18a4903e316d4e27598ad2b3c6434690..82ca2cc4ff947fd43a4ee83b994fc3140102ff93 100644 (file)
@@ -48,7 +48,7 @@ public class ExportAction implements QProfileWsAction {
 
   private static final String PARAM_PROFILE_NAME = "name";
   private static final String PARAM_LANGUAGE = "language";
-  private static final String PARAM_FORMAT = "exporterKey";
+  public static final String PARAM_FORMAT = "exporterKey";
 
   private final DbClient dbClient;
 
@@ -96,7 +96,9 @@ public class ExportAction implements QProfileWsAction {
       action.createParam(PARAM_FORMAT)
         .setDescription("Output format. If left empty, the same format as api/qualityprofiles/backup is used. " +
           "Possible values are described by api/qualityprofiles/exporters.")
-        .setPossibleValues(exporterKeys);
+        .setPossibleValues(exporterKeys)
+        // This deprecated key is only there to be able to deal with redirection from /profiles/export
+        .setDeprecatedKey("format");
     }
   }
 
index 9260b82f58d61bd53b414c43eaef938b0c28d070..46b374497e9e4b11368150628e9197632dba3b9d 100644 (file)
@@ -64,6 +64,11 @@ public class RoutesFilterTest {
     verifyRedirection("/api/sources", "resource=my.project", "/sonarqube/api/sources/index?resource=my.project");
   }
 
+  @Test
+  public void send_redirect_when_url_contains_profiles_export() throws Exception {
+    verifyRedirection("/profiles/export", "format=pmd", "/sonarqube/api/qualityprofiles/export?format=pmd");
+  }
+
   @Test
   public void does_not_redirect_and_execute_remaining_filter_on_unknown_path() throws Exception {
     verifyNoRedirection("/api/issues/search", null);