· 6 years ago · Dec 29, 2019, 03:36 PM
1package io.swagger.client.model;
2
3import org.apache.commons.logging.Log;
4import org.apache.commons.logging.LogFactory;
5import org.springframework.beans.factory.annotation.Autowired;
6import org.springframework.core.ParameterizedTypeReference;
7import org.springframework.http.HttpHeaders;
8import org.springframework.http.HttpMethod;
9import org.springframework.http.HttpRequest;
10import org.springframework.http.HttpStatus;
11import org.springframework.http.InvalidMediaTypeException;
12import org.springframework.http.MediaType;
13import org.springframework.http.RequestEntity;
14import org.springframework.http.RequestEntity.BodyBuilder;
15import org.springframework.http.ResponseEntity;
16import org.springframework.http.client.BufferingClientHttpRequestFactory;
17import org.springframework.http.client.ClientHttpRequestExecution;
18import org.springframework.http.client.ClientHttpRequestInterceptor;
19import org.springframework.http.client.ClientHttpResponse;
20import org.springframework.stereotype.Component;
21import org.springframework.util.LinkedMultiValueMap;
22import org.springframework.util.MultiValueMap;
23import org.springframework.util.StringUtils;
24import org.springframework.web.client.RestClientException;
25import org.springframework.web.client.RestTemplate;
26import org.springframework.web.util.UriComponentsBuilder;
27
28import java.io.BufferedReader;
29import java.io.IOException;
30import java.io.InputStream;
31import java.io.InputStreamReader;
32import java.io.UnsupportedEncodingException;
33import java.nio.charset.StandardCharsets;
34import java.text.DateFormat;
35import java.text.ParseException;
36import java.util.Arrays;
37import java.util.ArrayList;
38import java.util.Collection;
39import java.util.Collections;
40import java.util.Date;
41import java.util.HashMap;
42import java.util.Iterator;
43import java.util.List;
44import java.util.Map;
45import java.util.Map.Entry;
46import java.util.TimeZone;
47
48import io.swagger.client.model.auth.Authentication;
49import io.swagger.client.model.auth.HttpBasicAuth;
50import io.swagger.client.model.auth.ApiKeyAuth;
51import io.swagger.client.model.auth.OAuth;
52
53@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2019-12-27T11:24:03.094+02:00")
54@Component("io.swagger.client.model.ApiClient")
55public class ApiClient {
56 public enum CollectionFormat {
57 CSV(","), TSV("\t"), SSV(" "), PIPES("|"), MULTI(null);
58
59 private final String separator;
60 private CollectionFormat(String separator) {
61 this.separator = separator;
62 }
63
64 private String collectionToString(Collection<? extends CharSequence> collection) {
65 return StringUtils.collectionToDelimitedString(collection, separator);
66 }
67 }
68
69 private boolean debugging = false;
70
71 private HttpHeaders defaultHeaders = new HttpHeaders();
72
73 private String basePath = "https://may-path.com";
74
75 private RestTemplate restTemplate;
76
77 private Map<String, Authentication> authentications;
78
79 private DateFormat dateFormat;
80
81 public ApiClient() {
82 this.restTemplate = buildRestTemplate();
83 init();
84 }
85
86 @Autowired
87 public ApiClient(RestTemplate restTemplate) {
88 this.restTemplate = restTemplate;
89 init();
90 }
91
92 protected void init() {
93 // Use RFC3339 format for date and datetime.
94 // See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14
95 this.dateFormat = new RFC3339DateFormat();
96
97 // Use UTC as the default time zone.
98 this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
99
100 // Set default User-Agent.
101 setUserAgent("Java-SDK");
102
103 // Setup authentications (key: authentication name, value: authentication).
104 authentications = new HashMap<String, Authentication>();
105 authentications.put("oauth2_authentication", new OAuth());
106 // Prevent the authentications from being modified.
107 authentications = Collections.unmodifiableMap(authentications);
108 }
109
110 /**
111 * Get the current base path
112 * @return String the base path
113 */
114 public String getBasePath() {
115 return basePath;
116 }
117
118 /**
119 * Set the base path, which should include the host
120 * @param basePath the base path
121 * @return ApiClient this client
122 */
123 public ApiClient setBasePath(String basePath) {
124 this.basePath = basePath;
125 return this;
126 }
127
128 /**
129 * Get authentications (key: authentication name, value: authentication).
130 * @return Map the currently configured authentication types
131 */
132 public Map<String, Authentication> getAuthentications() {
133 return authentications;
134 }
135
136 /**
137 * Get authentication for the given name.
138 *
139 * @param authName The authentication name
140 * @return The authentication, null if not found
141 */
142 public Authentication getAuthentication(String authName) {
143 return authentications.get(authName);
144 }
145
146 /**
147 * Helper method to set username for the first HTTP basic authentication.
148 * @param username the username
149 */
150 public void setUsername(String username) {
151 for (Authentication auth : authentications.values()) {
152 if (auth instanceof HttpBasicAuth) {
153 ((HttpBasicAuth) auth).setUsername(username);
154 return;
155 }
156 }
157 throw new RuntimeException("No HTTP basic authentication configured!");
158 }
159
160 /**
161 * Helper method to set password for the first HTTP basic authentication.
162 * @param password the password
163 */
164 public void setPassword(String password) {
165 for (Authentication auth : authentications.values()) {
166 if (auth instanceof HttpBasicAuth) {
167 ((HttpBasicAuth) auth).setPassword(password);
168 return;
169 }
170 }
171 throw new RuntimeException("No HTTP basic authentication configured!");
172 }
173
174 /**
175 * Helper method to set API key value for the first API key authentication.
176 * @param apiKey the API key
177 */
178 public void setApiKey(String apiKey) {
179 for (Authentication auth : authentications.values()) {
180 if (auth instanceof ApiKeyAuth) {
181 ((ApiKeyAuth) auth).setApiKey(apiKey);
182 return;
183 }
184 }
185 throw new RuntimeException("No API key authentication configured!");
186 }
187
188 /**
189 * Helper method to set API key prefix for the first API key authentication.
190 * @param apiKeyPrefix the API key prefix
191 */
192 public void setApiKeyPrefix(String apiKeyPrefix) {
193 for (Authentication auth : authentications.values()) {
194 if (auth instanceof ApiKeyAuth) {
195 ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix);
196 return;
197 }
198 }
199 throw new RuntimeException("No API key authentication configured!");
200 }
201
202 /**
203 * Helper method to set access token for the first OAuth2 authentication.
204 * @param accessToken the access token
205 */
206 public void setAccessToken(String accessToken) {
207 for (Authentication auth : authentications.values()) {
208 if (auth instanceof OAuth) {
209 ((OAuth) auth).setAccessToken(accessToken);
210 return;
211 }
212 }
213 throw new RuntimeException("No OAuth2 authentication configured!");
214 }
215
216 /**
217 * Set the User-Agent header's value (by adding to the default header map).
218 * @param userAgent the user agent string
219 * @return ApiClient this client
220 */
221 public ApiClient setUserAgent(String userAgent) {
222 addDefaultHeader("User-Agent", userAgent);
223 return this;
224 }
225
226 /**
227 * Add a default header.
228 *
229 * @param name The header's name
230 * @param value The header's value
231 * @return ApiClient this client
232 */
233 public ApiClient addDefaultHeader(String name, String value) {
234 if (defaultHeaders.containsKey(name)) {
235 defaultHeaders.remove(name);
236 }
237 defaultHeaders.add(name, value);
238 return this;
239 }
240
241 public void setDebugging(boolean debugging) {
242 List<ClientHttpRequestInterceptor> currentInterceptors = this.restTemplate.getInterceptors();
243 if(debugging) {
244 if (currentInterceptors == null) {
245 currentInterceptors = new ArrayList<ClientHttpRequestInterceptor>();
246 }
247 ClientHttpRequestInterceptor interceptor = new ApiClientHttpRequestInterceptor();
248 currentInterceptors.add(interceptor);
249 this.restTemplate.setInterceptors(currentInterceptors);
250 } else {
251 if (currentInterceptors != null && !currentInterceptors.isEmpty()) {
252 Iterator<ClientHttpRequestInterceptor> iter = currentInterceptors.iterator();
253 while (iter.hasNext()) {
254 ClientHttpRequestInterceptor interceptor = iter.next();
255 if (interceptor instanceof ApiClientHttpRequestInterceptor) {
256 iter.remove();
257 }
258 }
259 this.restTemplate.setInterceptors(currentInterceptors);
260 }
261 }
262 this.debugging = debugging;
263 }
264
265 /**
266 * Check that whether debugging is enabled for this API client.
267 * @return boolean true if this client is enabled for debugging, false otherwise
268 */
269 public boolean isDebugging() {
270 return debugging;
271 }
272
273 /**
274 * Get the date format used to parse/format date parameters.
275 * @return DateFormat format
276 */
277 public DateFormat getDateFormat() {
278 return dateFormat;
279 }
280
281 /**
282 * Set the date format used to parse/format date parameters.
283 * @param dateFormat Date format
284 * @return API client
285 */
286 public ApiClient setDateFormat(DateFormat dateFormat) {
287 this.dateFormat = dateFormat;
288 return this;
289 }
290
291 /**
292 * Parse the given string into Date object.
293 */
294 public Date parseDate(String str) {
295 try {
296 return dateFormat.parse(str);
297 } catch (ParseException e) {
298 throw new RuntimeException(e);
299 }
300 }
301
302 /**
303 * Format the given Date object into string.
304 */
305 public String formatDate(Date date) {
306 return dateFormat.format(date);
307 }
308
309 /**
310 * Format the given parameter object into string.
311 * @param param the object to convert
312 * @return String the parameter represented as a String
313 */
314 public String parameterToString(Object param) {
315 if (param == null) {
316 return "";
317 } else if (param instanceof Date) {
318 return formatDate( (Date) param);
319 } else if (param instanceof Collection) {
320 StringBuilder b = new StringBuilder();
321 for(Object o : (Collection<?>) param) {
322 if(b.length() > 0) {
323 b.append(",");
324 }
325 b.append(String.valueOf(o));
326 }
327 return b.toString();
328 } else {
329 return String.valueOf(param);
330 }
331 }
332
333 /**
334 * Converts a parameter to a {@link MultiValueMap} for use in REST requests
335 * @param collectionFormat The format to convert to
336 * @param name The name of the parameter
337 * @param value The parameter's value
338 * @return a Map containing the String value(s) of the input parameter
339 */
340 public MultiValueMap<String, String> parameterToMultiValueMap(CollectionFormat collectionFormat, String name, Object value) {
341 final MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
342
343 if (name == null || name.isEmpty() || value == null) {
344 return params;
345 }
346
347 if(collectionFormat == null) {
348 collectionFormat = CollectionFormat.CSV;
349 }
350
351 Collection<?> valueCollection = null;
352 if (value instanceof Collection) {
353 valueCollection = (Collection<?>) value;
354 } else {
355 params.add(name, parameterToString(value));
356 return params;
357 }
358
359 if (valueCollection.isEmpty()){
360 return params;
361 }
362
363 if (collectionFormat.equals(CollectionFormat.MULTI)) {
364 for (Object item : valueCollection) {
365 params.add(name, parameterToString(item));
366 }
367 return params;
368 }
369
370 List<String> values = new ArrayList<String>();
371 for(Object o : valueCollection) {
372 values.add(parameterToString(o));
373 }
374 params.add(name, collectionFormat.collectionToString(values));
375
376 return params;
377 }
378
379 /**
380 * Check if the given {@code String} is a JSON MIME.
381 * @param mediaType the input MediaType
382 * @return boolean true if the MediaType represents JSON, false otherwise
383 */
384 public boolean isJsonMime(String mediaType) {
385 // "* / *" is default to JSON
386 if ("*/*".equals(mediaType)) {
387 return true;
388 }
389
390 try {
391 return isJsonMime(MediaType.parseMediaType(mediaType));
392 } catch (InvalidMediaTypeException e) {
393 }
394 return false;
395 }
396
397 /**
398 * Check if the given MIME is a JSON MIME.
399 * JSON MIME examples:
400 * application/json
401 * application/json; charset=UTF8
402 * APPLICATION/JSON
403 * @param mediaType the input MediaType
404 * @return boolean true if the MediaType represents JSON, false otherwise
405 */
406 public boolean isJsonMime(MediaType mediaType) {
407 return mediaType != null && (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType) || mediaType.getSubtype().matches("^.*\\+json[;]?\\s*$"));
408 }
409
410 /**
411 * Select the Accept header's value from the given accepts array:
412 * if JSON exists in the given array, use it;
413 * otherwise use all of them (joining into a string)
414 *
415 * @param accepts The accepts array to select from
416 * @return List The list of MediaTypes to use for the Accept header
417 */
418 public List<MediaType> selectHeaderAccept(String[] accepts) {
419 if (accepts.length == 0) {
420 return null;
421 }
422 for (String accept : accepts) {
423 MediaType mediaType = MediaType.parseMediaType(accept);
424 if (isJsonMime(mediaType)) {
425 return Collections.singletonList(mediaType);
426 }
427 }
428 return MediaType.parseMediaTypes(StringUtils.arrayToCommaDelimitedString(accepts));
429 }
430
431 /**
432 * Select the Content-Type header's value from the given array:
433 * if JSON exists in the given array, use it;
434 * otherwise use the first one of the array.
435 *
436 * @param contentTypes The Content-Type array to select from
437 * @return MediaType The Content-Type header to use. If the given array is empty, JSON will be used.
438 */
439 public MediaType selectHeaderContentType(String[] contentTypes) {
440 if (contentTypes.length == 0) {
441 return MediaType.APPLICATION_JSON;
442 }
443 for (String contentType : contentTypes) {
444 MediaType mediaType = MediaType.parseMediaType(contentType);
445 if (isJsonMime(mediaType)) {
446 return mediaType;
447 }
448 }
449 return MediaType.parseMediaType(contentTypes[0]);
450 }
451
452 /**
453 * Select the body to use for the request
454 * @param obj the body object
455 * @param formParams the form parameters
456 * @param contentType the content type of the request
457 * @return Object the selected body
458 */
459 protected Object selectBody(Object obj, MultiValueMap<String, Object> formParams, MediaType contentType) {
460 boolean isForm = MediaType.MULTIPART_FORM_DATA.isCompatibleWith(contentType) || MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(contentType);
461 return isForm ? formParams : obj;
462 }
463
464 /**
465 * Invoke API by sending HTTP request with the given options.
466 *
467 * @param <T> the return type to use
468 * @param path The sub-path of the HTTP URL
469 * @param method The request method
470 * @param queryParams The query parameters
471 * @param body The request body object
472 * @param headerParams The header parameters
473 * @param formParams The form parameters
474 * @param accept The request's Accept header
475 * @param contentType The request's Content-Type header
476 * @param authNames The authentications to apply
477 * @param returnType The return type into which to deserialize the response
478 * @return ResponseEntity<T> The response of the chosen type
479 */
480 public <T> ResponseEntity<T> invokeAPI(String path, HttpMethod method, MultiValueMap<String, String> queryParams, Object body, HttpHeaders headerParams, MultiValueMap<String, Object> formParams, List<MediaType> accept, MediaType contentType, String[] authNames, ParameterizedTypeReference<T> returnType) throws RestClientException {
481 updateParamsForAuth(authNames, queryParams, headerParams);
482
483 final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(path);
484 if (queryParams != null) {
485 builder.queryParams(queryParams);
486 }
487
488 final BodyBuilder requestBuilder = RequestEntity.method(method, builder.build().toUri());
489 if(accept != null) {
490 requestBuilder.accept(accept.toArray(new MediaType[accept.size()]));
491 }
492 if(contentType != null) {
493 requestBuilder.contentType(contentType);
494 }
495
496 addHeadersToRequest(headerParams, requestBuilder);
497 addHeadersToRequest(defaultHeaders, requestBuilder);
498
499 RequestEntity<Object> requestEntity = requestBuilder.body(selectBody(body, formParams, contentType));
500
501 ResponseEntity<T> responseEntity = restTemplate.exchange(requestEntity, returnType);
502
503 if (responseEntity.getStatusCode().is2xxSuccessful()) {
504 return responseEntity;
505 } else {
506 // The error handler built into the RestTemplate should handle 400 and 500 series errors.
507 throw new RestClientException("API returned " + responseEntity.getStatusCode() + " and it wasn't handled by the RestTemplate error handler");
508 }
509 }
510
511 /**
512 * Add headers to the request that is being built
513 * @param headers The headers to add
514 * @param requestBuilder The current request
515 */
516 protected void addHeadersToRequest(HttpHeaders headers, BodyBuilder requestBuilder) {
517 for (Entry<String, List<String>> entry : headers.entrySet()) {
518 List<String> values = entry.getValue();
519 for(String value : values) {
520 if (value != null) {
521 requestBuilder.header(entry.getKey(), value);
522 }
523 }
524 }
525 }
526
527 /**
528 * Build the RestTemplate used to make HTTP requests.
529 * @return RestTemplate
530 */
531 protected RestTemplate buildRestTemplate() {
532 RestTemplate restTemplate = new RestTemplate();
533 // This allows us to read the response more than once - Necessary for debugging.
534 restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(restTemplate.getRequestFactory()));
535 return restTemplate;
536 }
537
538 /**
539 * Update query and header parameters based on authentication settings.
540 *
541 * @param authNames The authentications to apply
542 * @param queryParams The query parameters
543 * @param headerParams The header parameters
544 */
545 private void updateParamsForAuth(String[] authNames, MultiValueMap<String, String> queryParams, HttpHeaders headerParams) {
546 for (String authName : authNames) {
547 Authentication auth = authentications.get(authName);
548 if (auth == null) {
549 throw new RestClientException("Authentication undefined: " + authName);
550 }
551 auth.applyToParams(queryParams, headerParams);
552 }
553 }
554
555 private class ApiClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
556 private final Log log = LogFactory.getLog(ApiClientHttpRequestInterceptor.class);
557
558 @Override
559 public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
560 logRequest(request, body);
561 ClientHttpResponse response = execution.execute(request, body);
562 logResponse(response);
563 return response;
564 }
565
566 private void logRequest(HttpRequest request, byte[] body) throws UnsupportedEncodingException {
567 log.info("URI: " + request.getURI());
568 log.info("HTTP Method: " + request.getMethod());
569 log.info("HTTP Headers: " + headersToString(request.getHeaders()));
570 log.info("Request Body: " + new String(body, StandardCharsets.UTF_8));
571 }
572
573 private void logResponse(ClientHttpResponse response) throws IOException {
574 log.info("HTTP Status Code: " + response.getRawStatusCode());
575 log.info("Status Text: " + response.getStatusText());
576 log.info("HTTP Headers: " + headersToString(response.getHeaders()));
577 log.info("Response Body: " + bodyToString(response.getBody()));
578 }
579
580 private String headersToString(HttpHeaders headers) {
581 StringBuilder builder = new StringBuilder();
582 for(Entry<String, List<String>> entry : headers.entrySet()) {
583 builder.append(entry.getKey()).append("=[");
584 for(String value : entry.getValue()) {
585 builder.append(value).append(",");
586 }
587 builder.setLength(builder.length() - 1); // Get rid of trailing comma
588 builder.append("],");
589 }
590 builder.setLength(builder.length() - 1); // Get rid of trailing comma
591 return builder.toString();
592 }
593
594 private String bodyToString(InputStream body) throws IOException {
595 StringBuilder builder = new StringBuilder();
596 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(body, StandardCharsets.UTF_8));
597 String line = bufferedReader.readLine();
598 while (line != null) {
599 builder.append(line).append(System.lineSeparator());
600 line = bufferedReader.readLine();
601 }
602 bufferedReader.close();
603 return builder.toString();
604 }
605 }
606}