21700: Install Bundler system-wide in Rails postinst
[arvados.git] / sdk / java-v2 / src / main / java / org / arvados / client / api / client / BaseApiClient.java
1 /*
2  * Copyright (C) The Arvados Authors. All rights reserved.
3  *
4  * SPDX-License-Identifier: AGPL-3.0 OR Apache-2.0
5  *
6  */
7
8 package org.arvados.client.api.client;
9
10 import com.fasterxml.jackson.databind.ObjectMapper;
11 import org.arvados.client.exception.ArvadosApiException;
12 import org.arvados.client.api.client.factory.OkHttpClientFactory;
13 import org.arvados.client.api.model.ApiError;
14 import org.arvados.client.config.ConfigProvider;
15 import okhttp3.OkHttpClient;
16 import okhttp3.Request;
17 import okhttp3.Response;
18 import okhttp3.ResponseBody;
19 import org.slf4j.Logger;
20
21 import java.io.IOException;
22 import java.io.UnsupportedEncodingException;
23 import java.net.URLDecoder;
24 import java.nio.charset.StandardCharsets;
25 import java.util.Objects;
26 import java.util.concurrent.TimeUnit;
27
28 abstract class BaseApiClient {
29
30     static final ObjectMapper MAPPER = new ObjectMapper().findAndRegisterModules();
31
32     final OkHttpClient client;
33     final ConfigProvider config;
34     private final Logger log = org.slf4j.LoggerFactory.getLogger(BaseApiClient.class);
35
36     BaseApiClient(ConfigProvider config) {
37         this.config = config;
38         this.client = OkHttpClientFactory.INSTANCE.create(config.isApiHostInsecure())
39             .newBuilder()
40             .connectTimeout(config.getConnectTimeout(), TimeUnit.MILLISECONDS)
41             .readTimeout(config.getReadTimeout(), TimeUnit.MILLISECONDS)
42             .writeTimeout(config.getWriteTimeout(), TimeUnit.MILLISECONDS)
43             .build();
44     }
45
46     Request.Builder getRequestBuilder() {
47         return new Request.Builder()
48                 .addHeader("authorization", String.format("OAuth2 %s", config.getApiToken()))
49                 .addHeader("cache-control", "no-cache");
50     }
51
52     String newCall(Request request) {
53         return (String) getResponseBody(request, body -> body.string().trim());
54     }
55
56     byte[] newFileCall(Request request) {
57         return (byte[]) getResponseBody(request, ResponseBody::bytes);
58     }
59
60     private Object getResponseBody(Request request, Command command) {
61         try {
62             log.debug(URLDecoder.decode(request.toString(), StandardCharsets.UTF_8.name()));
63         } catch (UnsupportedEncodingException e) {
64             throw new ArvadosApiException(e);
65         }
66
67         try (Response response = client.newCall(request).execute()) {
68             ResponseBody responseBody = response.body();
69
70             if (!response.isSuccessful()) {
71                 String errorBody = Objects.requireNonNull(responseBody).string();
72                 if (errorBody == null || errorBody.length() == 0) {
73                     throw new ArvadosApiException(String.format("Error code %s with message: %s", response.code(), response.message()));
74                 }
75                 ApiError apiError = MAPPER.readValue(errorBody, ApiError.class);
76                 throw new ArvadosApiException(String.format("Error code %s with messages: %s", response.code(), apiError.getErrors()));
77             }
78             return command.readResponseBody(responseBody);
79         } catch (IOException e) {
80             throw new ArvadosApiException(e);
81         }
82     }
83
84     private interface Command {
85         Object readResponseBody(ResponseBody body) throws IOException;
86     }
87 }