]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6304 Set Content-Disposition header on profile backup and export 394/head
authorJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Tue, 23 Jun 2015 09:58:27 +0000 (11:58 +0200)
committerJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Wed, 24 Jun 2015 12:01:18 +0000 (14:01 +0200)
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/BackupAction.java
server/sonar-server/src/main/java/org/sonar/server/ws/ServletResponse.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/BackupActionTest.java
server/sonar-server/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java
server/sonar-server/src/test/java/org/sonar/server/ws/WsTester.java
server/sonar-web/src/main/webapp/WEB-INF/app/controllers/api/java_ws_controller.rb
sonar-plugin-api/src/main/java/org/sonar/api/server/ws/Response.java

index 69e320da5b0c658f2bfef6e7098064ca5c98031e..4202334c288920942652de314512183870067987 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.sonar.server.qualityprofile.ws;
 
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
 import org.apache.commons.io.IOUtils;
 import org.sonar.api.resources.Languages;
 import org.sonar.api.server.ws.Request;
@@ -32,9 +34,6 @@ import org.sonar.server.plugins.MimeTypes;
 import org.sonar.server.qualityprofile.QProfileBackuper;
 import org.sonar.server.qualityprofile.QProfileFactory;
 
-import java.io.OutputStreamWriter;
-import java.nio.charset.StandardCharsets;
-
 public class BackupAction implements QProfileWsAction {
 
   private final QProfileBackuper backuper;
@@ -71,6 +70,7 @@ public class BackupAction implements QProfileWsAction {
     try {
       String profileKey = QProfileIdentificationParamUtils.getProfileKeyFromParameters(request, profileFactory, session);
       backuper.backup(profileKey, writer);
+      response.setHeader("Content-Disposition", String.format("attachment; filename=%s.xml", profileKey));
     } finally {
       session.close();
       IOUtils.closeQuietly(writer);
index 3fe0b5b96142c7819973d03925dad1747c9558c8..b08c0a6dd85a2674a607878910657bc5cab84f7c 100644 (file)
  */
 package org.sonar.server.ws;
 
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.api.utils.text.XmlWriter;
-import org.sonar.server.plugins.MimeTypes;
-
-import javax.annotation.CheckForNull;
-
 import java.io.ByteArrayOutputStream;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.CheckForNull;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.api.utils.text.XmlWriter;
+import org.sonar.server.plugins.MimeTypes;
 
 public class ServletResponse implements Response {
 
+  private Map<String, String> headers = new HashMap<String, String>();
+
   public static class ServletStream implements Stream {
     private String mediaType;
     private int httpStatus = 200;
@@ -98,4 +101,20 @@ public class ServletResponse implements Response {
     stream.setStatus(204);
     return this;
   }
+
+  @Override
+  public Response setHeader(String name, String value) {
+    headers.put(name, value);
+    return this;
+  }
+
+  @Override
+  public Collection<String> getHeaderNames() {
+    return headers.keySet();
+  }
+
+  @Override
+  public String getHeader(String name) {
+    return headers.get(name);
+  }
 }
index 37c920b63fad1aa3379f1516add9b41234ecd64c..502059c30358035bd7cc028fa7261e190af2b226 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.sonar.server.qualityprofile.ws;
 
+import java.io.PrintWriter;
+import java.io.Writer;
 import org.junit.Before;
 import org.junit.ClassRule;
 import org.junit.Test;
@@ -35,9 +37,6 @@ import org.sonar.server.qualityprofile.QProfileFactory;
 import org.sonar.server.ws.WsTester;
 import org.sonar.server.ws.WsTester.Result;
 
-import java.io.PrintWriter;
-import java.io.Writer;
-
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.eq;
@@ -84,6 +83,7 @@ public class BackupActionTest {
 
     Result result = tester.newGetRequest("api/qualityprofiles", "backup").setParam("profileKey", profileKey).execute();
     assertThat(result.outputAsString()).isEqualTo(response);
+    result.assertHeader("Content-Disposition", "attachment; filename=polop-palap-xoo-12345.xml");
   }
 
   @Test(expected = IllegalArgumentException.class)
index 186feed789d3de9c17ca9faf3ac1ef79923b5de4..5c36bb5834f445d1319a822bab3ca0f3846ace00 100644 (file)
 package org.sonar.server.ws;
 
 import com.google.common.collect.Maps;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Locale;
+import java.util.Map;
+import javax.annotation.Nullable;
 import org.apache.commons.io.IOUtils;
 import org.junit.After;
 import org.junit.Before;
@@ -37,12 +42,6 @@ import org.sonar.server.exceptions.Message;
 import org.sonar.server.plugins.MimeTypes;
 import org.sonar.server.tester.UserSessionRule;
 
-import javax.annotation.Nullable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Locale;
-import java.util.Map;
-
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -291,6 +290,16 @@ public class WebServiceEngineTest {
     assertThat(response.stream().mediaType()).isEqualTo(MimeTypes.JSON);
   }
 
+  @Test
+  public void should_handle_headers() throws Exception {
+    ServletResponse response = new ServletResponse();
+    String name = "Content-Disposition";
+    String value = "attachment; filename=sonarqube.zip";
+    response.setHeader(name, value);
+    assertThat(response.getHeaderNames()).containsExactly(name);
+    assertThat(response.getHeader(name)).isEqualTo(value);
+  }
+
   static class SystemWs implements WebService {
     @Override
     public void define(Context context) {
index eb30c9d303df401cf972c8d436bdd241a53b0e14..db00219e90ffa9e65474944bd4b93e31537552d7 100644 (file)
 package org.sonar.server.ws;
 
 import com.google.common.collect.Maps;
-import org.apache.commons.io.IOUtils;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.server.ws.internal.ValidatingRequest;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.api.utils.text.XmlWriter;
-import org.sonar.server.ws.WsTester.TestResponse.TestStream;
-import org.sonar.test.JsonAssert;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
 import java.io.ByteArrayOutputStream;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -39,7 +27,18 @@ import java.io.OutputStreamWriter;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.nio.charset.StandardCharsets;
+import java.util.Collection;
 import java.util.Map;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.apache.commons.io.IOUtils;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.server.ws.internal.ValidatingRequest;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.api.utils.text.XmlWriter;
+import org.sonar.server.ws.WsTester.TestResponse.TestStream;
+import org.sonar.test.JsonAssert;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.sonar.server.ws.RequestVerifier.verifyRequest;
@@ -104,6 +103,8 @@ public class WsTester {
 
     private TestStream stream;
 
+    private Map<String, String> headers = Maps.newHashMap();
+
     public class TestStream implements Response.Stream {
       private String mediaType;
       private int status;
@@ -165,6 +166,22 @@ public class WsTester {
     public String outputAsString() {
       return new String(output.toByteArray(), StandardCharsets.UTF_8);
     }
+
+    @Override
+    public Response setHeader(String name, String value) {
+      headers.put(name, value);
+      return this;
+    }
+
+    @Override
+    public Collection<String> getHeaderNames() {
+      return headers.keySet();
+    }
+
+    @Override
+    public String getHeader(String name) {
+      return headers.get(name);
+    }
   }
 
   public static class Result {
@@ -220,6 +237,10 @@ public class WsTester {
       return this;
     }
 
+    public Result assertHeader(String name, String value) {
+      assertThat(response.getHeader(name)).isEqualTo(value);
+      return this;
+    }
   }
 
   private final WebService.Context context = new WebService.Context();
index 6fe8c9306262be884532227d0f586b61d7f4a06e..7ee7e58070941d266cecdf74b25c1c7e25fdbc04 100644 (file)
@@ -33,6 +33,10 @@ class Api::JavaWsController < Api::ApiController
     engine = Java::OrgSonarServerPlatform::Platform.component(Java::OrgSonarServerWs::WebServiceEngine.java_class)
     engine.execute(ws_request, ws_response, params[:wspath], params[:wsaction])
 
+    ws_response.getHeaderNames().to_a.each do |name|
+      response.header[name] = ws_response.getHeader(name)
+    end
+
     # response is already written to HttpServletResponse
     render :text => ws_response.stream().output().toByteArray(),
            :status => ws_response.stream().httpStatus(),
index 149ae4178c74b23ab935c927b2169479b6bedae0..39e8b2c1869e0603294ef9779a093e1e0402078f 100644 (file)
  */
 package org.sonar.api.server.ws;
 
+import java.io.OutputStream;
+import java.util.Collection;
+import javax.annotation.CheckForNull;
 import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.api.utils.text.XmlWriter;
 
-import java.io.OutputStream;
-
 /**
  * HTTP response
  *
@@ -43,6 +44,13 @@ public interface Response {
 
   Response noContent();
 
+  Response setHeader(String name, String value);
+
+  Collection<String> getHeaderNames();
+
+  @CheckForNull
+  String getHeader(String name);
+
   Stream stream();
 
 }