]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-3941 Improve the batch logs when unauthorized credentials
authorSimon Brandhof <simon.brandhof@gmail.com>
Mon, 19 Nov 2012 17:42:05 +0000 (18:42 +0100)
committerSimon Brandhof <simon.brandhof@gmail.com>
Mon, 19 Nov 2012 17:42:14 +0000 (18:42 +0100)
sonar-batch/pom.xml
sonar-batch/src/main/java/org/sonar/batch/bootstrap/ServerClient.java
sonar-batch/src/test/java/org/sonar/batch/bootstrap/ServerClientTest.java
sonar-plugin-api/src/main/java/org/sonar/api/utils/HttpDownloader.java
sonar-server/src/main/webapp/WEB-INF/app/controllers/batch_bootstrap_controller.rb

index 6e75f40ba40d968c6ca2f34a0e9b7a11cf2f82d7..29421ca58e700f438e6b5cf267d78a335f008268 100644 (file)
       <artifactId>sonar-testing-harness</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.mortbay.jetty</groupId>
+      <artifactId>jetty</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 </project>
index e06c2f53cea4c3b3c35a7356c31b66c72f170b4d..eabee747fa5360ad32222bc17be751d93aeb00f6 100644 (file)
@@ -32,7 +32,6 @@ import org.sonar.api.utils.SonarException;
 import org.sonar.batch.bootstrapper.EnvironmentInformation;
 
 import java.io.File;
-import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
 
@@ -58,6 +57,8 @@ public class ServerClient implements BatchComponent {
     try {
       InputSupplier<InputStream> inputSupplier = doRequest(pathStartingWithSlash);
       Files.copy(inputSupplier, toFile);
+    } catch (HttpDownloader.HttpException he) {
+      throw handleHttpException(he);
     } catch (Exception e) {
       throw new SonarException(String.format("Unable to download '%s' to: %s", pathStartingWithSlash, toFile), e);
     }
@@ -67,7 +68,9 @@ public class ServerClient implements BatchComponent {
     InputSupplier<InputStream> inputSupplier = doRequest(pathStartingWithSlash);
     try {
       return IOUtils.toString(inputSupplier.getInput(), "UTF-8");
-    } catch (IOException e) {
+    } catch (HttpDownloader.HttpException he) {
+      throw handleHttpException(he);
+    } catch (Exception e) {
       throw new SonarException(String.format("Unable to request: %s", pathStartingWithSlash), e);
     }
   }
@@ -91,4 +94,11 @@ public class ServerClient implements BatchComponent {
     }
   }
 
+  private SonarException handleHttpException(HttpDownloader.HttpException he) {
+    if (he.getResponseCode() == 401) {
+      throw new SonarException(String.format("Not authorized. Please check the properties %s and %s.", CoreProperties.LOGIN, CoreProperties.PASSWORD));
+    }
+    throw new SonarException(String.format("Fail to execute request [code=%s, url=%s]", he.getResponseCode(), he.getUri()), he);
+  }
+
 }
index baf74ae58c41fd5c29304cd561c27c4392386fdd..3a0d2dfa570ad520e2f6189d4b87f88bce598025 100644 (file)
  */
 package org.sonar.batch.bootstrap;
 
+import com.google.common.base.Charsets;
+import com.google.common.io.Files;
+import org.apache.commons.io.IOUtils;
+import org.junit.After;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+import org.mortbay.jetty.Handler;
+import org.mortbay.jetty.HttpConnection;
+import org.mortbay.jetty.Request;
+import org.mortbay.jetty.Server;
+import org.mortbay.jetty.handler.AbstractHandler;
 import org.sonar.batch.bootstrapper.EnvironmentInformation;
 
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import java.io.File;
+import java.io.IOException;
+
+import static javax.servlet.http.HttpServletResponse.SC_OK;
+import static org.apache.commons.io.IOUtils.write;
 import static org.fest.assertions.Assertions.assertThat;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
