From dfa96c89fc0949b7c9c3784078c96ecabf56f1dd Mon Sep 17 00:00:00 2001 From: Duarte Meneses Date: Wed, 13 Jul 2016 11:32:23 +0200 Subject: [PATCH] Fix leaked connection --- .../java/org/sonar/scanner/bootstrap/BatchWsClient.java | 4 ++++ .../repository/DefaultGlobalRepositoriesLoader.java | 3 +-- .../repository/DefaultProjectRepositoriesLoader.java | 7 ++++--- .../main/java/org/sonarqube/ws/client/BaseResponse.java | 6 ++++++ .../main/java/org/sonarqube/ws/client/OkHttpResponse.java | 8 ++++++++ .../src/main/java/org/sonarqube/ws/client/WsResponse.java | 6 +++++- 6 files changed, 28 insertions(+), 6 deletions(-) diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchWsClient.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchWsClient.java index a9066499967..ea47cececbd 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchWsClient.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchWsClient.java @@ -56,6 +56,8 @@ public class BatchWsClient { } /** + * If an exception is not thrown, the response needs to be closed by either calling close() directly, or closing the + * body content's stream/reader. * @throws IllegalStateException if the request could not be executed due to * a connectivity problem or timeout. Because networks can * fail during an exchange, it is possible that the remote server @@ -82,6 +84,7 @@ public class BatchWsClient { private void failIfUnauthorized(WsResponse response) { int code = response.code(); if (code == HTTP_UNAUTHORIZED) { + response.close(); if (hasCredentials) { // credentials are not valid throw MessageException.of(format("Not authorized. Please check the properties %s and %s.", @@ -94,6 +97,7 @@ public class BatchWsClient { } if (code == HTTP_FORBIDDEN || code == HTTP_BAD_REQUEST) { // SONAR-4397 Details are in response content + response.close(); throw MessageException.of(tryParseAsJsonError(response.content())); } response.failIfNotSuccessful(); diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultGlobalRepositoriesLoader.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultGlobalRepositoriesLoader.java index d7140372d45..84a44c49d12 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultGlobalRepositoriesLoader.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultGlobalRepositoriesLoader.java @@ -39,9 +39,8 @@ public class DefaultGlobalRepositoriesLoader implements GlobalRepositoriesLoader @Override public GlobalRepositories load() { GetRequest getRequest = new GetRequest(BATCH_GLOBAL_URL); - Reader reader = wsClient.call(getRequest).contentReader(); String str; - try { + try (Reader reader = wsClient.call(getRequest).contentReader()) { str = IOUtils.toString(reader); } catch (IOException e) { throw new IllegalStateException(e); diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultProjectRepositoriesLoader.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultProjectRepositoriesLoader.java index 5a9283dbac1..cea4a21ba17 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultProjectRepositoriesLoader.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultProjectRepositoriesLoader.java @@ -41,6 +41,7 @@ import org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath; import org.sonarqube.ws.WsBatch.WsProjectResponse.Settings; import org.sonarqube.ws.client.GetRequest; import org.sonarqube.ws.client.HttpException; +import org.sonarqube.ws.client.WsResponse; public class DefaultProjectRepositoriesLoader implements ProjectRepositoriesLoader { private static final Logger LOG = LoggerFactory.getLogger(DefaultProjectRepositoriesLoader.class); @@ -53,9 +54,9 @@ public class DefaultProjectRepositoriesLoader implements ProjectRepositoriesLoad @Override public ProjectRepositories load(String projectKey, boolean issuesMode) { - try { - GetRequest request = new GetRequest(getUrl(projectKey, issuesMode)); - InputStream is = wsClient.call(request).contentStream(); + GetRequest request = new GetRequest(getUrl(projectKey, issuesMode)); + try (WsResponse response = wsClient.call(request)) { + InputStream is = response.contentStream(); return processStream(is, projectKey); } catch (RuntimeException e) { if (shouldThrow(e)) { diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/BaseResponse.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/BaseResponse.java index 2cfcd7448a5..f97a919ec91 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/BaseResponse.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/BaseResponse.java @@ -31,6 +31,7 @@ abstract class BaseResponse implements WsResponse { @Override public WsResponse failIfNotSuccessful() { if (!isSuccessful()) { + close(); throw new HttpException(requestUrl(), code()); } return this; @@ -40,4 +41,9 @@ abstract class BaseResponse implements WsResponse { public boolean hasContent() { return code() != HTTP_NO_CONTENT; } + + @Override + public void close() { + // override if needed + } } diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/OkHttpResponse.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/OkHttpResponse.java index c2a6babc714..ce412f69de8 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/OkHttpResponse.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/OkHttpResponse.java @@ -77,4 +77,12 @@ class OkHttpResponse extends BaseResponse { private RuntimeException fail(Exception e) { throw new IllegalStateException("Fail to read response of " + requestUrl(), e); } + + /** + * Equivalent to closing contentReader or contentStream. + */ + @Override + public void close() { + okResponse.close(); + } } diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/WsResponse.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/WsResponse.java index 89c8977a46d..fc3d83ff177 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/WsResponse.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/WsResponse.java @@ -19,13 +19,14 @@ */ package org.sonarqube.ws.client; +import java.io.Closeable; import java.io.InputStream; import java.io.Reader; /** * @since 5.3 */ -public interface WsResponse { +public interface WsResponse extends Closeable { /** * The absolute requested URL @@ -57,5 +58,8 @@ public interface WsResponse { Reader contentReader(); String content(); + + @Override + void close(); } -- 2.39.5