Skip to content

Commit 7da272b

Browse files
committed
- tracing the connectivity stack trace for ApiConnectionExceptions by logging the root cause which revealed the real problem
- fix the HTTP Client 5 integration and work with its consuming behavior for HttpResponse Entities - handle the Token secret object being null by falling back to username password credentials - this potential npe for token credentials still needs tracing - seems to happen for empty token credentials in the global sonar server configuration
1 parent 9fd0d34 commit 7da272b

File tree

2 files changed

+19
-16
lines changed

2 files changed

+19
-16
lines changed

src/main/java/org/quality/gates/sonar/api/SonarHttpRequester.java

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
import java.nio.charset.StandardCharsets;
88
import java.util.ArrayList;
99
import java.util.Base64;
10+
import java.util.HashMap;
1011
import java.util.List;
12+
import java.util.Map;
1113
import org.apache.commons.lang.StringUtils;
1214
import org.apache.hc.client5.http.auth.AuthScope;
1315
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
@@ -20,7 +22,6 @@
2022
import org.apache.hc.client5.http.protocol.HttpClientContext;
2123
import org.apache.hc.core5.http.HttpHeaders;
2224
import org.apache.hc.core5.http.NameValuePair;
23-
import org.apache.hc.core5.http.ParseException;
2425
import org.apache.hc.core5.http.io.entity.EntityUtils;
2526
import org.apache.hc.core5.http.message.BasicNameValuePair;
2627
import org.quality.gates.jenkins.plugin.JobConfigData;
@@ -66,7 +67,9 @@ public void setLogged(boolean logged) {
6667
private void loginApi(SonarInstance sonarInstance) {
6768
httpClientContext = HttpClientContext.create();
6869

69-
if (StringUtils.isNotEmpty(sonarInstance.getToken().getPlainText())) {
70+
// For some reason the Token Secret can be null even if empty in the Global Configuration UI
71+
if (sonarInstance.getToken() != null
72+
&& StringUtils.isNotEmpty(sonarInstance.getToken().getPlainText())) {
7073
token = sonarInstance.getToken().getPlainText();
7174
httpClient = HttpClientBuilder.create().build();
7275
} else {
@@ -121,19 +124,23 @@ private String executeGetRequest(CloseableHttpClient client, HttpGet request) th
121124
request.addHeader(HttpHeaders.AUTHORIZATION, authHeader);
122125
}
123126

124-
try (var response = client.execute(request, httpClientContext, classicHttpResponse -> classicHttpResponse)) {
125-
var statusCode = response.getCode();
126-
var entity = response.getEntity();
127-
var returnResponse = EntityUtils.toString(entity);
127+
try {
128+
var responseMap = client.execute(request, httpClientContext, classicHttpResponse -> {
129+
Map<String, Object> retVal = new HashMap<>();
130+
retVal.put("statusCode", classicHttpResponse.getCode());
131+
retVal.put("content", EntityUtils.toString(classicHttpResponse.getEntity()));
132+
return retVal;
133+
});
128134

129-
EntityUtils.consume(entity);
135+
var statusCode = (Integer) responseMap.get("statusCode");
136+
var returnResponse = responseMap.get("content").toString();
130137

131138
if (statusCode != 200) {
132139
throw new QGException("Expected status 200, got: " + statusCode + ". Response: " + returnResponse);
133140
}
134141

135142
return returnResponse;
136-
} catch (IOException | ParseException e) {
143+
} catch (IOException e) {
137144
throw new QGException("GET execution error", e);
138145
}
139146
}

src/main/java/org/quality/gates/sonar/api/SonarHttpRequesterFactory.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
import java.io.IOException;
44
import org.apache.hc.client5.http.classic.methods.HttpGet;
55
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
6-
import org.apache.hc.client5.http.protocol.HttpClientContext;
7-
import org.apache.hc.core5.http.ParseException;
86
import org.apache.hc.core5.http.io.entity.EntityUtils;
97
import org.quality.gates.jenkins.plugin.SonarInstance;
108
import org.quality.gates.sonar.api80.SonarHttpRequester80;
@@ -20,11 +18,9 @@ class SonarHttpRequesterFactory {
2018

2119
static SonarHttpRequester getSonarHttpRequester(SonarInstance sonarInstance) {
2220
var request = new HttpGet(getSonarApiServerVersion(sonarInstance));
23-
var context = HttpClientContext.create();
24-
25-
try (var client = HttpClientBuilder.create().build();
26-
var response = client.execute(request, context, classicHttpResponse -> classicHttpResponse)) {
27-
var sonarVersion = EntityUtils.toString(response.getEntity());
21+
try (var client = HttpClientBuilder.create().build()) {
22+
var sonarVersion = client.execute(
23+
request, classicHttpResponse -> EntityUtils.toString(classicHttpResponse.getEntity()));
2824

2925
if (majorSonarVersion(sonarVersion) == 8 && minorSonarVersion(sonarVersion) <= 7) {
3026
return new SonarHttpRequester80();
@@ -33,7 +29,7 @@ static SonarHttpRequester getSonarHttpRequester(SonarInstance sonarInstance) {
3329
} else {
3430
throw new UnsuportedVersionException("Plugin doesn't support this version of sonar api!");
3531
}
36-
} catch (IOException | ParseException e) {
32+
} catch (IOException e) {
3733
throw new ApiConnectionException(e.getLocalizedMessage(), e);
3834
}
3935
}

0 commit comments

Comments
 (0)