github.com/phrase/openapi@v0.0.0-20240514140800-49e8a106740e/openapi-generator/templates/java/ApiClient.mustache (about) 1 {{>licenseInfo}} 2 package {{invokerPackage}}; 3 4 {{#threetenbp}} 5 import org.threeten.bp.*; 6 7 {{/threetenbp}} 8 import com.fasterxml.jackson.annotation.*; 9 import com.fasterxml.jackson.databind.*; 10 {{#joda}} 11 import com.fasterxml.jackson.datatype.joda.JodaModule; 12 {{/joda}} 13 {{#java8}} 14 import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 15 {{/java8}} 16 {{#threetenbp}} 17 import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; 18 {{/threetenbp}} 19 import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; 20 21 import com.sun.jersey.api.client.Client; 22 import com.sun.jersey.api.client.ClientResponse; 23 import com.sun.jersey.api.client.GenericType; 24 import com.sun.jersey.api.client.config.DefaultClientConfig; 25 import com.sun.jersey.api.client.filter.GZIPContentEncodingFilter; 26 import com.sun.jersey.api.client.filter.LoggingFilter; 27 import com.sun.jersey.api.client.WebResource.Builder; 28 29 import com.sun.jersey.multipart.FormDataMultiPart; 30 import com.sun.jersey.multipart.file.FileDataBodyPart; 31 32 import javax.ws.rs.core.Cookie; 33 import javax.ws.rs.core.Response.Status.Family; 34 import javax.ws.rs.core.MediaType; 35 36 import java.util.Collection; 37 import java.util.Collections; 38 import java.util.Map; 39 import java.util.Map.Entry; 40 import java.util.HashMap; 41 import java.util.HashSet; 42 import java.util.List; 43 import java.util.Arrays; 44 import java.util.ArrayList; 45 import java.util.Date; 46 import java.util.TimeZone; 47 48 import java.net.URLEncoder; 49 50 import java.io.File; 51 import java.io.UnsupportedEncodingException; 52 53 import java.text.DateFormat; 54 55 import {{invokerPackage}}.auth.Authentication; 56 import {{invokerPackage}}.auth.HttpBasicAuth; 57 import {{invokerPackage}}.auth.HttpBearerAuth; 58 import {{invokerPackage}}.auth.ApiKeyAuth; 59 {{#hasOAuthMethods}} 60 import {{invokerPackage}}.auth.OAuth; 61 {{/hasOAuthMethods}} 62 63 {{>generatedAnnotation}} 64 public class ApiClient { 65 private Map<String, String> defaultHeaderMap = new HashMap<String, String>(); 66 private Map<String, String> defaultCookieMap = new HashMap<String, String>(); 67 private String basePath = "{{{basePath}}}"; 68 protected List<ServerConfiguration> servers = new ArrayList<ServerConfiguration>({{#servers}}{{#-first}}Arrays.asList( 69 {{/-first}} new ServerConfiguration( 70 "{{{url}}}", 71 "{{{description}}}{{^description}}No description provided{{/description}}", 72 new HashMap<String, ServerVariable>(){{#variables}}{{#-first}} {{ 73 {{/-first}} put("{{{name}}}", new ServerVariable( 74 "{{{description}}}{{^description}}No description provided{{/description}}", 75 "{{{defaultValue}}}", 76 new HashSet<String>( 77 {{#enumValues}} 78 {{#-first}} 79 Arrays.asList( 80 {{/-first}} 81 "{{{.}}}"{{^-last}},{{/-last}} 82 {{#-last}} 83 ) 84 {{/-last}} 85 {{/enumValues}} 86 ) 87 )); 88 {{#-last}} 89 }}{{/-last}}{{/variables}} 90 ){{^-last}},{{/-last}} 91 {{#-last}} 92 ){{/-last}}{{/servers}}); 93 protected Integer serverIndex = 0; 94 protected Map<String, String> serverVariables = null; 95 private boolean debugging = false; 96 private int connectionTimeout = 0; 97 98 private Client httpClient; 99 private ObjectMapper objectMapper; 100 101 private Map<String, Authentication> authentications; 102 103 private int statusCode; 104 private Map<String, List<String>> responseHeaders; 105 106 private DateFormat dateFormat; 107 108 public ApiClient() { 109 objectMapper = new ObjectMapper(); 110 objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 111 objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 112 objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); 113 objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); 114 objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); 115 objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); 116 {{#joda}} 117 objectMapper.registerModule(new JodaModule()); 118 {{/joda}} 119 {{#java8}} 120 objectMapper.registerModule(new JavaTimeModule()); 121 {{/java8}} 122 {{#threetenbp}} 123 ThreeTenModule module = new ThreeTenModule(); 124 module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); 125 module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); 126 module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); 127 objectMapper.registerModule(module); 128 {{/threetenbp}} 129 objectMapper.setDateFormat(ApiClient.buildDefaultDateFormat()); 130 131 dateFormat = ApiClient.buildDefaultDateFormat(); 132 133 // Set default User-Agent. 134 setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); 135 136 // Setup authentications (key: authentication name, value: authentication). 137 authentications = new HashMap<String, Authentication>();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} 138 authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} 139 authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} 140 authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} 141 authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} 142 // Prevent the authentications from being modified. 143 authentications = Collections.unmodifiableMap(authentications); 144 145 rebuildHttpClient(); 146 } 147 148 public static DateFormat buildDefaultDateFormat() { 149 return new RFC3339DateFormat(); 150 } 151 152 /** 153 * Build the Client used to make HTTP requests with the latest settings, 154 * i.e. objectMapper and debugging. 155 * TODO: better to use the Builder Pattern? 156 * @return API client 157 */ 158 public ApiClient rebuildHttpClient() { 159 // Add the JSON serialization support to Jersey 160 JacksonJsonProvider jsonProvider = new JacksonJsonProvider(objectMapper); 161 DefaultClientConfig conf = new DefaultClientConfig(); 162 conf.getSingletons().add(jsonProvider); 163 Client client = Client.create(conf); 164 client.addFilter(new GZIPContentEncodingFilter({{#useGzipFeature}}true{{/useGzipFeature}}{{^useGzipFeature}}false{{/useGzipFeature}})); 165 if (debugging) { 166 client.addFilter(new LoggingFilter()); 167 } 168 this.httpClient = client; 169 return this; 170 } 171 172 /** 173 * Returns the current object mapper used for JSON serialization/deserialization. 174 * <p> 175 * Note: If you make changes to the object mapper, remember to set it back via 176 * <code>setObjectMapper</code> in order to trigger HTTP client rebuilding. 177 * </p> 178 * @return Object mapper 179 */ 180 public ObjectMapper getObjectMapper() { 181 return objectMapper; 182 } 183 184 public ApiClient setObjectMapper(ObjectMapper objectMapper) { 185 this.objectMapper = objectMapper; 186 // Need to rebuild the Client as it depends on object mapper. 187 rebuildHttpClient(); 188 return this; 189 } 190 191 public Client getHttpClient() { 192 return httpClient; 193 } 194 195 public ApiClient setHttpClient(Client httpClient) { 196 this.httpClient = httpClient; 197 return this; 198 } 199 200 public String getBasePath() { 201 return basePath; 202 } 203 204 public ApiClient setBasePath(String basePath) { 205 this.basePath = basePath; 206 return this; 207 } 208 209 public List<ServerConfiguration> getServers() { 210 return servers; 211 } 212 213 public ApiClient setServers(List<ServerConfiguration> servers) { 214 this.servers = servers; 215 return this; 216 } 217 218 public Integer getServerIndex() { 219 return serverIndex; 220 } 221 222 public ApiClient setServerIndex(Integer serverIndex) { 223 this.serverIndex = serverIndex; 224 return this; 225 } 226 227 public Map<String, String> getServerVariables() { 228 return serverVariables; 229 } 230 231 public ApiClient setServerVariables(Map<String, String> serverVariables) { 232 this.serverVariables = serverVariables; 233 return this; 234 } 235 236 /** 237 * Gets the status code of the previous request 238 * @return Status code 239 */ 240 public int getStatusCode() { 241 return statusCode; 242 } 243 244 /** 245 * Gets the response headers of the previous request 246 * @return Response headers 247 */ 248 public Map<String, List<String>> getResponseHeaders() { 249 return responseHeaders; 250 } 251 252 /** 253 * Get authentications (key: authentication name, value: authentication). 254 * @return Map of authentication 255 */ 256 public Map<String, Authentication> getAuthentications() { 257 return authentications; 258 } 259 260 /** 261 * Get authentication for the given name. 262 * 263 * @param authName The authentication name 264 * @return The authentication, null if not found 265 */ 266 public Authentication getAuthentication(String authName) { 267 return authentications.get(authName); 268 } 269 270 /** 271 * Helper method to set username for the first HTTP basic authentication. 272 * @param username Username 273 */ 274 public void setUsername(String username) { 275 for (Authentication auth : authentications.values()) { 276 if (auth instanceof HttpBasicAuth) { 277 ((HttpBasicAuth) auth).setUsername(username); 278 return; 279 } 280 } 281 throw new RuntimeException("No HTTP basic authentication configured!"); 282 } 283 284 /** 285 * Helper method to set password for the first HTTP basic authentication. 286 * @param password Password 287 */ 288 public void setPassword(String password) { 289 for (Authentication auth : authentications.values()) { 290 if (auth instanceof HttpBasicAuth) { 291 ((HttpBasicAuth) auth).setPassword(password); 292 return; 293 } 294 } 295 throw new RuntimeException("No HTTP basic authentication configured!"); 296 } 297 298 /** 299 * Helper method to set API key value for the first API key authentication. 300 * @param apiKey the API key 301 */ 302 public void setApiKey(String apiKey) { 303 for (Authentication auth : authentications.values()) { 304 if (auth instanceof ApiKeyAuth) { 305 ((ApiKeyAuth) auth).setApiKey(apiKey); 306 return; 307 } 308 } 309 throw new RuntimeException("No API key authentication configured!"); 310 } 311 312 /** 313 * Helper method to set API key prefix for the first API key authentication. 314 * @param apiKeyPrefix API key prefix 315 */ 316 public void setApiKeyPrefix(String apiKeyPrefix) { 317 for (Authentication auth : authentications.values()) { 318 if (auth instanceof ApiKeyAuth) { 319 ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); 320 return; 321 } 322 } 323 throw new RuntimeException("No API key authentication configured!"); 324 } 325 326 {{#hasOAuthMethods}} 327 /** 328 * Helper method to set access token for the first OAuth2 authentication. 329 * @param accessToken Access token 330 */ 331 public void setAccessToken(String accessToken) { 332 for (Authentication auth : authentications.values()) { 333 if (auth instanceof OAuth) { 334 ((OAuth) auth).setAccessToken(accessToken); 335 return; 336 } 337 } 338 throw new RuntimeException("No OAuth2 authentication configured!"); 339 } 340 341 {{/hasOAuthMethods}} 342 343 /** 344 * Helper method to set access token for the first Bearer authentication. 345 * @param bearerToken Bearer token 346 */ 347 public void setBearerToken(String bearerToken) { 348 for (Authentication auth : authentications.values()) { 349 if (auth instanceof HttpBearerAuth) { 350 ((HttpBearerAuth) auth).setBearerToken(bearerToken); 351 return; 352 } 353 } 354 throw new RuntimeException("No Bearer authentication configured!"); 355 } 356 357 /** 358 * Set the User-Agent header's value (by adding to the default header map). 359 * @param userAgent User agent 360 * @return API client 361 */ 362 public ApiClient setUserAgent(String userAgent) { 363 addDefaultHeader("User-Agent", userAgent); 364 return this; 365 } 366 367 /** 368 * Add a default header. 369 * 370 * @param key The header's key 371 * @param value The header's value 372 * @return API client 373 */ 374 public ApiClient addDefaultHeader(String key, String value) { 375 defaultHeaderMap.put(key, value); 376 return this; 377 } 378 379 /** 380 * Add a default cookie. 381 * 382 * @param key The cookie's key 383 * @param value The cookie's value 384 * @return API client 385 */ 386 public ApiClient addDefaultCookie(String key, String value) { 387 defaultCookieMap.put(key, value); 388 return this; 389 } 390 391 /** 392 * Check that whether debugging is enabled for this API client. 393 * @return True if debugging is on 394 */ 395 public boolean isDebugging() { 396 return debugging; 397 } 398 399 /** 400 * Enable/disable debugging for this API client. 401 * 402 * @param debugging To enable (true) or disable (false) debugging 403 * @return API client 404 */ 405 public ApiClient setDebugging(boolean debugging) { 406 this.debugging = debugging; 407 // Need to rebuild the Client as it depends on the value of debugging. 408 rebuildHttpClient(); 409 return this; 410 } 411 412 /** 413 * Connect timeout (in milliseconds). 414 * @return Connection timeout 415 */ 416 public int getConnectTimeout() { 417 return connectionTimeout; 418 } 419 420 /** 421 * Set the connect timeout (in milliseconds). 422 * A value of 0 means no timeout, otherwise values must be between 1 and 423 * {@link Integer#MAX_VALUE}. 424 * @param connectionTimeout Connection timeout in milliseconds 425 * @return API client 426 */ 427 public ApiClient setConnectTimeout(int connectionTimeout) { 428 this.connectionTimeout = connectionTimeout; 429 httpClient.setConnectTimeout(connectionTimeout); 430 return this; 431 } 432 433 /** 434 * Get the date format used to parse/format date parameters. 435 * @return Date format 436 */ 437 public DateFormat getDateFormat() { 438 return dateFormat; 439 } 440 441 /** 442 * Set the date format used to parse/format date parameters. 443 * @param dateFormat Date format 444 * @return API client 445 */ 446 public ApiClient setDateFormat(DateFormat dateFormat) { 447 this.dateFormat = dateFormat; 448 // Also set the date format for model (de)serialization with Date properties. 449 this.objectMapper.setDateFormat((DateFormat) dateFormat.clone()); 450 // Need to rebuild the Client as objectMapper changes. 451 rebuildHttpClient(); 452 return this; 453 } 454 455 /** 456 * Parse the given string into Date object. 457 * @param str String 458 * @return Date 459 */ 460 public Date parseDate(String str) { 461 try { 462 return dateFormat.parse(str); 463 } catch (java.text.ParseException e) { 464 throw new RuntimeException(e); 465 } 466 } 467 468 /** 469 * Format the given Date object into string. 470 * @param date Date 471 * @return Date in string format 472 */ 473 public String formatDate(Date date) { 474 return dateFormat.format(date); 475 } 476 477 /** 478 * Format the given parameter object into string. 479 * @param param Object 480 * @return Object in string format 481 */ 482 public String parameterToString(Object param) { 483 if (param == null) { 484 return ""; 485 } else if (param instanceof Date) { 486 return formatDate((Date) param); 487 } else if (param instanceof Collection) { 488 StringBuilder b = new StringBuilder(); 489 for(Object o : (Collection<?>)param) { 490 if(b.length() > 0) { 491 b.append(','); 492 } 493 b.append(String.valueOf(o)); 494 } 495 return b.toString(); 496 } else { 497 return String.valueOf(param); 498 } 499 } 500 501 /** 502 * Formats the specified query parameter to a list containing a single {@code Pair} object. 503 * 504 * Note that {@code value} must not be a collection. 505 * 506 * @param name The name of the parameter. 507 * @param value The value of the parameter. 508 * @return A list containing a single {@code Pair} object. 509 */ 510 public List<Pair> parameterToPair(String name, Object value) { 511 List<Pair> params = new ArrayList<Pair>(); 512 513 // preconditions 514 if (name == null || name.isEmpty() || value == null || value instanceof Collection) return params; 515 516 params.add(new Pair(name, parameterToString(value))); 517 return params; 518 } 519 520 /** 521 * Formats the specified collection query parameters to a list of {@code Pair} objects. 522 * 523 * Note that the values of each of the returned Pair objects are percent-encoded. 524 * 525 * @param collectionFormat The collection format of the parameter. 526 * @param name The name of the parameter. 527 * @param value The value of the parameter. 528 * @return A list of {@code Pair} objects. 529 */ 530 public List<Pair> parameterToPairs(String collectionFormat, String name, Collection value) { 531 List<Pair> params = new ArrayList<Pair>(); 532 533 // preconditions 534 if (name == null || name.isEmpty() || value == null) { 535 return params; 536 } 537 538 // create the params based on the collection format 539 if ("multi".equals(collectionFormat)) { 540 for (Object item : value) { 541 params.add(new Pair(name, escapeString(parameterToString(item)))); 542 } 543 return params; 544 } 545 546 // collectionFormat is assumed to be "csv" by default 547 String delimiter = ","; 548 549 // escape all delimiters except commas, which are URI reserved 550 // characters 551 if ("ssv".equals(collectionFormat)) { 552 delimiter = escapeString(" "); 553 } else if ("tsv".equals(collectionFormat)) { 554 delimiter = escapeString("\t"); 555 } else if ("pipes".equals(collectionFormat)) { 556 delimiter = escapeString("|"); 557 } 558 559 StringBuilder sb = new StringBuilder() ; 560 for (Object item : value) { 561 sb.append(delimiter); 562 sb.append(escapeString(parameterToString(item))); 563 } 564 565 params.add(new Pair(name, sb.substring(delimiter.length()))); 566 567 return params; 568 } 569 570 /** 571 * Check if the given MIME is a JSON MIME. 572 * JSON MIME examples: 573 * application/json 574 * application/json; charset=UTF8 575 * APPLICATION/JSON 576 * application/vnd.company+json 577 * @param mime MIME 578 * @return True if MIME type is boolean 579 */ 580 public boolean isJsonMime(String mime) { 581 String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$"; 582 return mime != null && (mime.matches(jsonMime) || mime.equals("*/*")); 583 } 584 585 /** 586 * Select the Accept header's value from the given accepts array: 587 * if JSON exists in the given array, use it; 588 * otherwise use all of them (joining into a string) 589 * 590 * @param accepts The accepts array to select from 591 * @return The Accept header to use. If the given array is empty, 592 * null will be returned (not to set the Accept header explicitly). 593 */ 594 public String selectHeaderAccept(String[] accepts) { 595 if (accepts.length == 0) { 596 return null; 597 } 598 for (String accept : accepts) { 599 if (isJsonMime(accept)) { 600 return accept; 601 } 602 } 603 return StringUtil.join(accepts, ","); 604 } 605 606 /** 607 * Select the Content-Type header's value from the given array: 608 * if JSON exists in the given array, use it; 609 * otherwise use the first one of the array. 610 * 611 * @param contentTypes The Content-Type array to select from 612 * @return The Content-Type header to use. If the given array is empty, 613 * or matches "any", JSON will be used. 614 */ 615 public String selectHeaderContentType(String[] contentTypes) { 616 if (contentTypes.length == 0 || contentTypes[0].equals("*/*")) { 617 return "application/json"; 618 } 619 for (String contentType : contentTypes) { 620 if (isJsonMime(contentType)) { 621 return contentType; 622 } 623 } 624 return contentTypes[0]; 625 } 626 627 /** 628 * Escape the given string to be used as URL query value. 629 * @param str String 630 * @return Escaped string 631 */ 632 public String escapeString(String str) { 633 try { 634 return URLEncoder.encode(str, "utf8").replaceAll("\\+", "%20"); 635 } catch (UnsupportedEncodingException e) { 636 return str; 637 } 638 } 639 640 /** 641 * Serialize the given Java object into string according the given 642 * Content-Type (only JSON is supported for now). 643 * @param obj Object 644 * @param contentType Content type 645 * @param formParams Form parameters 646 * @return Object 647 * @throws ApiException API exception 648 */ 649 public Object serialize(Object obj, String contentType, Map<String, Object> formParams) throws ApiException { 650 if (contentType.startsWith("multipart/form-data")) { 651 FormDataMultiPart mp = new FormDataMultiPart(); 652 for (Entry<String, Object> param: formParams.entrySet()) { 653 if( param.getValue() instanceof List && !( ( List ) param.getValue() ).isEmpty() 654 && ( ( List ) param.getValue() ).get( 0 ) instanceof File ) { 655 @SuppressWarnings( "unchecked" ) 656 List<File> files = ( List<File> ) param.getValue(); 657 for( File file : files ) { 658 mp.bodyPart( new FileDataBodyPart( param.getKey(), file, MediaType.APPLICATION_OCTET_STREAM_TYPE ) ); 659 } 660 } else if (param.getValue() instanceof File) { 661 File file = (File) param.getValue(); 662 mp.bodyPart(new FileDataBodyPart(param.getKey(), file, MediaType.APPLICATION_OCTET_STREAM_TYPE)); 663 } else { 664 mp.field(param.getKey(), parameterToString(param.getValue()), MediaType.MULTIPART_FORM_DATA_TYPE); 665 } 666 } 667 return mp; 668 } else if (contentType.startsWith("application/x-www-form-urlencoded")) { 669 return this.getXWWWFormUrlencodedParams(formParams); 670 } else { 671 // We let Jersey attempt to serialize the body 672 return obj; 673 } 674 } 675 676 /** 677 * Build full URL by concatenating base path, the given sub path and query parameters. 678 * 679 * @param path The sub path 680 * @param queryParams The query parameters 681 * @param collectionQueryParams The collection query parameters 682 * @return The full URL 683 */ 684 private String buildUrl(String path, List<Pair> queryParams, List<Pair> collectionQueryParams) { 685 String baseURL; 686 if (serverIndex != null) { 687 if (serverIndex < 0 || serverIndex >= servers.size()) { 688 throw new ArrayIndexOutOfBoundsException(String.format( 689 "Invalid index %d when selecting the host settings. Must be less than %d", serverIndex, servers.size() 690 )); 691 } 692 baseURL = servers.get(serverIndex).URL(serverVariables); 693 } else { 694 baseURL = basePath; 695 } 696 697 final StringBuilder url = new StringBuilder(); 698 url.append(baseURL).append(path); 699 700 if (queryParams != null && !queryParams.isEmpty()) { 701 // support (constant) query string in `path`, e.g. "/posts?draft=1" 702 String prefix = path.contains("?") ? "&" : "?"; 703 for (Pair param : queryParams) { 704 if (param.getValue() != null) { 705 if (prefix != null) { 706 url.append(prefix); 707 prefix = null; 708 } else { 709 url.append("&"); 710 } 711 String value = parameterToString(param.getValue()); 712 url.append(escapeString(param.getName())).append("=").append(escapeString(value)); 713 } 714 } 715 } 716 717 if (collectionQueryParams != null && !collectionQueryParams.isEmpty()) { 718 String prefix = url.toString().contains("?") ? "&" : "?"; 719 for (Pair param : collectionQueryParams) { 720 if (param.getValue() != null) { 721 if (prefix != null) { 722 url.append(prefix); 723 prefix = null; 724 } else { 725 url.append("&"); 726 } 727 String value = parameterToString(param.getValue()); 728 // collection query parameter value already escaped as part of parameterToPairs 729 url.append(escapeString(param.getName())).append("=").append(value); 730 } 731 } 732 } 733 734 return url.toString(); 735 } 736 737 private ClientResponse getAPIResponse(String path, String method, List<Pair> queryParams, List<Pair> collectionQueryParams, Object body, Map<String, String> headerParams, Map<String, String> cookieParams, Map<String, Object> formParams, String accept, String contentType, String[] authNames) throws ApiException { 738 if (body != null && !formParams.isEmpty()) { 739 throw new ApiException(500, "Cannot have body and form params"); 740 } 741 742 updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); 743 744 final String url = buildUrl(path, queryParams, collectionQueryParams); 745 Builder builder; 746 if (accept == null) { 747 builder = httpClient.resource(url).getRequestBuilder(); 748 } else { 749 builder = httpClient.resource(url).accept(accept); 750 } 751 752 for (Entry<String, String> keyValue : headerParams.entrySet()) { 753 builder = builder.header(keyValue.getKey(), keyValue.getValue()); 754 } 755 for (Map.Entry<String,String> keyValue : defaultHeaderMap.entrySet()) { 756 if (!headerParams.containsKey(keyValue.getKey())) { 757 builder = builder.header(keyValue.getKey(), keyValue.getValue()); 758 } 759 } 760 761 for (Entry<String, String> keyValue : cookieParams.entrySet()) { 762 builder = builder.cookie(new Cookie(keyValue.getKey(), keyValue.getValue())); 763 } 764 for (Map.Entry<String,String> keyValue : defaultCookieMap.entrySet()) { 765 if (!cookieParams.containsKey(keyValue.getKey())) { 766 builder = builder.cookie(new Cookie(keyValue.getKey(), keyValue.getValue())); 767 } 768 } 769 770 ClientResponse response = null; 771 772 if ("GET".equals(method)) { 773 response = (ClientResponse) builder.get(ClientResponse.class); 774 } else if ("POST".equals(method)) { 775 response = builder.type(contentType).post(ClientResponse.class, serialize(body, contentType, formParams)); 776 } else if ("PUT".equals(method)) { 777 response = builder.type(contentType).put(ClientResponse.class, serialize(body, contentType, formParams)); 778 } else if ("DELETE".equals(method)) { 779 response = builder.type(contentType).delete(ClientResponse.class, serialize(body, contentType, formParams)); 780 } else if ("PATCH".equals(method)) { 781 response = builder.type(contentType).header("X-HTTP-Method-Override", "PATCH").post(ClientResponse.class, serialize(body, contentType, formParams)); 782 } else if ("HEAD".equals(method)) { 783 response = builder.head(); 784 } else { 785 throw new ApiException(500, "unknown method type " + method); 786 } 787 return response; 788 } 789 790 /** 791 * Invoke API by sending HTTP request with the given options. 792 * 793 * @param <T> Type 794 * @param path The sub-path of the HTTP URL 795 * @param method The request method, one of "GET", "POST", "PUT", and "DELETE" 796 * @param queryParams The query parameters 797 * @param collectionQueryParams The collection query parameters 798 * @param body The request body object - if it is not binary, otherwise null 799 * @param headerParams The header parameters 800 * @param cookieParams The cookie parameters 801 * @param formParams The form parameters 802 * @param accept The request's Accept header 803 * @param contentType The request's Content-Type header 804 * @param authNames The authentications to apply 805 * @param returnType Return type 806 * @return The response body in type of string 807 * @throws ApiException API exception 808 */ 809 public <T> T invokeAPI(String path, String method, List<Pair> queryParams, List<Pair> collectionQueryParams, Object body, Map<String, String> headerParams, Map<String, String> cookieParams, Map<String, Object> formParams, String accept, String contentType, String[] authNames, GenericType<T> returnType) throws ApiException { 810 811 ClientResponse response = getAPIResponse(path, method, queryParams, collectionQueryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames); 812 813 statusCode = response.getStatusInfo().getStatusCode(); 814 responseHeaders = response.getHeaders(); 815 816 if(response.getStatusInfo().getStatusCode() == ClientResponse.Status.NO_CONTENT.getStatusCode()) { 817 return null; 818 } else if (response.getStatusInfo().getFamily() == Family.SUCCESSFUL) { 819 if (returnType == null) 820 return null; 821 else 822 return response.getEntity(returnType); 823 } else { 824 String message = "error"; 825 String respBody = null; 826 if (response.hasEntity()) { 827 try { 828 respBody = response.getEntity(String.class); 829 message = respBody; 830 } catch (RuntimeException e) { 831 // e.printStackTrace(); 832 } 833 } 834 throw new ApiException( 835 response.getStatusInfo().getStatusCode(), 836 message, 837 response.getHeaders(), 838 respBody); 839 } 840 } 841 842 /** 843 * Update query and header parameters based on authentication settings. 844 * 845 * @param authNames The authentications to apply 846 * @param queryParams Query parameters 847 * @param headerParams Header parameters 848 * @param cookieParams Cookie parameters 849 */ 850 private void updateParamsForAuth(String[] authNames, List<Pair> queryParams, Map<String, String> headerParams, Map<String, String> cookieParams) { 851 for (String authName : authNames) { 852 Authentication auth = authentications.get(authName); 853 if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); 854 auth.applyToParams(queryParams, headerParams, cookieParams); 855 } 856 } 857 858 /** 859 * Encode the given form parameters as request body. 860 * @param formParams Form parameters 861 * @return HTTP form encoded parameters 862 */ 863 private String getXWWWFormUrlencodedParams(Map<String, Object> formParams) { 864 StringBuilder formParamBuilder = new StringBuilder(); 865 866 for (Entry<String, Object> param : formParams.entrySet()) { 867 String valueStr = parameterToString(param.getValue()); 868 try { 869 formParamBuilder.append(URLEncoder.encode(param.getKey(), "utf8")) 870 .append("=") 871 .append(URLEncoder.encode(valueStr, "utf8")); 872 formParamBuilder.append("&"); 873 } catch (UnsupportedEncodingException e) { 874 // move on to next 875 } 876 } 877 878 String encodedFormParams = formParamBuilder.toString(); 879 if (encodedFormParams.endsWith("&")) { 880 encodedFormParams = encodedFormParams.substring(0, encodedFormParams.length() - 1); 881 } 882 883 return encodedFormParams; 884 } 885 }