package fr.techad.sonar.gerrit.network.rest; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpHost; import org.apache.http.auth.AuthScheme; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.auth.BasicScheme; import org.apache.http.impl.auth.DigestScheme; import org.apache.http.impl.client.BasicAuthCache; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import org.jetbrains.annotations.NotNull; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import fr.techad.sonar.GerritConfiguration; import fr.techad.sonar.GerritConstants; import fr.techad.sonar.gerrit.GerritConnector; public class GerritRestConnector implements GerritConnector { private static final Logger LOG = Loggers.get(GerritRestConnector.class); private static final String URI_AUTH_PREFIX = "/a"; private static final String URI_CHANGES = "/changes/%s~%s~%s"; private static final String URI_REVISIONS = "/revisions/%s"; private static final String URI_LIST_FILES_SUFFIX = "/files/"; private static final String URI_SET_REVIEW = "/review"; private static int REQUEST_COUNTER; private HttpHost httpHost; private CloseableHttpClient httpClient; private HttpClientContext httpClientContext; private final GerritConfiguration gerritConfiguration; public GerritRestConnector(GerritConfiguration gerritConfiguration) { LOG.debug("[GERRIT PLUGIN] Instanciating GerritConnector"); this.gerritConfiguration = gerritConfiguration; } @NotNull @Override public String listFiles() throws IOException { String getUri = rootUriBuilder(); getUri = getUri.concat(URI_LIST_FILES_SUFFIX); LOG.info("[GERRIT PLUGIN] Listing files from {}", getUri); HttpGet httpGet = new HttpGet(getUri); httpGet.addHeader("Accept", "application/json"); CloseableHttpResponse httpResponse = logAndExecute(httpGet); return consumeAndLogEntity(httpResponse); } @NotNull @Override public String setReview(String reviewInputAsJson) throws IOException { LOG.info("[GERRIT PLUGIN] Setting review {}", reviewInputAsJson); String postUri = rootUriBuilder(); postUri = postUri.concat(URI_SET_REVIEW); LOG.info("[GERRIT PLUGIN] Setting review at {}", postUri); HttpPost httpPost = new HttpPost(postUri); httpPost.setEntity(new StringEntity(reviewInputAsJson, ContentType.APPLICATION_JSON)); CloseableHttpResponse httpResponse = logAndExecute(httpPost); return consumeAndLogEntity(httpResponse); } // Example // http://hc.apache.org/httpcomponents-client-ga/httpclient/examples/org/apache/http/examples/client/ClientPreemptiveDigestAuthentication.java private void createHttpContext() { httpHost = new HttpHost(gerritConfiguration.getHost(), gerritConfiguration.getPort(), gerritConfiguration.getScheme()); httpClientContext = HttpClientContext.create(); if (gerritConfiguration.isAnonymous()) { httpClient = HttpClients.createDefault(); } else { CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); credentialsProvider.setCredentials( new AuthScope(gerritConfiguration.getHost(), gerritConfiguration.getPort()), new UsernamePasswordCredentials(gerritConfiguration.getUsername(), gerritConfiguration.getPassword())); httpClient = HttpClients.custom().setDefaultCredentialsProvider(credentialsProvider).build(); BasicAuthCache basicAuthCache = new BasicAuthCache(); AuthScheme authScheme = null; if (GerritConstants.AUTH_BASIC.equalsIgnoreCase(gerritConfiguration.getHttpAuthScheme())) { authScheme = new BasicScheme(); } else if (GerritConstants.AUTH_DIGEST.equalsIgnoreCase(gerritConfiguration.getHttpAuthScheme())) { authScheme = new DigestScheme(); } else { LOG.error("[GERRIT PLUGIN] createHttpContext called with AUTH_SCHEME {} instead of digest or basic", gerritConfiguration.getHttpAuthScheme()); } basicAuthCache.put(httpHost, authScheme); httpClientContext.setAuthCache(basicAuthCache); } } @NotNull private CloseableHttpResponse logAndExecute(@NotNull HttpRequestBase request) throws IOException { if (null == httpClient || null == httpClientContext || null == httpHost) { createHttpContext(); } LOG.info("[GERRIT PLUGIN] Request {}: {} to {}", new Object[] { ++REQUEST_COUNTER, request.getMethod(), request.getURI().toString() }); CloseableHttpResponse httpResponse = httpClient.execute(httpHost, request, httpClientContext); LOG.info("[GERRIT PLUGIN] Response {}: {}", REQUEST_COUNTER, httpResponse.getStatusLine().toString()); return httpResponse; } @NotNull private String consumeAndLogEntity(@NotNull CloseableHttpResponse response) throws IOException { if (response.getEntity() == null) { if (LOG.isDebugEnabled()) { LOG.debug("[GERRIT PLUGIN] Entity {}: no entity", REQUEST_COUNTER); } return StringUtils.EMPTY; } String content = EntityUtils.toString(response.getEntity()); LOG.info("[GERRIT PLUGIN] Entity {}: {}", REQUEST_COUNTER, content); return content; } @NotNull private String encode(String content) { String result = ""; try { result = URLEncoder.encode(content, "UTF-8"); } catch (UnsupportedEncodingException e) { LOG.error("[GERRIT PLUGIN] Error during encodage", e); } catch (NullPointerException npe) { LOG.warn("[GERRIT PLUGIN] Could not encode. Is content empty ?"); } return result; } @NotNull public String rootUriBuilder() { String basePath = gerritConfiguration.getBasePath(); if ("/".compareTo(basePath) == 0) { basePath = ""; } String uri = basePath; if (!gerritConfiguration.isAnonymous()) { uri = uri.concat(URI_AUTH_PREFIX); } uri = uri.concat(String.format(URI_CHANGES, encode(gerritConfiguration.getProjectName()), encode(gerritConfiguration.getBranchName()), encode(gerritConfiguration.getChangeId()))); uri = uri.concat(String.format(URI_REVISIONS, encode(gerritConfiguration.getRevisionId()))); LOG.debug("[GERRIT PLUGIN] Built URI : {}", uri); return uri; } }