blob: cf74e0e4e1ab3e594d51f07bb1a90dc0e3abd6bf [file] [log] [blame]
//Copyright (C) 2017 The Android Open Source Project
//
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
package com.googlesource.gerrit.plugins.its.phabricator.conduit;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.googlesource.gerrit.plugins.its.phabricator.conduit.results.CallCapsule;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
/**
* Abstracts the connection to Conduit API
*/
class ConduitConnection {
private static final Logger log = LoggerFactory.getLogger(Conduit.class);
private final String apiUrlBase;
private final Gson gson;
private CloseableHttpClient client;
ConduitConnection(final String baseUrl) {
apiUrlBase = baseUrl.replaceAll("/+$", "") + "/api/";
gson = new Gson();
client = null;
}
/**
* Gives a cached HttpClient
* <p/>
* If no cached HttpClient exists, a new one is spawned.
*
* @return the cached CloseableHttpClient
*/
private CloseableHttpClient getClient() {
if (client == null) {
log.trace("Creating new client connection");
client = HttpClients.createDefault();
}
return client;
}
/**
* Call the given Conduit method without parameters
*
* @param method The name of the method that should get called
* @return The call's result, if there has been no error
* @throws ConduitException
*/
JsonElement call(String method, String token) throws ConduitException {
return call(method, new HashMap<String, Object>(), token);
}
/**
* Calls a conduit method with some parameters
*
* @param method The name of the method that should get called
* @param params A map of parameters to pass to the call
* @return The call's result, if there has been no error
* @throws ConduitException
*/
JsonElement call(String method, Map<String, Object> params, String token) throws ConduitException {
String methodUrl = apiUrlBase + method;
HttpPost httppost = new HttpPost(methodUrl);
if (token != null) {
Map<String, Object> conduitParams = new HashMap<>();
conduitParams.put("token", token);
params.put("__conduit__", conduitParams);
}
String json = gson.toJson(params);
log.trace("Calling phabricator method " + method
+ " with the parameters " + json );
httppost.setEntity(new StringEntity("params=" + json, StandardCharsets.UTF_8));
CloseableHttpResponse response;
try {
response = getClient().execute(httppost);
} catch (IOException e) {
throw new ConduitException("Could not execute Phabricator API call", e);
}
try {
log.trace("Phabricator HTTP response status: " + response.getStatusLine());
HttpEntity entity = response.getEntity();
String entityString;
try {
entityString = EntityUtils.toString(entity);
} catch (IOException e) {
throw new ConduitException("Could not read the API response", e);
}
log.trace("Phabricator response " + entityString);
CallCapsule callCapsule = gson.fromJson(entityString, CallCapsule.class);
log.trace("callCapsule.result: " + callCapsule.getResult());
log.trace("callCapsule.error_code: " + callCapsule.getErrorCode());
log.trace("callCapsule.error_info: " + callCapsule.getErrorInfo());
if (callCapsule.getErrorCode() != null
|| callCapsule.getErrorInfo() != null) {
throw new ConduitErrorException(method, callCapsule.getErrorCode(),
callCapsule.getErrorInfo());
}
return callCapsule.getResult();
} finally {
try {
response.close();
} catch (IOException e) {
throw new ConduitException("Could not close API response", e);
}
}
}
}