@@ -30,13 +51,153 @@ import static org.mockito.Mockito.when;
 
 public class ServerClientTest {
 
+  MockHttpServer server = null;
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  @Rule
+  public ExpectedException thrown = ExpectedException.none();
+
+  @After
+  public void stopServer() {
+    if (server != null) {
+      server.stop();
+    }
+  }
+
   @Test
   public void shouldRemoveUrlEndingSlash() throws Exception {
     BootstrapSettings settings = mock(BootstrapSettings.class);
     when(settings.getProperty(eq("sonar.host.url"), anyString())).thenReturn("http://localhost:8080/sonar/");
 
-    ServerClient server = new ServerClient(settings, new EnvironmentInformation("Junit", "4"));
+    ServerClient client = new ServerClient(settings, new EnvironmentInformation("Junit", "4"));
+
+    assertThat(client.getURL()).isEqualTo("http://localhost:8080/sonar");
+  }
+
+  @Test
+  public void should_request_url() throws Exception {
+    server = new MockHttpServer();
+    server.start();
+    server.setMockResponseData("this is the content");
+
+    assertThat(newServerClient().request("/foo")).isEqualTo("this is the content");
+  }
+
+  @Test
+  public void should_download_file() throws Exception {
+    server = new MockHttpServer();
+    server.start();
+    server.setMockResponseData("this is the content");
+
+    File file = temp.newFile();
+    newServerClient().download("/foo", file);
+    assertThat(Files.toString(file, Charsets.UTF_8)).isEqualTo("this is the content");
+  }
+
+  @Test
+  public void should_fail_if_unauthorized() throws Exception {
+    server = new MockHttpServer();
+    server.start();
+    server.setMockResponseStatus(401);
+
+    thrown.expectMessage("Not authorized. Please check the properties sonar.login and sonar.password");
+    newServerClient().request("/foo");
+  }
+
+  @Test
+  public void should_fail_if_error() throws Exception {
+    server = new MockHttpServer();
+    server.start();
+    server.setMockResponseStatus(500);
+
+    thrown.expectMessage("Fail to execute request [code=500, url=http://localhost:" + server.getPort() + "/foo]");
+    newServerClient().request("/foo");
+  }
 
-    assertThat(server.getURL()).isEqualTo("http://localhost:8080/sonar");
+  private ServerClient newServerClient() {
+    BootstrapSettings settings = mock(BootstrapSettings.class);
+    when(settings.getProperty(eq("sonar.host.url"), anyString())).thenReturn("http://localhost:" + server.getPort());
+    return new ServerClient(settings, new EnvironmentInformation("Junit", "4"));
   }
+
+
+  static class MockHttpServer {
+    private Server server;
+    private String responseBody;
+    private String requestBody;
+    private String mockResponseData;
+    private int mockResponseStatus = SC_OK;
+
+    public void start() throws Exception {
+      server = new Server(0);
+      server.setHandler(getMockHandler());
+      server.start();
+    }
+
+    /**
+     * Creates an {@link org.mortbay.jetty.handler.AbstractHandler handler} returning an arbitrary String as a response.
+     *
+     * @return never <code>null</code>.
+     */
+    public Handler getMockHandler() {
+      Handler handler = new AbstractHandler() {
+
+        public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) throws IOException, ServletException {
+          Request baseRequest = request instanceof Request ? (Request) request : HttpConnection.getCurrentConnection().getRequest();
+          setResponseBody(getMockResponseData());
+          setRequestBody(IOUtils.toString(baseRequest.getInputStream()));
+          response.setStatus(mockResponseStatus);
+          response.setContentType("text/xml;charset=utf-8");
+          write(getResponseBody(), response.getOutputStream());
+          baseRequest.setHandled(true);
+        }
+      };
+      return handler;
+    }
+
+    public void stop() {
+      try {
+        if (server != null) {
+          server.stop();
+        }
+      } catch (Exception e) {
+        throw new IllegalStateException("Fail to stop HTTP server", e);
+      }
+    }
+
+    public void setResponseBody(String responseBody) {
+      this.responseBody = responseBody;
+    }
+
+    public String getResponseBody() {
+      return responseBody;
+    }
+
+    public void setRequestBody(String requestBody) {
+      this.requestBody = requestBody;
+    }
+
+    public String getRequestBody() {
+      return requestBody;
+    }
+
+    public void setMockResponseData(String mockResponseData) {
+      this.mockResponseData = mockResponseData;
+    }
+
+    public void setMockResponseStatus(int status) {
+      this.mockResponseStatus = status;
+    }
+
+    public String getMockResponseData() {
+      return mockResponseData;
+    }
+
+    public int getPort() {
+      return server.getConnectors()[0].getLocalPort();
+    }
+  }
+
 }
index 2e739d1edbe3f522fb0ed0c60578c5cc6f79ed8c..a9bccf870ec2f6270af996210c046055048cf956 100644 (file)
@@ -249,7 +249,7 @@ public class HttpDownloader extends UriReader.SchemeProcessor implements BatchCo
     }
   }
 
-  public static class HttpException extends IOException {
+  public static class HttpException extends RuntimeException {
     private final URI uri;
     private final int responseCode;
 
index cf89bddff6bf665df427def0d96c328ca312e618..592870aa354f9386ced2f11ab7b1604f668b4af0 100644 (file)
@@ -19,7 +19,7 @@
 #
 
 # Since 3.4
-class BatchBootstrapController < ApplicationController
+class BatchBootstrapController < Api::ApiController
 
   # GET /batch_bootstrap/db?project=<key or id>
   def db