From 1a0f7ff8dbe75d6df5a208ba28963ce5050ef3c9 Mon Sep 17 00:00:00 2001 From: wing328 Date: Wed, 7 Mar 2018 00:20:46 +0800 Subject: [PATCH 001/370] renaming for openapi-generator --- ApiClient.mustache | 771 +++++++++++ BeanValidationException.mustache | 27 + Configuration.mustache | 28 + CustomInstantDeserializer.mustache | 232 ++++ JSON.mustache | 521 +++++++ Pair.mustache | 41 + README.mustache | 167 +++ RFC3339DateFormat.mustache | 21 + StringUtil.mustache | 44 + api.mustache | 117 ++ apiException.mustache | 80 ++ api_doc.mustache | 82 ++ api_test.mustache | 45 + auth/ApiKeyAuth.mustache | 64 + auth/Authentication.mustache | 18 + auth/HttpBasicAuth.mustache | 60 + auth/OAuth.mustache | 28 + auth/OAuthFlow.mustache | 7 + beanValidation.mustache | 16 + beanValidationCore.mustache | 20 + beanValidationQueryParams.mustache | 1 + build.gradle.mustache | 137 ++ build.sbt.mustache | 0 enum_outer_doc.mustache | 7 + generatedAnnotation.mustache | 1 + git_push.sh.mustache | 52 + gitignore.mustache | 21 + gradle-wrapper.jar | Bin 0 -> 53639 bytes gradle-wrapper.properties.mustache | 6 + gradle.properties.mustache | 2 + gradlew.bat.mustache | 90 ++ gradlew.mustache | 160 +++ libraries/feign/ApiClient.mustache | 361 +++++ libraries/feign/EncodingUtils.mustache | 86 ++ libraries/feign/ParamExpander.mustache | 22 + libraries/feign/README.mustache | 43 + libraries/feign/api.mustache | 105 ++ libraries/feign/api_test.mustache | 70 + libraries/feign/auth/ApiKeyAuth.mustache | 41 + libraries/feign/auth/HttpBasicAuth.mustache | 41 + libraries/feign/auth/OAuth.mustache | 197 +++ libraries/feign/build.gradle.mustache | 135 ++ libraries/feign/build.sbt.mustache | 26 + libraries/feign/pom.mustache | 308 +++++ .../google-api-client/ApiClient.mustache | 109 ++ libraries/google-api-client/api.mustache | 189 +++ libraries/google-api-client/api_test.mustache | 45 + .../google-api-client/build.gradle.mustache | 142 ++ .../google-api-client/build.sbt.mustache | 33 + libraries/google-api-client/pom.mustache | 299 ++++ libraries/jersey2/ApiClient.mustache | 799 +++++++++++ libraries/jersey2/ApiResponse.mustache | 48 + libraries/jersey2/JSON.mustache | 62 + libraries/jersey2/api.mustache | 143 ++ libraries/jersey2/build.gradle.mustache | 146 ++ libraries/jersey2/build.sbt.mustache | 38 + libraries/jersey2/pom.mustache | 330 +++++ libraries/okhttp-gson/ApiCallback.mustache | 51 + libraries/okhttp-gson/ApiClient.mustache | 1227 +++++++++++++++++ libraries/okhttp-gson/ApiResponse.mustache | 48 + .../GzipRequestInterceptor.mustache | 70 + .../okhttp-gson/ProgressRequestBody.mustache | 66 + .../okhttp-gson/ProgressResponseBody.mustache | 65 + libraries/okhttp-gson/api.mustache | 268 ++++ .../okhttp-gson/auth/HttpBasicAuth.mustache | 43 + libraries/okhttp-gson/build.gradle.mustache | 115 ++ libraries/okhttp-gson/build.sbt.mustache | 26 + libraries/okhttp-gson/pom.mustache | 287 ++++ libraries/rest-assured/ApiClient.mustache | 59 + .../rest-assured/GsonObjectMapper.mustache | 30 + libraries/rest-assured/README.mustache | 43 + .../ResponseSpecBuilders.mustache | 31 + libraries/rest-assured/api.mustache | 243 ++++ libraries/rest-assured/api_doc.mustache | 62 + libraries/rest-assured/api_test.mustache | 65 + libraries/rest-assured/build.gradle.mustache | 124 ++ libraries/rest-assured/build.sbt.mustache | 26 + libraries/rest-assured/pom.mustache | 262 ++++ libraries/resteasy/ApiClient.mustache | 693 ++++++++++ libraries/resteasy/JSON.mustache | 48 + libraries/resteasy/api.mustache | 109 ++ libraries/resteasy/build.gradle.mustache | 147 ++ libraries/resteasy/build.sbt.mustache | 34 + libraries/resteasy/pom.mustache | 263 ++++ libraries/resttemplate/ApiClient.mustache | 678 +++++++++ libraries/resttemplate/api.mustache | 107 ++ libraries/resttemplate/api_test.mustache | 44 + .../resttemplate/auth/ApiKeyAuth.mustache | 60 + .../resttemplate/auth/Authentication.mustache | 13 + .../resttemplate/auth/HttpBasicAuth.mustache | 39 + libraries/resttemplate/auth/OAuth.mustache | 24 + .../resttemplate/auth/OAuthFlow.mustache | 5 + libraries/resttemplate/build.gradle.mustache | 140 ++ libraries/resttemplate/pom.mustache | 301 ++++ libraries/retrofit/ApiClient.mustache | 418 ++++++ libraries/retrofit/CollectionFormats.mustache | 95 ++ libraries/retrofit/README.mustache | 43 + libraries/retrofit/api.mustache | 62 + libraries/retrofit/api_test.mustache | 44 + libraries/retrofit/auth/ApiKeyAuth.mustache | 68 + .../retrofit/auth/HttpBasicAuth.mustache | 49 + libraries/retrofit/auth/OAuth.mustache | 185 +++ .../retrofit/auth/OAuthOkHttpClient.mustache | 69 + libraries/retrofit/bodyParams.mustache | 1 + libraries/retrofit/build.gradle.mustache | 118 ++ libraries/retrofit/build.sbt.mustache | 20 + libraries/retrofit/formParams.mustache | 1 + libraries/retrofit/headerParams.mustache | 1 + libraries/retrofit/pathParams.mustache | 1 + libraries/retrofit/pom.mustache | 254 ++++ libraries/retrofit/queryParams.mustache | 1 + libraries/retrofit2/ApiClient.mustache | 420 ++++++ .../retrofit2/CollectionFormats.mustache | 95 ++ libraries/retrofit2/JSON.mustache | 446 ++++++ libraries/retrofit2/README.mustache | 39 + libraries/retrofit2/api.mustache | 77 ++ libraries/retrofit2/api_test.mustache | 46 + libraries/retrofit2/auth/ApiKeyAuth.mustache | 68 + .../retrofit2/auth/HttpBasicAuth.mustache | 50 + libraries/retrofit2/auth/OAuth.mustache | 185 +++ .../retrofit2/auth/OAuthOkHttpClient.mustache | 72 + libraries/retrofit2/bodyParams.mustache | 1 + libraries/retrofit2/build.gradle.mustache | 164 +++ libraries/retrofit2/build.sbt.mustache | 52 + libraries/retrofit2/formParams.mustache | 1 + libraries/retrofit2/formParams.mustache.save | 1 + libraries/retrofit2/headerParams.mustache | 1 + libraries/retrofit2/pathParams.mustache | 1 + .../play-common/auth/ApiKeyAuth.mustache | 67 + libraries/retrofit2/play24/ApiClient.mustache | 136 ++ .../play24/Play24CallAdapterFactory.mustache | 100 ++ .../play24/Play24CallFactory.mustache | 219 +++ libraries/retrofit2/play24/api.mustache | 57 + libraries/retrofit2/play25/ApiClient.mustache | 136 ++ .../play25/Play25CallAdapterFactory.mustache | 117 ++ .../play25/Play25CallFactory.mustache | 228 +++ libraries/retrofit2/play25/api.mustache | 57 + libraries/retrofit2/pom.mustache | 361 +++++ libraries/retrofit2/queryParams.mustache | 1 + libraries/vertx/ApiClient.mustache | 600 ++++++++ libraries/vertx/Configuration.mustache | 42 + libraries/vertx/api.mustache | 19 + libraries/vertx/apiException.mustache | 110 ++ libraries/vertx/apiImpl.mustache | 91 ++ libraries/vertx/api_test.mustache | 70 + libraries/vertx/auth/ApiKeyAuth.mustache | 64 + libraries/vertx/auth/Authentication.mustache | 18 + libraries/vertx/auth/HttpBasicAuth.mustache | 40 + libraries/vertx/auth/OAuth.mustache | 28 + libraries/vertx/auth/OAuthFlow.mustache | 7 + libraries/vertx/build.gradle.mustache | 53 + libraries/vertx/pom.mustache | 279 ++++ libraries/vertx/rxApiImpl.mustache | 58 + licenseInfo.mustache | 11 + manifest.mustache | 3 + model.mustache | 39 + modelEnum.mustache | 68 + modelInnerEnum.mustache | 59 + model_doc.mustache | 3 + pojo.mustache | 242 ++++ pojo_doc.mustache | 15 + pom.mustache | 336 +++++ settings.gradle.mustache | 1 + travis.mustache | 17 + typeInfoAnnotation.mustache | 7 + xmlAnnotation.mustache | 6 + 166 files changed, 19514 insertions(+) create mode 100644 ApiClient.mustache create mode 100644 BeanValidationException.mustache create mode 100644 Configuration.mustache create mode 100644 CustomInstantDeserializer.mustache create mode 100644 JSON.mustache create mode 100644 Pair.mustache create mode 100644 README.mustache create mode 100644 RFC3339DateFormat.mustache create mode 100644 StringUtil.mustache create mode 100644 api.mustache create mode 100644 apiException.mustache create mode 100644 api_doc.mustache create mode 100644 api_test.mustache create mode 100644 auth/ApiKeyAuth.mustache create mode 100644 auth/Authentication.mustache create mode 100644 auth/HttpBasicAuth.mustache create mode 100644 auth/OAuth.mustache create mode 100644 auth/OAuthFlow.mustache create mode 100644 beanValidation.mustache create mode 100644 beanValidationCore.mustache create mode 100644 beanValidationQueryParams.mustache create mode 100644 build.gradle.mustache create mode 100644 build.sbt.mustache create mode 100644 enum_outer_doc.mustache create mode 100644 generatedAnnotation.mustache create mode 100755 git_push.sh.mustache create mode 100644 gitignore.mustache create mode 100644 gradle-wrapper.jar create mode 100644 gradle-wrapper.properties.mustache create mode 100644 gradle.properties.mustache create mode 100644 gradlew.bat.mustache create mode 100755 gradlew.mustache create mode 100644 libraries/feign/ApiClient.mustache create mode 100644 libraries/feign/EncodingUtils.mustache create mode 100644 libraries/feign/ParamExpander.mustache create mode 100644 libraries/feign/README.mustache create mode 100644 libraries/feign/api.mustache create mode 100644 libraries/feign/api_test.mustache create mode 100644 libraries/feign/auth/ApiKeyAuth.mustache create mode 100644 libraries/feign/auth/HttpBasicAuth.mustache create mode 100644 libraries/feign/auth/OAuth.mustache create mode 100644 libraries/feign/build.gradle.mustache create mode 100644 libraries/feign/build.sbt.mustache create mode 100644 libraries/feign/pom.mustache create mode 100644 libraries/google-api-client/ApiClient.mustache create mode 100644 libraries/google-api-client/api.mustache create mode 100644 libraries/google-api-client/api_test.mustache create mode 100644 libraries/google-api-client/build.gradle.mustache create mode 100644 libraries/google-api-client/build.sbt.mustache create mode 100644 libraries/google-api-client/pom.mustache create mode 100644 libraries/jersey2/ApiClient.mustache create mode 100644 libraries/jersey2/ApiResponse.mustache create mode 100644 libraries/jersey2/JSON.mustache create mode 100644 libraries/jersey2/api.mustache create mode 100644 libraries/jersey2/build.gradle.mustache create mode 100644 libraries/jersey2/build.sbt.mustache create mode 100644 libraries/jersey2/pom.mustache create mode 100644 libraries/okhttp-gson/ApiCallback.mustache create mode 100644 libraries/okhttp-gson/ApiClient.mustache create mode 100644 libraries/okhttp-gson/ApiResponse.mustache create mode 100644 libraries/okhttp-gson/GzipRequestInterceptor.mustache create mode 100644 libraries/okhttp-gson/ProgressRequestBody.mustache create mode 100644 libraries/okhttp-gson/ProgressResponseBody.mustache create mode 100644 libraries/okhttp-gson/api.mustache create mode 100644 libraries/okhttp-gson/auth/HttpBasicAuth.mustache create mode 100644 libraries/okhttp-gson/build.gradle.mustache create mode 100644 libraries/okhttp-gson/build.sbt.mustache create mode 100644 libraries/okhttp-gson/pom.mustache create mode 100644 libraries/rest-assured/ApiClient.mustache create mode 100644 libraries/rest-assured/GsonObjectMapper.mustache create mode 100644 libraries/rest-assured/README.mustache create mode 100644 libraries/rest-assured/ResponseSpecBuilders.mustache create mode 100644 libraries/rest-assured/api.mustache create mode 100644 libraries/rest-assured/api_doc.mustache create mode 100644 libraries/rest-assured/api_test.mustache create mode 100644 libraries/rest-assured/build.gradle.mustache create mode 100644 libraries/rest-assured/build.sbt.mustache create mode 100644 libraries/rest-assured/pom.mustache create mode 100644 libraries/resteasy/ApiClient.mustache create mode 100644 libraries/resteasy/JSON.mustache create mode 100644 libraries/resteasy/api.mustache create mode 100644 libraries/resteasy/build.gradle.mustache create mode 100644 libraries/resteasy/build.sbt.mustache create mode 100644 libraries/resteasy/pom.mustache create mode 100644 libraries/resttemplate/ApiClient.mustache create mode 100644 libraries/resttemplate/api.mustache create mode 100644 libraries/resttemplate/api_test.mustache create mode 100644 libraries/resttemplate/auth/ApiKeyAuth.mustache create mode 100644 libraries/resttemplate/auth/Authentication.mustache create mode 100644 libraries/resttemplate/auth/HttpBasicAuth.mustache create mode 100644 libraries/resttemplate/auth/OAuth.mustache create mode 100644 libraries/resttemplate/auth/OAuthFlow.mustache create mode 100644 libraries/resttemplate/build.gradle.mustache create mode 100644 libraries/resttemplate/pom.mustache create mode 100644 libraries/retrofit/ApiClient.mustache create mode 100644 libraries/retrofit/CollectionFormats.mustache create mode 100644 libraries/retrofit/README.mustache create mode 100644 libraries/retrofit/api.mustache create mode 100644 libraries/retrofit/api_test.mustache create mode 100644 libraries/retrofit/auth/ApiKeyAuth.mustache create mode 100644 libraries/retrofit/auth/HttpBasicAuth.mustache create mode 100644 libraries/retrofit/auth/OAuth.mustache create mode 100644 libraries/retrofit/auth/OAuthOkHttpClient.mustache create mode 100644 libraries/retrofit/bodyParams.mustache create mode 100644 libraries/retrofit/build.gradle.mustache create mode 100644 libraries/retrofit/build.sbt.mustache create mode 100644 libraries/retrofit/formParams.mustache create mode 100644 libraries/retrofit/headerParams.mustache create mode 100644 libraries/retrofit/pathParams.mustache create mode 100644 libraries/retrofit/pom.mustache create mode 100644 libraries/retrofit/queryParams.mustache create mode 100644 libraries/retrofit2/ApiClient.mustache create mode 100644 libraries/retrofit2/CollectionFormats.mustache create mode 100644 libraries/retrofit2/JSON.mustache create mode 100644 libraries/retrofit2/README.mustache create mode 100644 libraries/retrofit2/api.mustache create mode 100644 libraries/retrofit2/api_test.mustache create mode 100644 libraries/retrofit2/auth/ApiKeyAuth.mustache create mode 100644 libraries/retrofit2/auth/HttpBasicAuth.mustache create mode 100644 libraries/retrofit2/auth/OAuth.mustache create mode 100644 libraries/retrofit2/auth/OAuthOkHttpClient.mustache create mode 100644 libraries/retrofit2/bodyParams.mustache create mode 100644 libraries/retrofit2/build.gradle.mustache create mode 100644 libraries/retrofit2/build.sbt.mustache create mode 100644 libraries/retrofit2/formParams.mustache create mode 100644 libraries/retrofit2/formParams.mustache.save create mode 100644 libraries/retrofit2/headerParams.mustache create mode 100644 libraries/retrofit2/pathParams.mustache create mode 100644 libraries/retrofit2/play-common/auth/ApiKeyAuth.mustache create mode 100644 libraries/retrofit2/play24/ApiClient.mustache create mode 100644 libraries/retrofit2/play24/Play24CallAdapterFactory.mustache create mode 100644 libraries/retrofit2/play24/Play24CallFactory.mustache create mode 100644 libraries/retrofit2/play24/api.mustache create mode 100644 libraries/retrofit2/play25/ApiClient.mustache create mode 100644 libraries/retrofit2/play25/Play25CallAdapterFactory.mustache create mode 100644 libraries/retrofit2/play25/Play25CallFactory.mustache create mode 100644 libraries/retrofit2/play25/api.mustache create mode 100644 libraries/retrofit2/pom.mustache create mode 100644 libraries/retrofit2/queryParams.mustache create mode 100644 libraries/vertx/ApiClient.mustache create mode 100644 libraries/vertx/Configuration.mustache create mode 100644 libraries/vertx/api.mustache create mode 100644 libraries/vertx/apiException.mustache create mode 100644 libraries/vertx/apiImpl.mustache create mode 100644 libraries/vertx/api_test.mustache create mode 100644 libraries/vertx/auth/ApiKeyAuth.mustache create mode 100644 libraries/vertx/auth/Authentication.mustache create mode 100644 libraries/vertx/auth/HttpBasicAuth.mustache create mode 100644 libraries/vertx/auth/OAuth.mustache create mode 100644 libraries/vertx/auth/OAuthFlow.mustache create mode 100644 libraries/vertx/build.gradle.mustache create mode 100644 libraries/vertx/pom.mustache create mode 100644 libraries/vertx/rxApiImpl.mustache create mode 100644 licenseInfo.mustache create mode 100644 manifest.mustache create mode 100644 model.mustache create mode 100644 modelEnum.mustache create mode 100644 modelInnerEnum.mustache create mode 100644 model_doc.mustache create mode 100644 pojo.mustache create mode 100644 pojo_doc.mustache create mode 100644 pom.mustache create mode 100644 settings.gradle.mustache create mode 100644 travis.mustache create mode 100644 typeInfoAnnotation.mustache create mode 100644 xmlAnnotation.mustache diff --git a/ApiClient.mustache b/ApiClient.mustache new file mode 100644 index 00000000000..f99ea1dade7 --- /dev/null +++ b/ApiClient.mustache @@ -0,0 +1,771 @@ +{{>licenseInfo}} +package {{invokerPackage}}; + +{{#threetenbp}} +import org.threeten.bp.*; + +{{/threetenbp}} +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.*; +{{#joda}} +import com.fasterxml.jackson.datatype.joda.JodaModule; +{{/joda}} +{{#java8}} +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{/java8}} +{{#threetenbp}} +import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; +{{/threetenbp}} +import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; + +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.GenericType; +import com.sun.jersey.api.client.config.DefaultClientConfig; +import com.sun.jersey.api.client.filter.GZIPContentEncodingFilter; +import com.sun.jersey.api.client.filter.LoggingFilter; +import com.sun.jersey.api.client.WebResource.Builder; + +import com.sun.jersey.multipart.FormDataMultiPart; +import com.sun.jersey.multipart.file.FileDataBodyPart; + +import javax.ws.rs.core.Response.Status.Family; +import javax.ws.rs.core.MediaType; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Map.Entry; +import java.util.HashMap; +import java.util.List; +import java.util.ArrayList; +import java.util.Date; +import java.util.TimeZone; + +import java.net.URLEncoder; + +import java.io.File; +import java.io.UnsupportedEncodingException; + +import java.text.DateFormat; + +import {{invokerPackage}}.auth.Authentication; +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.OAuth; + +{{>generatedAnnotation}} +public class ApiClient { + private Map defaultHeaderMap = new HashMap(); + private String basePath = "{{{basePath}}}"; + private boolean debugging = false; + private int connectionTimeout = 0; + + private Client httpClient; + private ObjectMapper objectMapper; + + private Map authentications; + + private int statusCode; + private Map> responseHeaders; + + private DateFormat dateFormat; + + public ApiClient() { + objectMapper = new ObjectMapper(); + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + {{#joda}} + objectMapper.registerModule(new JodaModule()); + {{/joda}} + {{#java8}} + objectMapper.registerModule(new JavaTimeModule()); + {{/java8}} + {{#threetenbp}} + ThreeTenModule module = new ThreeTenModule(); + module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); + module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); + module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); + objectMapper.registerModule(module); + {{/threetenbp}} + objectMapper.setDateFormat(ApiClient.buildDefaultDateFormat()); + + dateFormat = ApiClient.buildDefaultDateFormat(); + + // Set default User-Agent. + setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}Swagger-Codegen/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap();{{#authMethods}}{{#isBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + + rebuildHttpClient(); + } + + public static DateFormat buildDefaultDateFormat() { + return new RFC3339DateFormat(); + } + + /** + * Build the Client used to make HTTP requests with the latest settings, + * i.e. objectMapper and debugging. + * TODO: better to use the Builder Pattern? + * @return API client + */ + public ApiClient rebuildHttpClient() { + // Add the JSON serialization support to Jersey + JacksonJsonProvider jsonProvider = new JacksonJsonProvider(objectMapper); + DefaultClientConfig conf = new DefaultClientConfig(); + conf.getSingletons().add(jsonProvider); + Client client = Client.create(conf); + client.addFilter(new GZIPContentEncodingFilter({{#useGzipFeature}}true{{/useGzipFeature}}{{^useGzipFeature}}false{{/useGzipFeature}})); + if (debugging) { + client.addFilter(new LoggingFilter()); + } + this.httpClient = client; + return this; + } + + /** + * Returns the current object mapper used for JSON serialization/deserialization. + *

+ * Note: If you make changes to the object mapper, remember to set it back via + * setObjectMapper in order to trigger HTTP client rebuilding. + *

+ * @return Object mapper + */ + public ObjectMapper getObjectMapper() { + return objectMapper; + } + + public ApiClient setObjectMapper(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + // Need to rebuild the Client as it depends on object mapper. + rebuildHttpClient(); + return this; + } + + public Client getHttpClient() { + return httpClient; + } + + public ApiClient setHttpClient(Client httpClient) { + this.httpClient = httpClient; + return this; + } + + public String getBasePath() { + return basePath; + } + + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Gets the status code of the previous request + * @return Status code + */ + public int getStatusCode() { + return statusCode; + } + + /** + * Gets the response headers of the previous request + * @return Response headers + */ + public Map> getResponseHeaders() { + return responseHeaders; + } + + /** + * Get authentications (key: authentication name, value: authentication). + * @return Map of authentication + */ + public Map getAuthentications() { + return authentications; + } + + /** + * Get authentication for the given name. + * + * @param authName The authentication name + * @return The authentication, null if not found + */ + public Authentication getAuthentication(String authName) { + return authentications.get(authName); + } + + /** + * Helper method to set username for the first HTTP basic authentication. + * @param username Username + */ + public void setUsername(String username) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setUsername(username); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set password for the first HTTP basic authentication. + * @param password Password + */ + public void setPassword(String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setPassword(password); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set API key value for the first API key authentication. + * @param apiKey API key + */ + public void setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + * @param apiKeyPrefix API key prefix + */ + public void setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set access token for the first OAuth2 authentication. + * @param accessToken Access token + */ + public void setAccessToken(String accessToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setAccessToken(accessToken); + return; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Set the User-Agent header's value (by adding to the default header map). + * @param userAgent User agent + * @return API client + */ + public ApiClient setUserAgent(String userAgent) { + addDefaultHeader("User-Agent", userAgent); + return this; + } + + /** + * Add a default header. + * + * @param key The header's key + * @param value The header's value + * @return API client + */ + public ApiClient addDefaultHeader(String key, String value) { + defaultHeaderMap.put(key, value); + return this; + } + + /** + * Check that whether debugging is enabled for this API client. + * @return True if debugging is on + */ + public boolean isDebugging() { + return debugging; + } + + /** + * Enable/disable debugging for this API client. + * + * @param debugging To enable (true) or disable (false) debugging + * @return API client + */ + public ApiClient setDebugging(boolean debugging) { + this.debugging = debugging; + // Need to rebuild the Client as it depends on the value of debugging. + rebuildHttpClient(); + return this; + } + + /** + * Connect timeout (in milliseconds). + * @return Connection timeout + */ + public int getConnectTimeout() { + return connectionTimeout; + } + + /** + * Set the connect timeout (in milliseconds). + * A value of 0 means no timeout, otherwise values must be between 1 and + * {@link Integer#MAX_VALUE}. + * @param connectionTimeout Connection timeout in milliseconds + * @return API client + */ + public ApiClient setConnectTimeout(int connectionTimeout) { + this.connectionTimeout = connectionTimeout; + httpClient.setConnectTimeout(connectionTimeout); + return this; + } + + /** + * Get the date format used to parse/format date parameters. + * @return Date format + */ + public DateFormat getDateFormat() { + return dateFormat; + } + + /** + * Set the date format used to parse/format date parameters. + * @param dateFormat Date format + * @return API client + */ + public ApiClient setDateFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + // Also set the date format for model (de)serialization with Date properties. + this.objectMapper.setDateFormat((DateFormat) dateFormat.clone()); + // Need to rebuild the Client as objectMapper changes. + rebuildHttpClient(); + return this; + } + + /** + * Parse the given string into Date object. + * @param str String + * @return Date + */ + public Date parseDate(String str) { + try { + return dateFormat.parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(e); + } + } + + /** + * Format the given Date object into string. + * @param date Date + * @return Date in string format + */ + public String formatDate(Date date) { + return dateFormat.format(date); + } + + /** + * Format the given parameter object into string. + * @param param Object + * @return Object in string format + */ + public String parameterToString(Object param) { + if (param == null) { + return ""; + } else if (param instanceof Date) { + return formatDate((Date) param); + } else if (param instanceof Collection) { + StringBuilder b = new StringBuilder(); + for(Object o : (Collection)param) { + if(b.length() > 0) { + b.append(','); + } + b.append(String.valueOf(o)); + } + return b.toString(); + } else { + return String.valueOf(param); + } + } + + /** + * Formats the specified query parameter to a list containing a single {@code Pair} object. + * + * Note that {@code value} must not be a collection. + * + * @param name The name of the parameter. + * @param value The value of the parameter. + * @return A list containing a single {@code Pair} object. + */ + public List parameterToPair(String name, Object value) { + List params = new ArrayList(); + + // preconditions + if (name == null || name.isEmpty() || value == null || value instanceof Collection) return params; + + params.add(new Pair(name, parameterToString(value))); + return params; + } + + /** + * Formats the specified collection query parameters to a list of {@code Pair} objects. + * + * Note that the values of each of the returned Pair objects are percent-encoded. + * + * @param collectionFormat The collection format of the parameter. + * @param name The name of the parameter. + * @param value The value of the parameter. + * @return A list of {@code Pair} objects. + */ + public List parameterToPairs(String collectionFormat, String name, Collection value) { + List params = new ArrayList(); + + // preconditions + if (name == null || name.isEmpty() || value == null) { + return params; + } + + // create the params based on the collection format + if ("multi".equals(collectionFormat)) { + for (Object item : value) { + params.add(new Pair(name, escapeString(parameterToString(item)))); + } + return params; + } + + // collectionFormat is assumed to be "csv" by default + String delimiter = ","; + + // escape all delimiters except commas, which are URI reserved + // characters + if ("ssv".equals(collectionFormat)) { + delimiter = escapeString(" "); + } else if ("tsv".equals(collectionFormat)) { + delimiter = escapeString("\t"); + } else if ("pipes".equals(collectionFormat)) { + delimiter = escapeString("|"); + } + + StringBuilder sb = new StringBuilder() ; + for (Object item : value) { + sb.append(delimiter); + sb.append(escapeString(parameterToString(item))); + } + + params.add(new Pair(name, sb.substring(delimiter.length()))); + + return params; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * application/vnd.company+json + * @param mime MIME + * @return True if MIME type is boolean + */ + public boolean isJsonMime(String mime) { + String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$"; + return mime != null && (mime.matches(jsonMime) || mime.equals("*/*")); + } + + /** + * Select the Accept header's value from the given accepts array: + * if JSON exists in the given array, use it; + * otherwise use all of them (joining into a string) + * + * @param accepts The accepts array to select from + * @return The Accept header to use. If the given array is empty, + * null will be returned (not to set the Accept header explicitly). + */ + public String selectHeaderAccept(String[] accepts) { + if (accepts.length == 0) { + return null; + } + for (String accept : accepts) { + if (isJsonMime(accept)) { + return accept; + } + } + return StringUtil.join(accepts, ","); + } + + /** + * Select the Content-Type header's value from the given array: + * if JSON exists in the given array, use it; + * otherwise use the first one of the array. + * + * @param contentTypes The Content-Type array to select from + * @return The Content-Type header to use. If the given array is empty, + * or matches "any", JSON will be used. + */ + public String selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0 || contentTypes[0].equals("*/*")) { + return "application/json"; + } + for (String contentType : contentTypes) { + if (isJsonMime(contentType)) { + return contentType; + } + } + return contentTypes[0]; + } + + /** + * Escape the given string to be used as URL query value. + * @param str String + * @return Escaped string + */ + public String escapeString(String str) { + try { + return URLEncoder.encode(str, "utf8").replaceAll("\\+", "%20"); + } catch (UnsupportedEncodingException e) { + return str; + } + } + + /** + * Serialize the given Java object into string according the given + * Content-Type (only JSON is supported for now). + * @param obj Object + * @param contentType Content type + * @param formParams Form parameters + * @return Object + * @throws ApiException API exception + */ + public Object serialize(Object obj, String contentType, Map formParams) throws ApiException { + if (contentType.startsWith("multipart/form-data")) { + FormDataMultiPart mp = new FormDataMultiPart(); + for (Entry param: formParams.entrySet()) { + if( param.getValue() instanceof List && !( ( List ) param.getValue() ).isEmpty() + && ( ( List ) param.getValue() ).get( 0 ) instanceof File ) { + @SuppressWarnings( "unchecked" ) + List files = ( List ) param.getValue(); + for( File file : files ) { + mp.bodyPart( new FileDataBodyPart( param.getKey(), file, MediaType.APPLICATION_OCTET_STREAM_TYPE ) ); + } + } else if (param.getValue() instanceof File) { + File file = (File) param.getValue(); + mp.bodyPart(new FileDataBodyPart(param.getKey(), file, MediaType.APPLICATION_OCTET_STREAM_TYPE)); + } else { + mp.field(param.getKey(), parameterToString(param.getValue()), MediaType.MULTIPART_FORM_DATA_TYPE); + } + } + return mp; + } else if (contentType.startsWith("application/x-www-form-urlencoded")) { + return this.getXWWWFormUrlencodedParams(formParams); + } else { + // We let Jersey attempt to serialize the body + return obj; + } + } + + /** + * Build full URL by concatenating base path, the given sub path and query parameters. + * + * @param path The sub path + * @param queryParams The query parameters + * @param collectionQueryParams The collection query parameters + * @return The full URL + */ + private String buildUrl(String path, List queryParams, List collectionQueryParams) { + final StringBuilder url = new StringBuilder(); + url.append(basePath).append(path); + + if (queryParams != null && !queryParams.isEmpty()) { + // support (constant) query string in `path`, e.g. "/posts?draft=1" + String prefix = path.contains("?") ? "&" : "?"; + for (Pair param : queryParams) { + if (param.getValue() != null) { + if (prefix != null) { + url.append(prefix); + prefix = null; + } else { + url.append("&"); + } + String value = parameterToString(param.getValue()); + url.append(escapeString(param.getName())).append("=").append(escapeString(value)); + } + } + } + + if (collectionQueryParams != null && !collectionQueryParams.isEmpty()) { + String prefix = url.toString().contains("?") ? "&" : "?"; + for (Pair param : collectionQueryParams) { + if (param.getValue() != null) { + if (prefix != null) { + url.append(prefix); + prefix = null; + } else { + url.append("&"); + } + String value = parameterToString(param.getValue()); + // collection query parameter value already escaped as part of parameterToPairs + url.append(escapeString(param.getName())).append("=").append(value); + } + } + } + + return url.toString(); + } + + private ClientResponse getAPIResponse(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map formParams, String accept, String contentType, String[] authNames) throws ApiException { + if (body != null && !formParams.isEmpty()) { + throw new ApiException(500, "Cannot have body and form params"); + } + + updateParamsForAuth(authNames, queryParams, headerParams); + + final String url = buildUrl(path, queryParams, collectionQueryParams); + Builder builder; + if (accept == null) { + builder = httpClient.resource(url).getRequestBuilder(); + } else { + builder = httpClient.resource(url).accept(accept); + } + + for (Entry keyValue : headerParams.entrySet()) { + builder = builder.header(keyValue.getKey(), keyValue.getValue()); + } + for (Map.Entry keyValue : defaultHeaderMap.entrySet()) { + if (!headerParams.containsKey(keyValue.getKey())) { + builder = builder.header(keyValue.getKey(), keyValue.getValue()); + } + } + + ClientResponse response = null; + + if ("GET".equals(method)) { + response = (ClientResponse) builder.get(ClientResponse.class); + } else if ("POST".equals(method)) { + response = builder.type(contentType).post(ClientResponse.class, serialize(body, contentType, formParams)); + } else if ("PUT".equals(method)) { + response = builder.type(contentType).put(ClientResponse.class, serialize(body, contentType, formParams)); + } else if ("DELETE".equals(method)) { + response = builder.type(contentType).delete(ClientResponse.class, serialize(body, contentType, formParams)); + } else if ("PATCH".equals(method)) { + response = builder.type(contentType).header("X-HTTP-Method-Override", "PATCH").post(ClientResponse.class, serialize(body, contentType, formParams)); + } else if ("HEAD".equals(method)) { + response = builder.head(); + } else { + throw new ApiException(500, "unknown method type " + method); + } + return response; + } + + /** + * Invoke API by sending HTTP request with the given options. + * + * @param Type + * @param path The sub-path of the HTTP URL + * @param method The request method, one of "GET", "POST", "PUT", and "DELETE" + * @param queryParams The query parameters + * @param collectionQueryParams The collection query parameters + * @param body The request body object - if it is not binary, otherwise null + * @param headerParams The header parameters + * @param formParams The form parameters + * @param accept The request's Accept header + * @param contentType The request's Content-Type header + * @param authNames The authentications to apply + * @param returnType Return type + * @return The response body in type of string + * @throws ApiException API exception + */ + public T invokeAPI(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { + + ClientResponse response = getAPIResponse(path, method, queryParams, collectionQueryParams, body, headerParams, formParams, accept, contentType, authNames); + + statusCode = response.getStatusInfo().getStatusCode(); + responseHeaders = response.getHeaders(); + + if(response.getStatusInfo().getStatusCode() == ClientResponse.Status.NO_CONTENT.getStatusCode()) { + return null; + } else if (response.getStatusInfo().getFamily() == Family.SUCCESSFUL) { + if (returnType == null) + return null; + else + return response.getEntity(returnType); + } else { + String message = "error"; + String respBody = null; + if (response.hasEntity()) { + try { + respBody = response.getEntity(String.class); + message = respBody; + } catch (RuntimeException e) { + // e.printStackTrace(); + } + } + throw new ApiException( + response.getStatusInfo().getStatusCode(), + message, + response.getHeaders(), + respBody); + } + } + + /** + * Update query and header parameters based on authentication settings. + * + * @param authNames The authentications to apply + * @param queryParams Query parameters + * @param headerParams Header parameters + */ + private void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams) { + for (String authName : authNames) { + Authentication auth = authentications.get(authName); + if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + auth.applyToParams(queryParams, headerParams); + } + } + + /** + * Encode the given form parameters as request body. + * @param formParams Form parameters + * @return HTTP form encoded parameters + */ + private String getXWWWFormUrlencodedParams(Map formParams) { + StringBuilder formParamBuilder = new StringBuilder(); + + for (Entry param : formParams.entrySet()) { + String valueStr = parameterToString(param.getValue()); + try { + formParamBuilder.append(URLEncoder.encode(param.getKey(), "utf8")) + .append("=") + .append(URLEncoder.encode(valueStr, "utf8")); + formParamBuilder.append("&"); + } catch (UnsupportedEncodingException e) { + // move on to next + } + } + + String encodedFormParams = formParamBuilder.toString(); + if (encodedFormParams.endsWith("&")) { + encodedFormParams = encodedFormParams.substring(0, encodedFormParams.length() - 1); + } + + return encodedFormParams; + } +} diff --git a/BeanValidationException.mustache b/BeanValidationException.mustache new file mode 100644 index 00000000000..ab8ef30b69b --- /dev/null +++ b/BeanValidationException.mustache @@ -0,0 +1,27 @@ +package {{invokerPackage}}; + +import java.util.Set; + +import javax.validation.ConstraintViolation; +import javax.validation.ValidationException; + +public class BeanValidationException extends ValidationException { + /** + * + */ + private static final long serialVersionUID = -5294733947409491364L; + Set> violations; + + public BeanValidationException(Set> violations) { + this.violations = violations; + } + + public Set> getViolations() { + return violations; + } + + public void setViolations(Set> violations) { + this.violations = violations; + } + +} diff --git a/Configuration.mustache b/Configuration.mustache new file mode 100644 index 00000000000..cb425df3563 --- /dev/null +++ b/Configuration.mustache @@ -0,0 +1,28 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +{{>generatedAnnotation}} +public class Configuration { + private static ApiClient defaultApiClient = new ApiClient(); + + /** + * Get the default API client, which would be used when creating API + * instances without providing an API client. + * + * @return Default API client + */ + public static ApiClient getDefaultApiClient() { + return defaultApiClient; + } + + /** + * Set the default API client, which would be used when creating API + * instances without providing an API client. + * + * @param apiClient API client + */ + public static void setDefaultApiClient(ApiClient apiClient) { + defaultApiClient = apiClient; + } +} diff --git a/CustomInstantDeserializer.mustache b/CustomInstantDeserializer.mustache new file mode 100644 index 00000000000..dbf4d30e117 --- /dev/null +++ b/CustomInstantDeserializer.mustache @@ -0,0 +1,232 @@ +package {{invokerPackage}}; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonTokenId; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.datatype.threetenbp.DateTimeUtils; +import com.fasterxml.jackson.datatype.threetenbp.DecimalUtils; +import com.fasterxml.jackson.datatype.threetenbp.deser.ThreeTenDateTimeDeserializerBase; +import com.fasterxml.jackson.datatype.threetenbp.function.BiFunction; +import com.fasterxml.jackson.datatype.threetenbp.function.Function; +import org.threeten.bp.DateTimeException; +import org.threeten.bp.Instant; +import org.threeten.bp.OffsetDateTime; +import org.threeten.bp.ZoneId; +import org.threeten.bp.ZonedDateTime; +import org.threeten.bp.format.DateTimeFormatter; +import org.threeten.bp.temporal.Temporal; +import org.threeten.bp.temporal.TemporalAccessor; + +import java.io.IOException; +import java.math.BigDecimal; + +/** + * Deserializer for ThreeTen temporal {@link Instant}s, {@link OffsetDateTime}, and {@link ZonedDateTime}s. + * Adapted from the jackson threetenbp InstantDeserializer to add support for deserializing rfc822 format. + * + * @author Nick Williams + */ +public class CustomInstantDeserializer + extends ThreeTenDateTimeDeserializerBase { + private static final long serialVersionUID = 1L; + + public static final CustomInstantDeserializer INSTANT = new CustomInstantDeserializer( + Instant.class, DateTimeFormatter.ISO_INSTANT, + new Function() { + @Override + public Instant apply(TemporalAccessor temporalAccessor) { + return Instant.from(temporalAccessor); + } + }, + new Function() { + @Override + public Instant apply(FromIntegerArguments a) { + return Instant.ofEpochMilli(a.value); + } + }, + new Function() { + @Override + public Instant apply(FromDecimalArguments a) { + return Instant.ofEpochSecond(a.integer, a.fraction); + } + }, + null + ); + + public static final CustomInstantDeserializer OFFSET_DATE_TIME = new CustomInstantDeserializer( + OffsetDateTime.class, DateTimeFormatter.ISO_OFFSET_DATE_TIME, + new Function() { + @Override + public OffsetDateTime apply(TemporalAccessor temporalAccessor) { + return OffsetDateTime.from(temporalAccessor); + } + }, + new Function() { + @Override + public OffsetDateTime apply(FromIntegerArguments a) { + return OffsetDateTime.ofInstant(Instant.ofEpochMilli(a.value), a.zoneId); + } + }, + new Function() { + @Override + public OffsetDateTime apply(FromDecimalArguments a) { + return OffsetDateTime.ofInstant(Instant.ofEpochSecond(a.integer, a.fraction), a.zoneId); + } + }, + new BiFunction() { + @Override + public OffsetDateTime apply(OffsetDateTime d, ZoneId z) { + return d.withOffsetSameInstant(z.getRules().getOffset(d.toLocalDateTime())); + } + } + ); + + public static final CustomInstantDeserializer ZONED_DATE_TIME = new CustomInstantDeserializer( + ZonedDateTime.class, DateTimeFormatter.ISO_ZONED_DATE_TIME, + new Function() { + @Override + public ZonedDateTime apply(TemporalAccessor temporalAccessor) { + return ZonedDateTime.from(temporalAccessor); + } + }, + new Function() { + @Override + public ZonedDateTime apply(FromIntegerArguments a) { + return ZonedDateTime.ofInstant(Instant.ofEpochMilli(a.value), a.zoneId); + } + }, + new Function() { + @Override + public ZonedDateTime apply(FromDecimalArguments a) { + return ZonedDateTime.ofInstant(Instant.ofEpochSecond(a.integer, a.fraction), a.zoneId); + } + }, + new BiFunction() { + @Override + public ZonedDateTime apply(ZonedDateTime zonedDateTime, ZoneId zoneId) { + return zonedDateTime.withZoneSameInstant(zoneId); + } + } + ); + + protected final Function fromMilliseconds; + + protected final Function fromNanoseconds; + + protected final Function parsedToValue; + + protected final BiFunction adjust; + + protected CustomInstantDeserializer(Class supportedType, + DateTimeFormatter parser, + Function parsedToValue, + Function fromMilliseconds, + Function fromNanoseconds, + BiFunction adjust) { + super(supportedType, parser); + this.parsedToValue = parsedToValue; + this.fromMilliseconds = fromMilliseconds; + this.fromNanoseconds = fromNanoseconds; + this.adjust = adjust == null ? new BiFunction() { + @Override + public T apply(T t, ZoneId zoneId) { + return t; + } + } : adjust; + } + + @SuppressWarnings("unchecked") + protected CustomInstantDeserializer(CustomInstantDeserializer base, DateTimeFormatter f) { + super((Class) base.handledType(), f); + parsedToValue = base.parsedToValue; + fromMilliseconds = base.fromMilliseconds; + fromNanoseconds = base.fromNanoseconds; + adjust = base.adjust; + } + + @Override + protected JsonDeserializer withDateFormat(DateTimeFormatter dtf) { + if (dtf == _formatter) { + return this; + } + return new CustomInstantDeserializer(this, dtf); + } + + @Override + public T deserialize(JsonParser parser, DeserializationContext context) throws IOException { + //NOTE: Timestamps contain no timezone info, and are always in configured TZ. Only + //string values have to be adjusted to the configured TZ. + switch (parser.getCurrentTokenId()) { + case JsonTokenId.ID_NUMBER_FLOAT: { + BigDecimal value = parser.getDecimalValue(); + long seconds = value.longValue(); + int nanoseconds = DecimalUtils.extractNanosecondDecimal(value, seconds); + return fromNanoseconds.apply(new FromDecimalArguments( + seconds, nanoseconds, getZone(context))); + } + + case JsonTokenId.ID_NUMBER_INT: { + long timestamp = parser.getLongValue(); + if (context.isEnabled(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS)) { + return this.fromNanoseconds.apply(new FromDecimalArguments( + timestamp, 0, this.getZone(context) + )); + } + return this.fromMilliseconds.apply(new FromIntegerArguments( + timestamp, this.getZone(context) + )); + } + + case JsonTokenId.ID_STRING: { + String string = parser.getText().trim(); + if (string.length() == 0) { + return null; + } + if (string.endsWith("+0000")) { + string = string.substring(0, string.length() - 5) + "Z"; + } + T value; + try { + TemporalAccessor acc = _formatter.parse(string); + value = parsedToValue.apply(acc); + if (context.isEnabled(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)) { + return adjust.apply(value, this.getZone(context)); + } + } catch (DateTimeException e) { + throw _peelDTE(e); + } + return value; + } + } + throw context.mappingException("Expected type float, integer, or string."); + } + + private ZoneId getZone(DeserializationContext context) { + // Instants are always in UTC, so don't waste compute cycles + return (_valueClass == Instant.class) ? null : DateTimeUtils.timeZoneToZoneId(context.getTimeZone()); + } + + private static class FromIntegerArguments { + public final long value; + public final ZoneId zoneId; + + private FromIntegerArguments(long value, ZoneId zoneId) { + this.value = value; + this.zoneId = zoneId; + } + } + + private static class FromDecimalArguments { + public final long integer; + public final int fraction; + public final ZoneId zoneId; + + private FromDecimalArguments(long integer, int fraction, ZoneId zoneId) { + this.integer = integer; + this.fraction = fraction; + this.zoneId = zoneId; + } + } +} diff --git a/JSON.mustache b/JSON.mustache new file mode 100644 index 00000000000..63814a361fc --- /dev/null +++ b/JSON.mustache @@ -0,0 +1,521 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonParseException; +import com.google.gson.TypeAdapter; +import com.google.gson.internal.bind.util.ISO8601Utils; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import com.google.gson.JsonElement; +import io.gsonfire.GsonFireBuilder; +import io.gsonfire.TypeSelector; +{{#joda}} +import org.joda.time.DateTime; +import org.joda.time.LocalDate; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.DateTimeFormatterBuilder; +import org.joda.time.format.ISODateTimeFormat; +{{/joda}} +{{#threetenbp}} +import org.threeten.bp.LocalDate; +import org.threeten.bp.OffsetDateTime; +import org.threeten.bp.format.DateTimeFormatter; +{{/threetenbp}} + +import {{modelPackage}}.*; +import okio.ByteString; + +import java.io.IOException; +import java.io.StringReader; +import java.lang.reflect.Type; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.ParsePosition; +{{#java8}} +import java.time.LocalDate; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +{{/java8}} +import java.util.Date; +import java.util.Map; +import java.util.HashMap; + +public class JSON { + private Gson gson; + private boolean isLenientOnJson = false; + private DateTypeAdapter dateTypeAdapter = new DateTypeAdapter(); + private SqlDateTypeAdapter sqlDateTypeAdapter = new SqlDateTypeAdapter(); + {{#joda}} + private DateTimeTypeAdapter dateTimeTypeAdapter = new DateTimeTypeAdapter(); + private LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter(); + {{/joda}} + {{#jsr310}} + private OffsetDateTimeTypeAdapter offsetDateTimeTypeAdapter = new OffsetDateTimeTypeAdapter(); + private LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter(); + {{/jsr310}} + private ByteArrayAdapter byteArrayAdapter = new ByteArrayAdapter(); + + public static GsonBuilder createGson() { + GsonFireBuilder fireBuilder = new GsonFireBuilder() + {{#parent}} + .registerTypeSelector({{classname}}.class, new TypeSelector() { + @Override + public Class getClassForElement(JsonElement readElement) { + Map classByDiscriminatorValue = new HashMap(); + {{#children}} + classByDiscriminatorValue.put("{{name}}".toUpperCase(), {{classname}}.class); + {{/children}} + classByDiscriminatorValue.put("{{classname}}".toUpperCase(), {{classname}}.class); + return getClassByDiscriminator( + classByDiscriminatorValue, + getDiscriminatorValue(readElement, "{{discriminator}}")); + } + }) + {{/parent}} + ; + return fireBuilder.createGsonBuilder(); + } + + private static String getDiscriminatorValue(JsonElement readElement, String discriminatorField) { + JsonElement element = readElement.getAsJsonObject().get(discriminatorField); + if(null == element) { + throw new IllegalArgumentException("missing discriminator field: <" + discriminatorField + ">"); + } + return element.getAsString(); + } + + private static Class getClassByDiscriminator(Map classByDiscriminatorValue, String discriminatorValue) { + Class clazz = (Class) classByDiscriminatorValue.get(discriminatorValue.toUpperCase()); + if(null == clazz) { + throw new IllegalArgumentException("cannot determine model class of name: <" + discriminatorValue + ">"); + } + return clazz; + } + + public JSON() { + gson = createGson() + .registerTypeAdapter(Date.class, dateTypeAdapter) + .registerTypeAdapter(java.sql.Date.class, sqlDateTypeAdapter) + {{#joda}} + .registerTypeAdapter(DateTime.class, dateTimeTypeAdapter) + .registerTypeAdapter(LocalDate.class, localDateTypeAdapter) + {{/joda}} + {{#jsr310}} + .registerTypeAdapter(OffsetDateTime.class, offsetDateTimeTypeAdapter) + .registerTypeAdapter(LocalDate.class, localDateTypeAdapter) + {{/jsr310}} + .registerTypeAdapter(byte[].class, byteArrayAdapter) + .create(); + } + + /** + * Get Gson. + * + * @return Gson + */ + public Gson getGson() { + return gson; + } + + /** + * Set Gson. + * + * @param gson Gson + * @return JSON + */ + public JSON setGson(Gson gson) { + this.gson = gson; + return this; + } + + public JSON setLenientOnJson(boolean lenientOnJson) { + isLenientOnJson = lenientOnJson; + return this; + } + + /** + * Serialize the given Java object into JSON string. + * + * @param obj Object + * @return String representation of the JSON + */ + public String serialize(Object obj) { + return gson.toJson(obj); + } + + /** + * Deserialize the given JSON string to Java object. + * + * @param Type + * @param body The JSON string + * @param returnType The type to deserialize into + * @return The deserialized Java object + */ + @SuppressWarnings("unchecked") + public T deserialize(String body, Type returnType) { + try { + if (isLenientOnJson) { + JsonReader jsonReader = new JsonReader(new StringReader(body)); + // see https://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/stream/JsonReader.html#setLenient(boolean) + jsonReader.setLenient(true); + return gson.fromJson(jsonReader, returnType); + } else { + return gson.fromJson(body, returnType); + } + } catch (JsonParseException e) { + // Fallback processing when failed to parse JSON form response body: + // return the response body string directly for the String return type; + if (returnType.equals(String.class)) + return (T) body; + else throw (e); + } + } + + /** + * Gson TypeAdapter for Byte Array type + */ + public class ByteArrayAdapter extends TypeAdapter { + + @Override + public void write(JsonWriter out, byte[] value) throws IOException { + if (value == null) { + out.nullValue(); + } else { + out.value(ByteString.of(value).base64()); + } + } + + @Override + public byte[] read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String bytesAsBase64 = in.nextString(); + ByteString byteString = ByteString.decodeBase64(bytesAsBase64); + return byteString.toByteArray(); + } + } + } + + {{#joda}} + /** + * Gson TypeAdapter for Joda DateTime type + */ + public static class DateTimeTypeAdapter extends TypeAdapter { + + private DateTimeFormatter formatter; + + public DateTimeTypeAdapter() { + this(new DateTimeFormatterBuilder() + .append(ISODateTimeFormat.dateTime().getPrinter(), ISODateTimeFormat.dateOptionalTimeParser().getParser()) + .toFormatter()); + } + + public DateTimeTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } + + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } + + @Override + public void write(JsonWriter out, DateTime date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.print(date)); + } + } + + @Override + public DateTime read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + return formatter.parseDateTime(date); + } + } + } + + /** + * Gson TypeAdapter for Joda LocalDate type + */ + public class LocalDateTypeAdapter extends TypeAdapter { + + private DateTimeFormatter formatter; + + public LocalDateTypeAdapter() { + this(ISODateTimeFormat.date()); + } + + public LocalDateTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } + + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } + + @Override + public void write(JsonWriter out, LocalDate date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.print(date)); + } + } + + @Override + public LocalDate read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + return formatter.parseLocalDate(date); + } + } + } + + public JSON setDateTimeFormat(DateTimeFormatter dateFormat) { + dateTimeTypeAdapter.setFormat(dateFormat); + return this; + } + + public JSON setLocalDateFormat(DateTimeFormatter dateFormat) { + localDateTypeAdapter.setFormat(dateFormat); + return this; + } + + {{/joda}} + {{#jsr310}} + /** + * Gson TypeAdapter for JSR310 OffsetDateTime type + */ + public static class OffsetDateTimeTypeAdapter extends TypeAdapter { + + private DateTimeFormatter formatter; + + public OffsetDateTimeTypeAdapter() { + this(DateTimeFormatter.ISO_OFFSET_DATE_TIME); + } + + public OffsetDateTimeTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } + + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } + + @Override + public void write(JsonWriter out, OffsetDateTime date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.format(date)); + } + } + + @Override + public OffsetDateTime read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + if (date.endsWith("+0000")) { + date = date.substring(0, date.length()-5) + "Z"; + } + return OffsetDateTime.parse(date, formatter); + } + } + } + + /** + * Gson TypeAdapter for JSR310 LocalDate type + */ + public class LocalDateTypeAdapter extends TypeAdapter { + + private DateTimeFormatter formatter; + + public LocalDateTypeAdapter() { + this(DateTimeFormatter.ISO_LOCAL_DATE); + } + + public LocalDateTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } + + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } + + @Override + public void write(JsonWriter out, LocalDate date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.format(date)); + } + } + + @Override + public LocalDate read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + return LocalDate.parse(date, formatter); + } + } + } + + public JSON setOffsetDateTimeFormat(DateTimeFormatter dateFormat) { + offsetDateTimeTypeAdapter.setFormat(dateFormat); + return this; + } + + public JSON setLocalDateFormat(DateTimeFormatter dateFormat) { + localDateTypeAdapter.setFormat(dateFormat); + return this; + } + + {{/jsr310}} + /** + * Gson TypeAdapter for java.sql.Date type + * If the dateFormat is null, a simple "yyyy-MM-dd" format will be used + * (more efficient than SimpleDateFormat). + */ + public static class SqlDateTypeAdapter extends TypeAdapter { + + private DateFormat dateFormat; + + public SqlDateTypeAdapter() { + } + + public SqlDateTypeAdapter(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + public void setFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + @Override + public void write(JsonWriter out, java.sql.Date date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + String value; + if (dateFormat != null) { + value = dateFormat.format(date); + } else { + value = date.toString(); + } + out.value(value); + } + } + + @Override + public java.sql.Date read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + try { + if (dateFormat != null) { + return new java.sql.Date(dateFormat.parse(date).getTime()); + } + return new java.sql.Date(ISO8601Utils.parse(date, new ParsePosition(0)).getTime()); + } catch (ParseException e) { + throw new JsonParseException(e); + } + } + } + } + + /** + * Gson TypeAdapter for java.util.Date type + * If the dateFormat is null, ISO8601Utils will be used. + */ + public static class DateTypeAdapter extends TypeAdapter { + + private DateFormat dateFormat; + + public DateTypeAdapter() { + } + + public DateTypeAdapter(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + public void setFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + @Override + public void write(JsonWriter out, Date date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + String value; + if (dateFormat != null) { + value = dateFormat.format(date); + } else { + value = ISO8601Utils.format(date, true); + } + out.value(value); + } + } + + @Override + public Date read(JsonReader in) throws IOException { + try { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + try { + if (dateFormat != null) { + return dateFormat.parse(date); + } + return ISO8601Utils.parse(date, new ParsePosition(0)); + } catch (ParseException e) { + throw new JsonParseException(e); + } + } + } catch (IllegalArgumentException e) { + throw new JsonParseException(e); + } + } + } + + public JSON setDateFormat(DateFormat dateFormat) { + dateTypeAdapter.setFormat(dateFormat); + return this; + } + + public JSON setSqlDateFormat(DateFormat dateFormat) { + sqlDateTypeAdapter.setFormat(dateFormat); + return this; + } + +} diff --git a/Pair.mustache b/Pair.mustache new file mode 100644 index 00000000000..c08f145a482 --- /dev/null +++ b/Pair.mustache @@ -0,0 +1,41 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +{{>generatedAnnotation}} +public class Pair { + private String name = ""; + private String value = ""; + + public Pair (String name, String value) { + setName(name); + setValue(value); + } + + private void setName(String name) { + if (!isValidString(name)) return; + + this.name = name; + } + + private void setValue(String value) { + if (!isValidString(value)) return; + + this.value = value; + } + + public String getName() { + return this.name; + } + + public String getValue() { + return this.value; + } + + private boolean isValidString(String arg) { + if (arg == null) return false; + if (arg.trim().isEmpty()) return false; + + return true; + } +} diff --git a/README.mustache b/README.mustache new file mode 100644 index 00000000000..6ec3efff471 --- /dev/null +++ b/README.mustache @@ -0,0 +1,167 @@ +# {{artifactId}} + +{{appName}} +- API version: {{appVersion}} +{{^hideGenerationTimestamp}} + - Build date: {{generatedDate}} +{{/hideGenerationTimestamp}} + +{{#appDescription}}{{{appDescription}}}{{/appDescription}} + +{{#infoUrl}} + For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) +{{/infoUrl}} + +*Automatically generated by the [Swagger Codegen](https://github.com/swagger-api/swagger-codegen)* + + +## Requirements + +Building the API client library requires: +1. Java 1.7+ +2. Maven/Gradle + +## Installation + +To install the API client library to your local Maven repository, simply execute: + +```shell +mvn clean install +``` + +To deploy it to a remote Maven repository instead, configure the settings of the repository and execute: + +```shell +mvn clean deploy +``` + +Refer to the [OSSRH Guide](http://central.sonatype.org/pages/ossrh-guide.html) for more information. + +### Maven users + +Add this dependency to your project's POM: + +```xml + + {{{groupId}}} + {{{artifactId}}} + {{{artifactVersion}}} + compile + +``` + +### Gradle users + +Add this dependency to your project's build file: + +```groovy +compile "{{{groupId}}}:{{{artifactId}}}:{{{artifactVersion}}}" +``` + +### Others + +At first generate the JAR by executing: + +```shell +mvn clean package +``` + +Then manually install the following JARs: + +* `target/{{{artifactId}}}-{{{artifactVersion}}}.jar` +* `target/lib/*.jar` + +## Getting Started + +Please follow the [installation](#installation) instruction and execute the following Java code: + +```java +{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}} +import {{{invokerPackage}}}.*; +import {{{invokerPackage}}}.auth.*; +import {{{modelPackage}}}.*; +import {{{package}}}.{{{classname}}}; + +import java.io.File; +import java.util.*; + +public class {{{classname}}}Example { + + public static void main(String[] args) { + {{#hasAuthMethods}}ApiClient defaultClient = Configuration.getDefaultApiClient(); + {{#authMethods}}{{#isBasic}} + // Configure HTTP basic authorization: {{{name}}} + HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setUsername("YOUR USERNAME"); + {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasic}}{{#isApiKey}} + // Configure API key authorization: {{{name}}} + ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setApiKey("YOUR API KEY"); + // Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null) + //{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} + // Configure OAuth2 access token for authorization: {{{name}}} + OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}} + {{/authMethods}} + {{/hasAuthMethods}} + + {{{classname}}} apiInstance = new {{{classname}}}(); + {{#allParams}} + {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} + {{/allParams}} + try { + {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + System.out.println(result);{{/returnType}} + } catch (ApiException e) { + System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); + e.printStackTrace(); + } + } +} +{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} +``` + +## Documentation for API Endpoints + +All URIs are relative to *{{basePath}}* + +Class | Method | HTTP request | Description +------------ | ------------- | ------------- | ------------- +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} + +## Documentation for Models + +{{#models}}{{#model}} - [{{classname}}]({{modelDocPath}}{{classname}}.md) +{{/model}}{{/models}} + +## Documentation for Authorization + +{{^authMethods}}All endpoints do not require authorization. +{{/authMethods}}Authentication schemes defined for the API: +{{#authMethods}}### {{name}} + +{{#isApiKey}}- **Type**: API key +- **API key parameter name**: {{keyParamName}} +- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}} +{{/isApiKey}} +{{#isBasic}}- **Type**: HTTP basic authentication +{{/isBasic}} +{{#isOAuth}}- **Type**: OAuth +- **Flow**: {{flow}} +- **Authorization URL**: {{authorizationUrl}} +- **Scopes**: {{^scopes}}N/A{{/scopes}} +{{#scopes}} - {{scope}}: {{description}} +{{/scopes}} +{{/isOAuth}} + +{{/authMethods}} + +## Recommendation + +It's recommended to create an instance of `ApiClient` per thread in a multithreaded environment to avoid any potential issues. + +## Author + +{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} +{{/hasMore}}{{/apis}}{{/apiInfo}} diff --git a/RFC3339DateFormat.mustache b/RFC3339DateFormat.mustache new file mode 100644 index 00000000000..16fd2a495a7 --- /dev/null +++ b/RFC3339DateFormat.mustache @@ -0,0 +1,21 @@ +{{>licenseInfo}} +package {{invokerPackage}}; + +import com.fasterxml.jackson.databind.util.ISO8601DateFormat; +import com.fasterxml.jackson.databind.util.ISO8601Utils; + +import java.text.FieldPosition; +import java.util.Date; + + +public class RFC3339DateFormat extends ISO8601DateFormat { + + // Same as ISO8601DateFormat but serializing milliseconds. + @Override + public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { + String value = ISO8601Utils.format(date, true); + toAppendTo.append(value); + return toAppendTo; + } + +} \ No newline at end of file diff --git a/StringUtil.mustache b/StringUtil.mustache new file mode 100644 index 00000000000..7b72a7bab45 --- /dev/null +++ b/StringUtil.mustache @@ -0,0 +1,44 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +{{>generatedAnnotation}} +public class StringUtil { + /** + * Check if the given array contains the given value (with case-insensitive comparison). + * + * @param array The array + * @param value The value to search + * @return true if the array contains the value + */ + public static boolean containsIgnoreCase(String[] array, String value) { + for (String str : array) { + if (value == null && str == null) return true; + if (value != null && value.equalsIgnoreCase(str)) return true; + } + return false; + } + + /** + * Join an array of strings with the given separator. + *

+ * Note: This might be replaced by utility method from commons-lang or guava someday + * if one of those libraries is added as dependency. + *

+ * + * @param array The array of strings + * @param separator The separator + * @return the resulting string + */ + public static String join(String[] array, String separator) { + int len = array.length; + if (len == 0) return ""; + + StringBuilder out = new StringBuilder(); + out.append(array[0]); + for (int i = 1; i < len; i++) { + out.append(separator).append(array[i]); + } + return out.toString(); + } +} diff --git a/api.mustache b/api.mustache new file mode 100644 index 00000000000..542ccbba287 --- /dev/null +++ b/api.mustache @@ -0,0 +1,117 @@ +{{>licenseInfo}} +package {{package}}; + +import com.sun.jersey.api.client.GenericType; + +import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.Configuration; +import {{modelPackage}}.*; +import {{invokerPackage}}.Pair; + +{{#imports}}import {{import}}; +{{/imports}} + + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}} { + private ApiClient {{localVariablePrefix}}apiClient; + + public {{classname}}() { + this(Configuration.getDefaultApiClient()); + } + + public {{classname}}(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + public ApiClient getApiClient() { + return {{localVariablePrefix}}apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + {{#operation}} + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} + {{#returnType}} + * @return {{returnType}} + {{/returnType}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + Object {{localVariablePrefix}}localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + } + {{/required}}{{/allParams}} + // create path and map variables + String {{localVariablePrefix}}localVarPath = "{{{path}}}"{{#pathParams}} + .replaceAll("\\{" + "{{baseName}}" + "\\}", {{localVariablePrefix}}apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; + + // query params + {{javaUtilPrefix}}List {{localVariablePrefix}}localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}List {{localVariablePrefix}}localVarCollectionQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarFormParams = new {{javaUtilPrefix}}HashMap(); + + {{#queryParams}} + {{localVariablePrefix}}{{#collectionFormat}}localVarCollectionQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPairs("{{{collectionFormat}}}", {{/collectionFormat}}{{^collectionFormat}}localVarQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPair({{/collectionFormat}}"{{baseName}}", {{paramName}})); + {{/queryParams}} + + {{#headerParams}}if ({{paramName}} != null) + {{localVariablePrefix}}localVarHeaderParams.put("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}})); + {{/headerParams}} + + {{#formParams}}if ({{paramName}} != null) + {{localVariablePrefix}}localVarFormParams.put("{{baseName}}", {{paramName}}); + {{/formParams}} + + final String[] {{localVariablePrefix}}localVarAccepts = { + {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} + }; + final String {{localVariablePrefix}}localVarAccept = {{localVariablePrefix}}apiClient.selectHeaderAccept({{localVariablePrefix}}localVarAccepts); + + final String[] {{localVariablePrefix}}localVarContentTypes = { + {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} + }; + final String {{localVariablePrefix}}localVarContentType = {{localVariablePrefix}}apiClient.selectHeaderContentType({{localVariablePrefix}}localVarContentTypes); + + String[] {{localVariablePrefix}}localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + + {{#returnType}} + GenericType<{{{returnType}}}> {{localVariablePrefix}}localVarReturnType = new GenericType<{{{returnType}}}>() {}; + return {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarCollectionQueryParams, {{localVariablePrefix}}localVarPostBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccept, {{localVariablePrefix}}localVarContentType, {{localVariablePrefix}}localVarAuthNames, {{localVariablePrefix}}localVarReturnType); + {{/returnType}}{{^returnType}} + {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarCollectionQueryParams, {{localVariablePrefix}}localVarPostBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccept, {{localVariablePrefix}}localVarContentType, {{localVariablePrefix}}localVarAuthNames, null); + {{/returnType}} + } + {{/operation}} +} +{{/operations}} diff --git a/apiException.mustache b/apiException.mustache new file mode 100644 index 00000000000..5b450c9ba62 --- /dev/null +++ b/apiException.mustache @@ -0,0 +1,80 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import java.util.Map; +import java.util.List; + +{{>generatedAnnotation}} +public class ApiException extends{{#useRuntimeException}} RuntimeException {{/useRuntimeException}}{{^useRuntimeException}} Exception {{/useRuntimeException}}{ + private int code = 0; + private Map> responseHeaders = null; + private String responseBody = null; + + public ApiException() {} + + public ApiException(Throwable throwable) { + super(throwable); + } + + public ApiException(String message) { + super(message); + } + + public ApiException(String message, Throwable throwable, int code, Map> responseHeaders, String responseBody) { + super(message, throwable); + this.code = code; + this.responseHeaders = responseHeaders; + this.responseBody = responseBody; + } + + public ApiException(String message, int code, Map> responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(String message, Throwable throwable, int code, Map> responseHeaders) { + this(message, throwable, code, responseHeaders, null); + } + + public ApiException(int code, Map> responseHeaders, String responseBody) { + this((String) null, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(int code, String message) { + super(message); + this.code = code; + } + + public ApiException(int code, String message, Map> responseHeaders, String responseBody) { + this(code, message); + this.responseHeaders = responseHeaders; + this.responseBody = responseBody; + } + + /** + * Get the HTTP status code. + * + * @return HTTP status code + */ + public int getCode() { + return code; + } + + /** + * Get the HTTP response headers. + * + * @return A map of list of string + */ + public Map> getResponseHeaders() { + return responseHeaders; + } + + /** + * Get the HTTP response body. + * + * @return Response body in the form of string + */ + public String getResponseBody() { + return responseBody; + } +} diff --git a/api_doc.mustache b/api_doc.mustache new file mode 100644 index 00000000000..bbb5b66f840 --- /dev/null +++ b/api_doc.mustache @@ -0,0 +1,82 @@ +# {{classname}}{{#description}} +{{description}}{{/description}} + +All URIs are relative to *{{basePath}}* + +Method | HTTP request | Description +------------- | ------------- | ------------- +{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}} + +{{#operations}} +{{#operation}} + +# **{{operationId}}** +> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) + +{{summary}}{{#notes}} + +{{notes}}{{/notes}} + +### Example +```java +// Import classes:{{#hasAuthMethods}} +//import {{{invokerPackage}}}.ApiClient;{{/hasAuthMethods}} +//import {{{invokerPackage}}}.ApiException;{{#hasAuthMethods}} +//import {{{invokerPackage}}}.Configuration; +//import {{{invokerPackage}}}.auth.*;{{/hasAuthMethods}} +//import {{{package}}}.{{{classname}}}; + +{{#hasAuthMethods}} +ApiClient defaultClient = Configuration.getDefaultApiClient(); +{{#authMethods}}{{#isBasic}} +// Configure HTTP basic authorization: {{{name}}} +HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); +{{{name}}}.setUsername("YOUR USERNAME"); +{{{name}}}.setPassword("YOUR PASSWORD");{{/isBasic}}{{#isApiKey}} +// Configure API key authorization: {{{name}}} +ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); +{{{name}}}.setApiKey("YOUR API KEY"); +// Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null) +//{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} +// Configure OAuth2 access token for authorization: {{{name}}} +OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); +{{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}} +{{/authMethods}} +{{/hasAuthMethods}} + +{{{classname}}} apiInstance = new {{{classname}}}(); +{{#allParams}} +{{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} +{{/allParams}} +try { + {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + System.out.println(result);{{/returnType}} +} catch (ApiException e) { + System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); + e.printStackTrace(); +} +``` + +### Parameters +{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} +Name | Type | Description | Notes +------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} +{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} +{{/allParams}} + +### Return type + +{{#returnType}}{{#returnTypeIsPrimitive}}**{{returnType}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{returnType}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}null (empty response body){{/returnType}} + +### Authorization + +{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{name}}](../README.md#{{name}}){{^-last}}, {{/-last}}{{/authMethods}} + +### HTTP request headers + + - **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} + - **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} + +{{/operation}} +{{/operations}} diff --git a/api_test.mustache b/api_test.mustache new file mode 100644 index 00000000000..1d95ac2ed89 --- /dev/null +++ b/api_test.mustache @@ -0,0 +1,45 @@ +{{>licenseInfo}} + +package {{package}}; + +import {{invokerPackage}}.ApiException; +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Test; +import org.junit.Ignore; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +@Ignore +public class {{classname}}Test { + + private final {{classname}} api = new {{classname}}(); + + {{#operations}}{{#operation}} + /** + * {{summary}} + * + * {{notes}} + * + * @throws ApiException + * if the Api call fails + */ + @Test + public void {{operationId}}Test() throws ApiException { + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + + // TODO: test validations + } + {{/operation}}{{/operations}} +} diff --git a/auth/ApiKeyAuth.mustache b/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..5af060f1173 --- /dev/null +++ b/auth/ApiKeyAuth.mustache @@ -0,0 +1,64 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; + +import java.util.Map; +import java.util.List; + +{{>generatedAnnotation}} +public class ApiKeyAuth implements Authentication { + private final String location; + private final String paramName; + + private String apiKey; + private String apiKeyPrefix; + + public ApiKeyAuth(String location, String paramName) { + this.location = location; + this.paramName = paramName; + } + + public String getLocation() { + return location; + } + + public String getParamName() { + return paramName; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + public String getApiKeyPrefix() { + return apiKeyPrefix; + } + + public void setApiKeyPrefix(String apiKeyPrefix) { + this.apiKeyPrefix = apiKeyPrefix; + } + + @Override + public void applyToParams(List queryParams, Map headerParams) { + if (apiKey == null) { + return; + } + String value; + if (apiKeyPrefix != null) { + value = apiKeyPrefix + " " + apiKey; + } else { + value = apiKey; + } + if ("query".equals(location)) { + queryParams.add(new Pair(paramName, value)); + } else if ("header".equals(location)) { + headerParams.put(paramName, value); + } + } +} diff --git a/auth/Authentication.mustache b/auth/Authentication.mustache new file mode 100644 index 00000000000..26174fa3b59 --- /dev/null +++ b/auth/Authentication.mustache @@ -0,0 +1,18 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; + +import java.util.Map; +import java.util.List; + +public interface Authentication { + /** + * Apply authentication settings to header and query params. + * + * @param queryParams List of query parameters + * @param headerParams Map of header parameters + */ + void applyToParams(List queryParams, Map headerParams); +} diff --git a/auth/HttpBasicAuth.mustache b/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..015e042e171 --- /dev/null +++ b/auth/HttpBasicAuth.mustache @@ -0,0 +1,60 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; + +{{^java8}} +import com.migcomponents.migbase64.Base64; +{{/java8}} +{{#java8}} +import java.util.Base64; +import java.nio.charset.StandardCharsets; +{{/java8}} + +import java.util.Map; +import java.util.List; + +{{^java8}} +import java.io.UnsupportedEncodingException; +{{/java8}} + +{{>generatedAnnotation}} +public class HttpBasicAuth implements Authentication { + private String username; + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public void applyToParams(List queryParams, Map headerParams) { + if (username == null && password == null) { + return; + } + String str = (username == null ? "" : username) + ":" + (password == null ? "" : password); +{{^java8}} + try { + headerParams.put("Authorization", "Basic " + Base64.encodeToString(str.getBytes("UTF-8"), false)); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } +{{/java8}} +{{#java8}} + headerParams.put("Authorization", "Basic " + Base64.getEncoder().encodeToString(str.getBytes(StandardCharsets.UTF_8))); +{{/java8}} + } +} diff --git a/auth/OAuth.mustache b/auth/OAuth.mustache new file mode 100644 index 00000000000..ffc9923d1fe --- /dev/null +++ b/auth/OAuth.mustache @@ -0,0 +1,28 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; + +import java.util.Map; +import java.util.List; + +{{>generatedAnnotation}} +public class OAuth implements Authentication { + private String accessToken; + + public String getAccessToken() { + return accessToken; + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + @Override + public void applyToParams(List queryParams, Map headerParams) { + if (accessToken != null) { + headerParams.put("Authorization", "Bearer " + accessToken); + } + } +} diff --git a/auth/OAuthFlow.mustache b/auth/OAuthFlow.mustache new file mode 100644 index 00000000000..002e9572f33 --- /dev/null +++ b/auth/OAuthFlow.mustache @@ -0,0 +1,7 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +public enum OAuthFlow { + accessCode, implicit, password, application +} diff --git a/beanValidation.mustache b/beanValidation.mustache new file mode 100644 index 00000000000..7c347758d8d --- /dev/null +++ b/beanValidation.mustache @@ -0,0 +1,16 @@ +{{#required}} + @NotNull +{{/required}} +{{#isContainer}} +{{^isPrimitiveType}} +{{^isEnum}} + @Valid +{{/isEnum}} +{{/isPrimitiveType}} +{{/isContainer}} +{{#isNotContainer}} +{{^isPrimitiveType}} + @Valid +{{/isPrimitiveType}} +{{/isNotContainer}} +{{>beanValidationCore}} \ No newline at end of file diff --git a/beanValidationCore.mustache b/beanValidationCore.mustache new file mode 100644 index 00000000000..8bcdce3df16 --- /dev/null +++ b/beanValidationCore.mustache @@ -0,0 +1,20 @@ +{{#pattern}} @Pattern(regexp="{{{pattern}}}"){{/pattern}}{{! +minLength && maxLength set +}}{{#minLength}}{{#maxLength}} @Size(min={{minLength}},max={{maxLength}}){{/maxLength}}{{/minLength}}{{! +minLength set, maxLength not +}}{{#minLength}}{{^maxLength}} @Size(min={{minLength}}){{/maxLength}}{{/minLength}}{{! +minLength not set, maxLength set +}}{{^minLength}}{{#maxLength}} @Size(max={{maxLength}}){{/maxLength}}{{/minLength}}{{! +@Size: minItems && maxItems set +}}{{#minItems}}{{#maxItems}} @Size(min={{minItems}},max={{maxItems}}){{/maxItems}}{{/minItems}}{{! +@Size: minItems set, maxItems not +}}{{#minItems}}{{^maxItems}} @Size(min={{minItems}}){{/maxItems}}{{/minItems}}{{! +@Size: minItems not set && maxItems set +}}{{^minItems}}{{#maxItems}} @Size(max={{maxItems}}){{/maxItems}}{{/minItems}}{{! +check for integer or long / all others=decimal type with @Decimal* +isInteger set +}}{{#isInteger}}{{#minimum}} @Min({{minimum}}){{/minimum}}{{#maximum}} @Max({{maximum}}){{/maximum}}{{/isInteger}}{{! +isLong set +}}{{#isLong}}{{#minimum}} @Min({{minimum}}L){{/minimum}}{{#maximum}} @Max({{maximum}}L){{/maximum}}{{/isLong}}{{! +Not Integer, not Long => we have a decimal value! +}}{{^isInteger}}{{^isLong}}{{#minimum}} @DecimalMin("{{minimum}}"){{/minimum}}{{#maximum}} @DecimalMax("{{maximum}}"){{/maximum}}{{/isLong}}{{/isInteger}} \ No newline at end of file diff --git a/beanValidationQueryParams.mustache b/beanValidationQueryParams.mustache new file mode 100644 index 00000000000..f8eef8f94c7 --- /dev/null +++ b/beanValidationQueryParams.mustache @@ -0,0 +1 @@ +{{#required}} @NotNull{{/required}}{{>beanValidationCore}} \ No newline at end of file diff --git a/build.gradle.mustache b/build.gradle.mustache new file mode 100644 index 00000000000..cbc39ce3aca --- /dev/null +++ b/build.gradle.mustache @@ -0,0 +1,137 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + } + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + {{#java8}} + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + {{/java8}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + swagger_annotations_version = "1.5.17" + jackson_version = "{{^threetenbp}}2.8.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" + jersey_version = "1.19.4" + jodatime_version = "2.9.9" + junit_version = "4.12" +} + +dependencies { + compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "com.sun.jersey:jersey-client:$jersey_version" + compile "com.sun.jersey.contribs:jersey-multipart:$jersey_version" + compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + {{#joda}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version", + {{/joda}} + {{#java8}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version", + {{/java8}} + {{#threetenbp}} + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_version", + {{/threetenbp}} + {{^java8}} + compile "com.brsanthu:migbase64:2.2" + {{/java8}} + testCompile "junit:junit:$junit_version" +} diff --git a/build.sbt.mustache b/build.sbt.mustache new file mode 100644 index 00000000000..e69de29bb2d diff --git a/enum_outer_doc.mustache b/enum_outer_doc.mustache new file mode 100644 index 00000000000..20c512aaeae --- /dev/null +++ b/enum_outer_doc.mustache @@ -0,0 +1,7 @@ +# {{classname}} + +## Enum + +{{#allowableValues}}{{#enumVars}} +* `{{name}}` (value: `{{{value}}}`) +{{/enumVars}}{{/allowableValues}} diff --git a/generatedAnnotation.mustache b/generatedAnnotation.mustache new file mode 100644 index 00000000000..a47b6faa85b --- /dev/null +++ b/generatedAnnotation.mustache @@ -0,0 +1 @@ +{{^hideGenerationTimestamp}}@javax.annotation.Generated(value = "{{generatorClass}}", date = "{{generatedDate}}"){{/hideGenerationTimestamp}} \ No newline at end of file diff --git a/git_push.sh.mustache b/git_push.sh.mustache new file mode 100755 index 00000000000..a2d75234837 --- /dev/null +++ b/git_push.sh.mustache @@ -0,0 +1,52 @@ +#!/bin/sh +# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ +# +# Usage example: /bin/sh ./git_push.sh wing328 swagger-petstore-perl "minor update" + +git_user_id=$1 +git_repo_id=$2 +release_note=$3 + +if [ "$git_user_id" = "" ]; then + git_user_id="{{{gitUserId}}}" + echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id" +fi + +if [ "$git_repo_id" = "" ]; then + git_repo_id="{{{gitRepoId}}}" + echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id" +fi + +if [ "$release_note" = "" ]; then + release_note="{{{releaseNote}}}" + echo "[INFO] No command line input provided. Set \$release_note to $release_note" +fi + +# Initialize the local directory as a Git repository +git init + +# Adds the files in the local repository and stages them for commit. +git add . + +# Commits the tracked changes and prepares them to be pushed to a remote repository. +git commit -m "$release_note" + +# Sets the new remote +git_remote=`git remote` +if [ "$git_remote" = "" ]; then # git remote not defined + + if [ "$GIT_TOKEN" = "" ]; then + echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment." + git remote add origin https://github.com/${git_user_id}/${git_repo_id}.git + else + git remote add origin https://${git_user_id}:${GIT_TOKEN}@github.com/${git_user_id}/${git_repo_id}.git + fi + +fi + +git pull origin master + +# Pushes (Forces) the changes in the local repository up to the remote repository +echo "Git pushing to https://github.com/${git_user_id}/${git_repo_id}.git" +git push origin master 2>&1 | grep -v 'To https' + diff --git a/gitignore.mustache b/gitignore.mustache new file mode 100644 index 00000000000..a530464afa1 --- /dev/null +++ b/gitignore.mustache @@ -0,0 +1,21 @@ +*.class + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear + +# exclude jar for gradle wrapper +!gradle/wrapper/*.jar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +# build files +**/target +target +.gradle +build diff --git a/gradle-wrapper.jar b/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..2c6137b87896c8f70315ae454e00a969ef5f6019 GIT binary patch literal 53639 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 F{{tUq7iIte literal 0 HcmV?d00001 diff --git a/gradle-wrapper.properties.mustache b/gradle-wrapper.properties.mustache new file mode 100644 index 00000000000..b7a36473955 --- /dev/null +++ b/gradle-wrapper.properties.mustache @@ -0,0 +1,6 @@ +#Tue May 17 23:08:05 CST 2016 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.6-bin.zip diff --git a/gradle.properties.mustache b/gradle.properties.mustache new file mode 100644 index 00000000000..05644f0754a --- /dev/null +++ b/gradle.properties.mustache @@ -0,0 +1,2 @@ +# Uncomment to build for Android +#target = android \ No newline at end of file diff --git a/gradlew.bat.mustache b/gradlew.bat.mustache new file mode 100644 index 00000000000..5f192121eb4 --- /dev/null +++ b/gradlew.bat.mustache @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/gradlew.mustache b/gradlew.mustache new file mode 100755 index 00000000000..9d82f789151 --- /dev/null +++ b/gradlew.mustache @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/libraries/feign/ApiClient.mustache b/libraries/feign/ApiClient.mustache new file mode 100644 index 00000000000..fa1dea42e8a --- /dev/null +++ b/libraries/feign/ApiClient.mustache @@ -0,0 +1,361 @@ +package {{invokerPackage}}; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; +{{#threetenbp}} +import org.threeten.bp.*; +{{/threetenbp}} + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +{{#joda}} +import com.fasterxml.jackson.datatype.joda.JodaModule; +{{/joda}} +{{#java8}} +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{/java8}} +{{#threetenbp}} +import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; +{{/threetenbp}} + +import feign.Feign; +import feign.RequestInterceptor; +import feign.form.FormEncoder; +import feign.jackson.JacksonDecoder; +import feign.jackson.JacksonEncoder; +import feign.slf4j.Slf4jLogger; +import {{invokerPackage}}.auth.*; +import {{invokerPackage}}.auth.OAuth.AccessTokenListener; + +{{>generatedAnnotation}} +public class ApiClient { + public interface Api {} + + protected ObjectMapper objectMapper; + private String basePath = "{{{basePath}}}"; + private Map apiAuthorizations; + private Feign.Builder feignBuilder; + + public ApiClient() { + objectMapper = createObjectMapper(); + apiAuthorizations = new LinkedHashMap(); + feignBuilder = Feign.builder() + .encoder(new FormEncoder(new JacksonEncoder(objectMapper))) + .decoder(new JacksonDecoder(objectMapper)) + .logger(new Slf4jLogger()); + } + + public ApiClient(String[] authNames) { + this(); + for(String authName : authNames) { + {{#hasAuthMethods}} + RequestInterceptor auth; + {{#authMethods}}if ("{{name}}".equals(authName)) { + {{#isBasic}} + auth = new HttpBasicAuth(); + {{/isBasic}} + {{#isApiKey}} + auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"); + {{/isApiKey}} + {{#isOAuth}} + auth = new OAuth(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{#hasMore}}, {{/hasMore}}{{/scopes}}"); + {{/isOAuth}} + } else {{/authMethods}}{ + throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); + } + addAuthorization(authName, auth); + {{/hasAuthMethods}} + {{^hasAuthMethods}} + throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); + {{/hasAuthMethods}} + } + } + + /** + * Basic constructor for single auth name + * @param authName + */ + public ApiClient(String authName) { + this(new String[]{authName}); + } + + /** + * Helper constructor for single api key + * @param authName + * @param apiKey + */ + public ApiClient(String authName, String apiKey) { + this(authName); + this.setApiKey(apiKey); + } + + /** + * Helper constructor for single basic auth or password oauth2 + * @param authName + * @param username + * @param password + */ + public ApiClient(String authName, String username, String password) { + this(authName); + this.setCredentials(username, password); + } + + /** + * Helper constructor for single password oauth2 + * @param authName + * @param clientId + * @param secret + * @param username + * @param password + */ + public ApiClient(String authName, String clientId, String secret, String username, String password) { + this(authName); + this.getTokenEndPoint() + .setClientId(clientId) + .setClientSecret(secret) + .setUsername(username) + .setPassword(password); + } + + public String getBasePath() { + return basePath; + } + + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + public Map getApiAuthorizations() { + return apiAuthorizations; + } + + public void setApiAuthorizations(Map apiAuthorizations) { + this.apiAuthorizations = apiAuthorizations; + } + + public Feign.Builder getFeignBuilder() { + return feignBuilder; + } + + public ApiClient setFeignBuilder(Feign.Builder feignBuilder) { + this.feignBuilder = feignBuilder; + return this; + } + + private ObjectMapper createObjectMapper() { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + objectMapper.disable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE); + objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + objectMapper.setDateFormat(new RFC3339DateFormat()); + {{#joda}} + objectMapper.registerModule(new JodaModule()); + {{/joda}} + {{#java8}} + objectMapper.registerModule(new JavaTimeModule()); + {{/java8}} + {{#threetenbp}} + ThreeTenModule module = new ThreeTenModule(); + module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); + module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); + module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); + objectMapper.registerModule(module); + {{/threetenbp}} + return objectMapper; + } + + public ObjectMapper getObjectMapper(){ + return objectMapper; + } + + /** + * Creates a feign client for given API interface. + * + * Usage: + * ApiClient apiClient = new ApiClient(); + * apiClient.setBasePath("http://localhost:8080"); + * XYZApi api = apiClient.buildClient(XYZApi.class); + * XYZResponse response = api.someMethod(...); + * @param Type + * @param clientClass Client class + * @return The Client + */ + public T buildClient(Class clientClass) { + return feignBuilder.target(clientClass, basePath); + } + + /** + * Select the Accept header's value from the given accepts array: + * if JSON exists in the given array, use it; + * otherwise use all of them (joining into a string) + * + * @param accepts The accepts array to select from + * @return The Accept header to use. If the given array is empty, + * null will be returned (not to set the Accept header explicitly). + */ + public String selectHeaderAccept(String[] accepts) { + if (accepts.length == 0) return null; + if (StringUtil.containsIgnoreCase(accepts, "application/json")) return "application/json"; + return StringUtil.join(accepts, ","); + } + + /** + * Select the Content-Type header's value from the given array: + * if JSON exists in the given array, use it; + * otherwise use the first one of the array. + * + * @param contentTypes The Content-Type array to select from + * @return The Content-Type header to use. If the given array is empty, + * JSON will be used. + */ + public String selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0) return "application/json"; + if (StringUtil.containsIgnoreCase(contentTypes, "application/json")) return "application/json"; + return contentTypes[0]; + } + + /** + * Helper method to configure the first api key found + * @param apiKey API key + */ + public void setApiKey(String apiKey) { + for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof ApiKeyAuth) { + ApiKeyAuth keyAuth = (ApiKeyAuth) apiAuthorization; + keyAuth.setApiKey(apiKey); + return ; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to configure the username/password for basic auth or password OAuth + * @param username Username + * @param password Password + */ + public void setCredentials(String username, String password) { + for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof HttpBasicAuth) { + HttpBasicAuth basicAuth = (HttpBasicAuth) apiAuthorization; + basicAuth.setCredentials(username, password); + return; + } + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.getTokenRequestBuilder().setUsername(username).setPassword(password); + return; + } + } + throw new RuntimeException("No Basic authentication or OAuth configured!"); + } + + /** + * Helper method to configure the token endpoint of the first oauth found in the apiAuthorizations (there should be only one) + * @return Token request builder + */ + public TokenRequestBuilder getTokenEndPoint() { + for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + return oauth.getTokenRequestBuilder(); + } + } + return null; + } + + /** + * Helper method to configure authorization endpoint of the first oauth found in the apiAuthorizations (there should be only one) + * @return Authentication request builder + */ + public AuthenticationRequestBuilder getAuthorizationEndPoint() { + for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + return oauth.getAuthenticationRequestBuilder(); + } + } + return null; + } + + /** + * Helper method to pre-set the oauth access token of the first oauth found in the apiAuthorizations (there should be only one) + * @param accessToken Access Token + * @param expiresIn Validity period in seconds + */ + public void setAccessToken(String accessToken, Long expiresIn) { + for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.setAccessToken(accessToken, expiresIn); + return; + } + } + } + + /** + * Helper method to configure the oauth accessCode/implicit flow parameters + * @param clientId Client ID + * @param clientSecret Client secret + * @param redirectURI Redirect URI + */ + public void configureAuthorizationFlow(String clientId, String clientSecret, String redirectURI) { + for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.getTokenRequestBuilder() + .setClientId(clientId) + .setClientSecret(clientSecret) + .setRedirectURI(redirectURI); + oauth.getAuthenticationRequestBuilder() + .setClientId(clientId) + .setRedirectURI(redirectURI); + return; + } + } + } + + /** + * Configures a listener which is notified when a new access token is received. + * @param accessTokenListener Acesss token listener + */ + public void registerAccessTokenListener(AccessTokenListener accessTokenListener) { + for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.registerAccessTokenListener(accessTokenListener); + return; + } + } + } + + /** + * Gets request interceptor based on authentication name + * @param authName Authentiation name + * @return Request Interceptor + */ + public RequestInterceptor getAuthorization(String authName) { + return apiAuthorizations.get(authName); + } + + /** + * Adds an authorization to be used by the client + * @param authName Authentication name + * @param authorization Request interceptor + */ + public void addAuthorization(String authName, RequestInterceptor authorization) { + if (apiAuthorizations.containsKey(authName)) { + throw new RuntimeException("auth name \"" + authName + "\" already in api authorizations"); + } + apiAuthorizations.put(authName, authorization); + feignBuilder.requestInterceptor(authorization); + } + +} diff --git a/libraries/feign/EncodingUtils.mustache b/libraries/feign/EncodingUtils.mustache new file mode 100644 index 00000000000..6f43e1c3c2a --- /dev/null +++ b/libraries/feign/EncodingUtils.mustache @@ -0,0 +1,86 @@ +package {{invokerPackage}}; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** +* Utilities to support Swagger encoding formats in Feign. +*/ +public final class EncodingUtils { + + /** + * Private constructor. Do not construct this class. + */ + private EncodingUtils() {} + + /** + *

Encodes a collection of query parameters according to the Swagger + * collection format.

+ * + *

Of the various collection formats defined by Swagger ("csv", "tsv", + * etc), Feign only natively supports "multi". This utility generates the + * other format types so it will be properly processed by Feign.

+ * + *

Note, as part of reformatting, it URL encodes the parameters as + * well.

+ * @param parameters The collection object to be formatted. This object will + * not be changed. + * @param collectionFormat The Swagger collection format (eg, "csv", "tsv", + * "pipes"). See the + *
+ * Swagger Spec for more details. + * @return An object that will be correctly formatted by Feign. + */ + public static Object encodeCollection(Collection parameters, + String collectionFormat) { + if (parameters == null) { + return parameters; + } + List stringValues = new ArrayList<>(parameters.size()); + for (Object parameter : parameters) { + // ignore null values (same behavior as Feign) + if (parameter != null) { + stringValues.add(encode(parameter)); + } + } + // Feign natively handles single-element lists and the "multi" format. + if (stringValues.size() < 2 || "multi".equals(collectionFormat)) { + return stringValues; + } + // Otherwise return a formatted String + String[] stringArray = stringValues.toArray(new String[0]); + switch (collectionFormat) { + case "csv": + default: + return StringUtil.join(stringArray, ","); + case "ssv": + return StringUtil.join(stringArray, " "); + case "tsv": + return StringUtil.join(stringArray, "\t"); + case "pipes": + return StringUtil.join(stringArray, "|"); + } + } + + /** + * URL encode a single query parameter. + * @param parameter The query parameter to encode. This object will not be + * changed. + * @return The URL encoded string representation of the parameter. If the + * parameter is null, returns null. + */ + public static String encode(Object parameter) { + if (parameter == null) { + return null; + } + try { + return URLEncoder.encode(parameter.toString(), "UTF-8"); + } catch (UnsupportedEncodingException e) { + // Should never happen, UTF-8 is always supported + throw new RuntimeException(e); + } + } +} diff --git a/libraries/feign/ParamExpander.mustache b/libraries/feign/ParamExpander.mustache new file mode 100644 index 00000000000..2f5095d00f0 --- /dev/null +++ b/libraries/feign/ParamExpander.mustache @@ -0,0 +1,22 @@ +package {{invokerPackage}}; + +import feign.Param; + +import java.text.DateFormat; +import java.util.Date; + +/** + * Param Expander to convert {@link Date} to RFC3339 + */ +public class ParamExpander implements Param.Expander { + + private static final DateFormat dateformat = new RFC3339DateFormat(); + + @Override + public String expand(Object value) { + if (value instanceof Date) { + return dateformat.format(value); + } + return value.toString(); + } +} diff --git a/libraries/feign/README.mustache b/libraries/feign/README.mustache new file mode 100644 index 00000000000..56560172ee3 --- /dev/null +++ b/libraries/feign/README.mustache @@ -0,0 +1,43 @@ +# {{artifactId}} + +## Requirements + +Building the API client library requires [Maven](https://maven.apache.org/) to be installed. + +## Installation & Usage + +To install the API client library to your local Maven repository, simply execute: + +```shell +mvn install +``` + +To deploy it to a remote Maven repository instead, configure the settings of the repository and execute: + +```shell +mvn deploy +``` + +Refer to the [official documentation](https://maven.apache.org/plugins/maven-deploy-plugin/usage.html) for more information. + +After the client library is installed/deployed, you can use it in your Maven project by adding the following to your *pom.xml*: + +```xml + + {{groupId}} + {{artifactId}} + {{artifactVersion}} + compile + + +``` + +## Recommendation + +It's recommended to create an instance of `ApiClient` per thread in a multithreaded environment to avoid any potential issues. + +## Author + +{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} +{{/hasMore}}{{/apis}}{{/apiInfo}} + diff --git a/libraries/feign/api.mustache b/libraries/feign/api.mustache new file mode 100644 index 00000000000..03eb7dd40cb --- /dev/null +++ b/libraries/feign/api.mustache @@ -0,0 +1,105 @@ +package {{package}}; + +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.EncodingUtils; +{{#legacyDates}} +import {{invokerPackage}}.ParamExpander; +{{/legacyDates}} + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} +import feign.*; + +{{>generatedAnnotation}} +public interface {{classname}} extends ApiClient.Api { + +{{#operations}}{{#operation}} + /** + * {{summary}} + * {{notes}} +{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} +{{/allParams}} +{{#returnType}} + * @return {{returnType}} +{{/returnType}} +{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation +{{/externalDocs}} + */ + @RequestLine("{{httpMethod}} {{{path}}}{{#hasQueryParams}}?{{/hasQueryParams}}{{#queryParams}}{{baseName}}={{=<% %>=}}{<%paramName%>}<%={{ }}=%>{{#hasMore}}&{{/hasMore}}{{/queryParams}}") + @Headers({ +{{#vendorExtensions.x-contentType}} "Content-Type: {{vendorExtensions.x-contentType}}", +{{/vendorExtensions.x-contentType}} "Accept: {{vendorExtensions.x-accepts}}",{{#headerParams}} + "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{#hasMore}}, + {{/hasMore}}{{/headerParams}} + }) + {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{paramName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{#hasQueryParams}} + + /** + * {{summary}} + * {{notes}} + * Note, this is equivalent to the other {{operationId}} method, + * but with the query parameters collected into a single Map parameter. This + * is convenient for services with optional query parameters, especially when + * used with the {@link {{operationIdCamelCase}}QueryParams} class that allows for + * building up this map in a fluent style. + {{#allParams}} + {{^isQueryParam}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/isQueryParam}} + {{/allParams}} + * @param queryParams Map of query parameters as name-value pairs + *

The following elements may be specified in the query map:

+ *
    + {{#queryParams}} + *
  • {{paramName}} - {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}
  • + {{/queryParams}} + *
+ {{#returnType}} + * @return {{returnType}} + {{/returnType}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + @RequestLine("{{httpMethod}} {{{path}}}?{{#queryParams}}{{baseName}}={{=<% %>=}}{<%paramName%>}<%={{ }}=%>{{#hasMore}}&{{/hasMore}}{{/queryParams}}") + @Headers({ +{{#vendorExtensions.x-contentType}} "Content-Type: {{vendorExtensions.x-contentType}}", +{{/vendorExtensions.x-contentType}} "Accept: {{vendorExtensions.x-accepts}}",{{#headerParams}} + "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{#hasMore}}, + {{/hasMore}}{{/headerParams}} + }) + {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isQueryParam}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{paramName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}, {{/isQueryParam}}{{/allParams}}@QueryMap(encoded=true) Map queryParams); + + /** + * A convenience class for generating query parameters for the + * {{operationId}} method in a fluent style. + */ + public static class {{operationIdCamelCase}}QueryParams extends HashMap { + {{#queryParams}} + public {{operationIdCamelCase}}QueryParams {{paramName}}(final {{{dataType}}} value) { + {{#collectionFormat}} + put("{{baseName}}", EncodingUtils.encodeCollection(value, "{{collectionFormat}}")); + {{/collectionFormat}} + {{^collectionFormat}} + put("{{baseName}}", EncodingUtils.encode(value)); + {{/collectionFormat}} + return this; + } + {{/queryParams}} + } + {{/hasQueryParams}} + {{/operation}} +{{/operations}} +} diff --git a/libraries/feign/api_test.mustache b/libraries/feign/api_test.mustache new file mode 100644 index 00000000000..bcc14a987c6 --- /dev/null +++ b/libraries/feign/api_test.mustache @@ -0,0 +1,70 @@ +package {{package}}; + +import {{invokerPackage}}.ApiClient; +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Before; +import org.junit.Test; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +public class {{classname}}Test { + + private {{classname}} api; + + @Before + public void setup() { + api = new ApiClient().buildClient({{classname}}.class); + } + + {{#operations}}{{#operation}} + /** + * {{summary}} + * + * {{notes}} + */ + @Test + public void {{operationId}}Test() { + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + // {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + + // TODO: test validations + } + + {{#hasQueryParams}} + /** + * {{summary}} + * + * {{notes}} + * + * This tests the overload of the method that uses a Map for query parameters instead of + * listing them out individually. + */ + @Test + public void {{operationId}}TestQueryMap() { + {{#allParams}} + {{^isQueryParam}} + {{{dataType}}} {{paramName}} = null; + {{/isQueryParam}} + {{/allParams}} + {{classname}}.{{operationIdCamelCase}}QueryParams queryParams = new {{classname}}.{{operationIdCamelCase}}QueryParams() + {{#queryParams}} + .{{paramName}}(null){{^hasMore}};{{/hasMore}} + {{/queryParams}} + // {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{^isQueryParam}}{{paramName}}, {{/isQueryParam}}{{/allParams}}queryParams); + + // TODO: test validations + } + {{/hasQueryParams}} + {{/operation}}{{/operations}} +} diff --git a/libraries/feign/auth/ApiKeyAuth.mustache b/libraries/feign/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..9982cd7fc49 --- /dev/null +++ b/libraries/feign/auth/ApiKeyAuth.mustache @@ -0,0 +1,41 @@ +package {{invokerPackage}}.auth; + +import feign.RequestInterceptor; +import feign.RequestTemplate; + +public class ApiKeyAuth implements RequestInterceptor { + private final String location; + private final String paramName; + + private String apiKey; + + public ApiKeyAuth(String location, String paramName) { + this.location = location; + this.paramName = paramName; + } + + public String getLocation() { + return location; + } + + public String getParamName() { + return paramName; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + @Override + public void apply(RequestTemplate template) { + if ("query".equals(location)) { + template.query(paramName, apiKey); + } else if ("header".equals(location)) { + template.header(paramName, apiKey); + } + } +} diff --git a/libraries/feign/auth/HttpBasicAuth.mustache b/libraries/feign/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..2b1acb8ff74 --- /dev/null +++ b/libraries/feign/auth/HttpBasicAuth.mustache @@ -0,0 +1,41 @@ +package {{invokerPackage}}.auth; + +import feign.RequestInterceptor; +import feign.RequestTemplate; +import feign.auth.BasicAuthRequestInterceptor; + +/** + * An interceptor that adds the request header needed to use HTTP basic authentication. + */ +public class HttpBasicAuth implements RequestInterceptor { + + private String username; + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public void setCredentials(String username, String password) { + this.username = username; + this.password = password; + } + + @Override + public void apply(RequestTemplate template) { + RequestInterceptor requestInterceptor = new BasicAuthRequestInterceptor(username, password); + requestInterceptor.apply(template); + } +} diff --git a/libraries/feign/auth/OAuth.mustache b/libraries/feign/auth/OAuth.mustache new file mode 100644 index 00000000000..1df88d403a2 --- /dev/null +++ b/libraries/feign/auth/OAuth.mustache @@ -0,0 +1,197 @@ +package {{invokerPackage}}.auth; + +import java.io.IOException; +import java.util.Collection; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.oltu.oauth2.client.HttpClient; +import org.apache.oltu.oauth2.client.OAuthClient; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; +import org.apache.oltu.oauth2.client.response.OAuthClientResponse; +import org.apache.oltu.oauth2.client.response.OAuthClientResponseFactory; +import org.apache.oltu.oauth2.client.response.OAuthJSONAccessTokenResponse; +import org.apache.oltu.oauth2.common.exception.OAuthProblemException; +import org.apache.oltu.oauth2.common.exception.OAuthSystemException; +import org.apache.oltu.oauth2.common.message.types.GrantType; +import org.apache.oltu.oauth2.common.token.BasicOAuthToken; + +import feign.Client; +import feign.Request.Options; +import feign.RequestInterceptor; +import feign.RequestTemplate; +import feign.Response; +import feign.RetryableException; +import feign.Util; +import {{invokerPackage}}.StringUtil; + + +public class OAuth implements RequestInterceptor { + + static final int MILLIS_PER_SECOND = 1000; + + public interface AccessTokenListener { + void notify(BasicOAuthToken token); + } + + private volatile String accessToken; + private Long expirationTimeMillis; + private OAuthClient oauthClient; + private TokenRequestBuilder tokenRequestBuilder; + private AuthenticationRequestBuilder authenticationRequestBuilder; + private AccessTokenListener accessTokenListener; + + public OAuth(Client client, TokenRequestBuilder requestBuilder) { + this.oauthClient = new OAuthClient(new OAuthFeignClient(client)); + this.tokenRequestBuilder = requestBuilder; + } + + public OAuth(Client client, OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { + this(client, OAuthClientRequest.tokenLocation(tokenUrl).setScope(scopes)); + + switch(flow) { + case accessCode: + case implicit: + tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE); + break; + case password: + tokenRequestBuilder.setGrantType(GrantType.PASSWORD); + break; + case application: + tokenRequestBuilder.setGrantType(GrantType.CLIENT_CREDENTIALS); + break; + default: + break; + } + authenticationRequestBuilder = OAuthClientRequest.authorizationLocation(authorizationUrl); + } + + public OAuth(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { + this(new Client.Default(null, null), flow, authorizationUrl, tokenUrl, scopes); + } + + @Override + public void apply(RequestTemplate template) { + // If the request already have an authorization (eg. Basic auth), do nothing + if (template.headers().containsKey("Authorization")) { + return; + } + // If first time, get the token + if (expirationTimeMillis == null || System.currentTimeMillis() >= expirationTimeMillis) { + updateAccessToken(); + } + if (getAccessToken() != null) { + template.header("Authorization", "Bearer " + getAccessToken()); + } + } + + public synchronized void updateAccessToken() { + OAuthJSONAccessTokenResponse accessTokenResponse; + try { + accessTokenResponse = oauthClient.accessToken(tokenRequestBuilder.buildBodyMessage()); + } catch (Exception e) { + throw new RetryableException(e.getMessage(), e,null); + } + if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { + setAccessToken(accessTokenResponse.getAccessToken(), accessTokenResponse.getExpiresIn()); + if (accessTokenListener != null) { + accessTokenListener.notify((BasicOAuthToken) accessTokenResponse.getOAuthToken()); + } + } + } + + public synchronized void registerAccessTokenListener(AccessTokenListener accessTokenListener) { + this.accessTokenListener = accessTokenListener; + } + + public synchronized String getAccessToken() { + return accessToken; + } + + public synchronized void setAccessToken(String accessToken, Long expiresIn) { + this.accessToken = accessToken; + this.expirationTimeMillis = System.currentTimeMillis() + expiresIn * MILLIS_PER_SECOND; + } + + public TokenRequestBuilder getTokenRequestBuilder() { + return tokenRequestBuilder; + } + + public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) { + this.tokenRequestBuilder = tokenRequestBuilder; + } + + public AuthenticationRequestBuilder getAuthenticationRequestBuilder() { + return authenticationRequestBuilder; + } + + public void setAuthenticationRequestBuilder(AuthenticationRequestBuilder authenticationRequestBuilder) { + this.authenticationRequestBuilder = authenticationRequestBuilder; + } + + public OAuthClient getOauthClient() { + return oauthClient; + } + + public void setOauthClient(OAuthClient oauthClient) { + this.oauthClient = oauthClient; + } + + public void setOauthClient(Client client) { + this.oauthClient = new OAuthClient( new OAuthFeignClient(client)); + } + + public static class OAuthFeignClient implements HttpClient { + + private Client client; + + public OAuthFeignClient() { + this.client = new Client.Default(null, null); + } + + public OAuthFeignClient(Client client) { + this.client = client; + } + + public T execute(OAuthClientRequest request, Map headers, + String requestMethod, Class responseClass) + throws OAuthSystemException, OAuthProblemException { + + RequestTemplate req = new RequestTemplate() + .append(request.getLocationUri()) + .method(requestMethod) + .body(request.getBody()); + + for (Entry entry : headers.entrySet()) { + req.header(entry.getKey(), entry.getValue()); + } + Response feignResponse; + String body = ""; + try { + feignResponse = client.execute(req.request(), new Options()); + body = Util.toString(feignResponse.body().asReader()); + } catch (IOException e) { + throw new OAuthSystemException(e); + } + + String contentType = null; + Collection contentTypeHeader = feignResponse.headers().get("Content-Type"); + if(contentTypeHeader != null) { + contentType = StringUtil.join(contentTypeHeader.toArray(new String[0]), ";"); + } + + return OAuthClientResponseFactory.createCustomResponse( + body, + contentType, + feignResponse.status(), + responseClass + ); + } + + public void shutdown() { + // Nothing to do here + } + } +} diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache new file mode 100644 index 00000000000..0074c0e38a2 --- /dev/null +++ b/libraries/feign/build.gradle.mustache @@ -0,0 +1,135 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + } + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + sourceCompatibility = JavaVersion.VERSION_{{^java8}}1_7{{/java8}}{{#java8}}1_8{{/java8}} + targetCompatibility = JavaVersion.VERSION_{{^java8}}1_7{{/java8}}{{#java8}}1_8{{/java8}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + swagger_annotations_version = "1.5.9" + jackson_version = "2.8.7" + {{#threetenbp}} + threepane_version = "2.6.4" + {{/threetenbp}} + feign_version = "9.4.0" + feign_form_version = "2.1.0" + junit_version = "4.12" + oltu_version = "1.0.1" +} + +dependencies { + compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "io.github.openfeign:feign-core:$feign_version" + compile "io.github.openfeign:feign-jackson:$feign_version" + compile "io.github.openfeign:feign-slf4j:$feign_version" + compile "io.github.openfeign.form:feign-form:$feign_form_version" + compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + {{#joda}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + {{/joda}} + {{#java8}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{/java8}} + {{#threetenbp}} + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$threepane_version" + {{/threetenbp}} + compile "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version" + compile "com.brsanthu:migbase64:2.2" + testCompile "junit:junit:$junit_version" +} diff --git a/libraries/feign/build.sbt.mustache b/libraries/feign/build.sbt.mustache new file mode 100644 index 00000000000..d745ef7e86d --- /dev/null +++ b/libraries/feign/build.sbt.mustache @@ -0,0 +1,26 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "io.swagger" % "swagger-annotations" % "1.5.9" % "compile", + "io.github.openfeign" % "feign-core" % "9.4.0" % "compile", + "io.github.openfeign" % "feign-jackson" % "9.4.0" % "compile", + "io.github.openfeign" % "feign-slf4j" % "9.4.0" % "compile", + "io.github.openfeign.form" % "feign-form" % "2.1.0" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.8.7" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.7" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.7" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}" % "2.8.7" % "compile", + "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", + "com.brsanthu" % "migbase64" % "2.2" % "compile", + "junit" % "junit" % "4.12" % "test", + "com.novocode" % "junit-interface" % "0.10" % "test" + ) + ) diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache new file mode 100644 index 00000000000..ad255c13ea4 --- /dev/null +++ b/libraries/feign/pom.mustache @@ -0,0 +1,308 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{artifactUrl}} + {{artifactDescription}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-core-version} + + + + + io.github.openfeign + feign-core + ${feign-version} + + + io.github.openfeign + feign-jackson + ${feign-version} + + + io.github.openfeign + feign-slf4j + ${feign-version} + + + io.github.openfeign.form + feign-form + ${feign-form-version} + + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-version} + + {{#withXml}} + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson-version} + + + {{/withXml}} + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + {{/joda}} + {{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{/java8}} + {{#threetenbp}} + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${jackson-threetenbp-version} + + {{/threetenbp}} + + org.apache.oltu.oauth2 + org.apache.oltu.oauth2.client + ${oltu-version} + + + + + junit + junit + ${junit-version} + test + + + com.squareup.okhttp3 + mockwebserver + 3.6.0 + test + + + org.assertj + assertj-core + 1.7.1 + test + + + + UTF-8 + {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}} + ${java.version} + ${java.version} + 1.5.18 + 9.4.0 + 2.1.0 + 2.8.9 + {{#threetenbp}} + 2.6.4 + {{/threetenbp}} + 4.12 + 1.0.0 + 1.0.1 + + diff --git a/libraries/google-api-client/ApiClient.mustache b/libraries/google-api-client/ApiClient.mustache new file mode 100644 index 00000000000..fa6e7a601fe --- /dev/null +++ b/libraries/google-api-client/ApiClient.mustache @@ -0,0 +1,109 @@ +package {{invokerPackage}}; + +import {{apiPackage}}.*; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +{{#joda}} +import com.fasterxml.jackson.datatype.joda.JodaModule; +{{/joda}} +{{#java8}} +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{/java8}} +{{#threetenbp}} +import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; +{{/threetenbp}} +{{#threetenbp}} +import org.threeten.bp.*; +{{/threetenbp}} +import com.google.api.client.googleapis.util.Utils; +import com.google.api.client.http.AbstractHttpContent; +import com.google.api.client.http.HttpRequestFactory; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.HttpTransport; +import com.google.api.client.json.Json; + +import java.io.IOException; +import java.io.OutputStream; + +{{>generatedAnnotation}} +public class ApiClient { + private final String basePath; + private final HttpRequestFactory httpRequestFactory; + private final ObjectMapper objectMapper; + + private static final String defaultBasePath = "{{basePath}}"; + + // A reasonable default object mapper. Client can pass in a chosen ObjectMapper anyway, this is just for reasonable defaults. + private static ObjectMapper createDefaultObjectMapper() { + ObjectMapper objectMapper = new ObjectMapper() + .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) + .setDateFormat(new RFC3339DateFormat()); + {{#joda}} + objectMapper.registerModule(new JodaModule()); + {{/joda}} + {{#java8}} + objectMapper.registerModule(new JavaTimeModule()); + {{/java8}} + {{#threetenbp}} + ThreeTenModule module = new ThreeTenModule(); + module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); + module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); + module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); + objectMapper.registerModule(module); + {{/threetenbp}} + return objectMapper; + } + + public ApiClient() { + this(null, null, null, null); + } + + public ApiClient( + String basePath, + HttpTransport httpTransport, + HttpRequestInitializer initializer, + ObjectMapper objectMapper + ) { + this.basePath = basePath == null ? defaultBasePath : ( + basePath.endsWith("/") ? basePath.substring(0, basePath.length() - 1) : basePath + ); + this.httpRequestFactory = (httpTransport == null ? Utils.getDefaultTransport() : httpTransport).createRequestFactory(initializer); + this.objectMapper = (objectMapper == null ? createDefaultObjectMapper() : objectMapper); + } + + public HttpRequestFactory getHttpRequestFactory() { + return httpRequestFactory; + } + + public String getBasePath() { + return basePath; + } + + public ObjectMapper getObjectMapper() { + return objectMapper; + } + + public class JacksonJsonHttpContent extends AbstractHttpContent { + /* A POJO that can be serialized with a com.fasterxml Jackson ObjectMapper */ + private final Object data; + + public JacksonJsonHttpContent(Object data) { + super(Json.MEDIA_TYPE); + this.data = data; + } + + @Override + public void writeTo(OutputStream out) throws IOException { + objectMapper.writeValue(out, data); + } + } + + // Builder pattern to get API instances for this client. + {{#apiInfo}}{{#apis}} + public {{classname}} {{classVarName}}Api() { + return new {{classname}}(this); + } + {{/apis}}{{/apiInfo}} +} diff --git a/libraries/google-api-client/api.mustache b/libraries/google-api-client/api.mustache new file mode 100644 index 00000000000..46ecf3af355 --- /dev/null +++ b/libraries/google-api-client/api.mustache @@ -0,0 +1,189 @@ +package {{package}}; + +import {{invokerPackage}}.ApiClient; + +{{#imports}}import {{import}}; +{{/imports}} + +import com.fasterxml.jackson.core.type.TypeReference; +import com.google.api.client.http.GenericUrl; +import com.google.api.client.http.HttpContent; +import com.google.api.client.http.InputStreamContent; +import com.google.api.client.http.HttpMethods; +import com.google.api.client.http.HttpResponse; +import com.google.api.client.json.Json; + +import javax.ws.rs.core.UriBuilder; +import java.io.IOException; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.List; +import java.util.ArrayList; + +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}} { + private ApiClient {{localVariablePrefix}}apiClient; + + public {{classname}}() { + this(new ApiClient()); + } + + public {{classname}}(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + public ApiClient getApiClient() { + return {{localVariablePrefix}}apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + {{#operation}} + /**{{#summary}} + * {{summary}}{{/summary}}{{#notes}} + * {{notes}}{{/notes}}{{#responses}} + *

{{code}}{{#message}} - {{message}}{{/message}}{{/responses}}{{#allParams}} + * @param {{paramName}} {{description}}{{^description}}The {{paramName}} parameter{{/description}}{{/allParams}}{{#returnType}} + * @return {{returnType}}{{/returnType}} + * @throws IOException if an error occurs while attempting to invoke the API{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + + **/ + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws IOException { + {{#returnType}}HttpResponse response = {{/returnType}}{{operationId}}ForHttpResponse({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + TypeReference typeRef = new TypeReference<{{{returnType}}}>() {}; + return apiClient.getObjectMapper().readValue(response.getContent(), typeRef);{{/returnType}} + } + + /**{{#summary}} + * {{summary}}{{/summary}}{{#notes}} + * {{notes}}{{/notes}}{{#responses}} + *

{{code}}{{#message}} - {{message}}{{/message}}{{/responses}}{{#requiredParams}} + * @param {{paramName}} {{description}}{{^description}}The {{paramName}} parameter{{/description}}{{/requiredParams}} + * @param params Map of query params. A collection will be interpreted as passing in multiple instances of the same query param.{{#returnType}} + * @return {{returnType}}{{/returnType}} + * @throws IOException if an error occurs while attempting to invoke the API{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + + **/ + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#bodyParam}}{{^required}}{{{dataType}}} {{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}Map params) throws IOException { + {{#returnType}}HttpResponse response = {{/returnType}}{{operationId}}ForHttpResponse({{#bodyParam}}{{^required}}{{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}params);{{#returnType}} + TypeReference typeRef = new TypeReference<{{{returnType}}}>() {}; + return apiClient.getObjectMapper().readValue(response.getContent(), typeRef);{{/returnType}} + } + + public HttpResponse {{operationId}}ForHttpResponse({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws IOException { + {{#allParams}}{{#required}}// verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new IllegalArgumentException("Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + }{{/required}}{{/allParams}} + {{#hasPathParams}} + // create a map of path variables + final Map uriVariables = new HashMap();{{#pathParams}} + uriVariables.put("{{baseName}}", {{{paramName}}});{{/pathParams}} + {{/hasPathParams}} + UriBuilder uriBuilder = UriBuilder.fromUri(apiClient.getBasePath() + "{{{path}}}");{{#hasQueryParams}} + {{#queryParams}} + if ({{paramName}} != null) { + String key = "{{baseName}}"; + Object value = {{paramName}}; + if (value instanceof Collection) { + uriBuilder = uriBuilder.queryParam(key, ((Collection) value).toArray()); + } else if (value instanceof Object[]) { + uriBuilder = uriBuilder.queryParam(key, (Object[]) value); + } else { + uriBuilder = uriBuilder.queryParam(key, value); + } + }{{/queryParams}}{{/hasQueryParams}} + + String url = uriBuilder{{#hasPathParams}}.buildFromMap(uriVariables).toString();{{/hasPathParams}}{{^hasPathParams}}.build().toString();{{/hasPathParams}} + GenericUrl genericUrl = new GenericUrl(url); + + HttpContent content = {{#isBodyAllowed}}apiClient.new JacksonJsonHttpContent({{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}){{/isBodyAllowed}}{{^isBodyAllowed}}null{{/isBodyAllowed}}; + return apiClient.getHttpRequestFactory().buildRequest(HttpMethods.{{httpMethod}}, genericUrl, content).execute(); + }{{#bodyParam}} + + public HttpResponse {{operationId}}ForHttpResponse({{#allParams}}{{#isBodyParam}}java.io.InputStream {{paramName}}{{/isBodyParam}}{{^isBodyParam}}{{{dataType}}} {{paramName}}{{/isBodyParam}}{{#hasMore}}, {{/hasMore}}{{/allParams}}, String mediaType) throws IOException { + {{#allParams}}{{#required}}// verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new IllegalArgumentException("Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + }{{/required}}{{/allParams}} + {{#hasPathParams}} + // create a map of path variables + final Map uriVariables = new HashMap();{{#pathParams}} + uriVariables.put("{{baseName}}", {{{paramName}}});{{/pathParams}} + {{/hasPathParams}} + UriBuilder uriBuilder = UriBuilder.fromUri(apiClient.getBasePath() + "{{{path}}}");{{#hasQueryParams}} + {{#queryParams}} + if ({{paramName}} != null) { + String key = "{{baseName}}"; + Object value = {{paramName}}; + if (value instanceof Collection) { + uriBuilder = uriBuilder.queryParam(key, ((Collection) value).toArray()); + } else if (value instanceof Object[]) { + uriBuilder = uriBuilder.queryParam(key, (Object[]) value); + } else { + uriBuilder = uriBuilder.queryParam(key, value); + } + }{{/queryParams}}{{/hasQueryParams}} + + String url = uriBuilder{{#hasPathParams}}.buildFromMap(uriVariables).toString();{{/hasPathParams}}{{^hasPathParams}}.build().toString();{{/hasPathParams}} + GenericUrl genericUrl = new GenericUrl(url); + + HttpContent content = {{#bodyParam}}{{paramName}} == null ? + apiClient.new JacksonJsonHttpContent(null) : + new InputStreamContent(mediaType == null ? Json.MEDIA_TYPE : mediaType, {{paramName}}){{/bodyParam}}; + return apiClient.getHttpRequestFactory().buildRequest(HttpMethods.{{httpMethod}}, genericUrl, content).execute(); + }{{/bodyParam}} + + public HttpResponse {{operationId}}ForHttpResponse({{#bodyParam}}{{^required}}{{{dataType}}} {{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}Map params) throws IOException { + {{#allParams}}{{#required}}// verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new IllegalArgumentException("Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + }{{/required}}{{/allParams}} + {{#hasPathParams}} + // create a map of path variables + final Map uriVariables = new HashMap();{{#pathParams}} + uriVariables.put("{{baseName}}", {{{paramName}}});{{/pathParams}} + {{/hasPathParams}} + UriBuilder uriBuilder = UriBuilder.fromUri(apiClient.getBasePath() + "{{{path}}}"); + + // Copy the params argument if present, to allow passing in immutable maps + Map allParams = params == null ? new HashMap() : new HashMap(params);{{#queryParams}}{{#required}} + // Add the required query param '{{paramName}}' to the map of query params + allParams.put("{{paramName}}", {{paramName}});{{/required}}{{/queryParams}} + + for (Map.Entry entry: allParams.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + + if (key != null && value != null) { + if (value instanceof Collection) { + uriBuilder = uriBuilder.queryParam(key, ((Collection) value).toArray()); + } else if (value instanceof Object[]) { + uriBuilder = uriBuilder.queryParam(key, (Object[]) value); + } else { + uriBuilder = uriBuilder.queryParam(key, value); + } + } + } + + String url = uriBuilder{{#hasPathParams}}.buildFromMap(uriVariables).toString();{{/hasPathParams}}{{^hasPathParams}}.build().toString();{{/hasPathParams}} + GenericUrl genericUrl = new GenericUrl(url); + + HttpContent content = {{#isBodyAllowed}}apiClient.new JacksonJsonHttpContent({{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}){{/isBodyAllowed}}{{^isBodyAllowed}}null{{/isBodyAllowed}}; + return apiClient.getHttpRequestFactory().buildRequest(HttpMethods.{{httpMethod}}, genericUrl, content).execute(); + } + + + {{/operation}} +} +{{/operations}} diff --git a/libraries/google-api-client/api_test.mustache b/libraries/google-api-client/api_test.mustache new file mode 100644 index 00000000000..365106fbedf --- /dev/null +++ b/libraries/google-api-client/api_test.mustache @@ -0,0 +1,45 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Test; +import org.junit.Ignore; + +import java.io.IOException; +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +@Ignore +public class {{classname}}Test { + + private final {{classname}} api = new {{classname}}(); + + {{#operations}}{{#operation}} + /** + * {{summary}} + * + * {{notes}} + * + * @throws IOException + * if the Api call fails + */ + @Test + public void {{operationId}}Test() throws IOException { + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + + // TODO: test validations + } + {{/operation}}{{/operations}} +} diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache new file mode 100644 index 00000000000..e6197b08f7a --- /dev/null +++ b/libraries/google-api-client/build.gradle.mustache @@ -0,0 +1,142 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.5.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 23 + buildToolsVersion '23.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 22 + } + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + {{#java8}} + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + {{/java8}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + swagger_annotations_version = "1.5.17" + jackson_version = "2.8.9" + google_api_client_version = "1.23.0" + jersey_common_version = "2.25.1" + jodatime_version = "2.9.9" + junit_version = "4.12" + {{#threetenbp}} + jackson_threeten_version = "2.6.4" + {{/threetenbp}} +} + +dependencies { + compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "com.google.api-client:google-api-client:${google_api_client_version}" + compile "org.glassfish.jersey.core:jersey-common:${jersey_common_version}" + compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + {{#java8}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{/java8}} + {{#joda}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + compile "joda-time:joda-time:$jodatime_version" + {{/joda}} + {{#threetenbp}} + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threeten_version" + {{/threetenbp}} + {{#withXml}} + compile "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jackson_version" + {{/withXml}} + testCompile "junit:junit:$junit_version" +} diff --git a/libraries/google-api-client/build.sbt.mustache b/libraries/google-api-client/build.sbt.mustache new file mode 100644 index 00000000000..d6b88c91d96 --- /dev/null +++ b/libraries/google-api-client/build.sbt.mustache @@ -0,0 +1,33 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "io.swagger" % "swagger-annotations" % "1.5.17", + "com.google.api-client" % "google-api-client" % "1.23.0", + "org.glassfish.jersey.core" % "jersey-common" % "2.25.1", + "com.fasterxml.jackson.core" % "jackson-core" % "2.8.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.9" % "compile", + {{#withXml}} + "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.8.9" % "compile", + {{/withXml}} + {{#joda}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.8.9" % "compile", + {{/joda}} + {{#java8}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.8.9" % "compile", + {{/java8}} + {{#threetenbp}} + "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4" % "compile", + {{/threetenbp}} + "junit" % "junit" % "4.12" % "test", + "com.novocode" % "junit-interface" % "0.10" % "test" + ) + ) diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache new file mode 100644 index 00000000000..fb2d2bdfab7 --- /dev/null +++ b/libraries/google-api-client/pom.mustache @@ -0,0 +1,299 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{artifactUrl}} + {{artifactDescription}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + {{#java8}} + + 1.8 + 1.8 + {{/java8}} + {{^java8}} + + 1.7 + 1.7 + {{/java8}} + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-annotations-version} + + + + com.google.api-client + google-api-client + ${google-api-client-version} + + + + org.glassfish.jersey.core + jersey-common + ${jersey-common-version} + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-version} + + {{#withXml}} + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson-version} + + {{/withXml}} + {{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{/java8}} + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + + joda-time + joda-time + ${jodatime-version} + + {{/joda}} + {{#threetenbp}} + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${jackson-threetenbp-version} + + {{/threetenbp}} + + + + junit + junit + ${junit-version} + test + + + + UTF-8 + 1.5.17 + 1.23.0 + 2.25.1 + 2.8.9 + {{#joda}} + 2.9.9 + {{/joda}} + {{#threetenbp}} + 2.6.4 + {{/threetenbp}} + 1.0.0 + 4.12 + + diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache new file mode 100644 index 00000000000..a699e001f17 --- /dev/null +++ b/libraries/jersey2/ApiClient.mustache @@ -0,0 +1,799 @@ +package {{invokerPackage}}; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.Form; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.glassfish.jersey.client.ClientConfig; +import org.glassfish.jersey.client.ClientProperties; +import org.glassfish.jersey.client.HttpUrlConnectorProvider; +import org.glassfish.jersey.jackson.JacksonFeature; +import org.glassfish.jersey.media.multipart.FormDataBodyPart; +import org.glassfish.jersey.media.multipart.FormDataContentDisposition; +import org.glassfish.jersey.media.multipart.MultiPart; +import org.glassfish.jersey.media.multipart.MultiPartFeature; + +import java.io.IOException; +import java.io.InputStream; + +{{^supportJava6}} +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import org.glassfish.jersey.logging.LoggingFeature; +{{/supportJava6}} +{{#supportJava6}} +import org.apache.commons.io.FileUtils; +import org.glassfish.jersey.filter.LoggingFilter; +{{/supportJava6}} +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Map.Entry; +import java.util.HashMap; +import java.util.List; +import java.util.ArrayList; +import java.util.Date; +import java.util.TimeZone; + +import java.net.URLEncoder; + +import java.io.File; +import java.io.UnsupportedEncodingException; + +import java.text.DateFormat; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import {{invokerPackage}}.auth.Authentication; +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.OAuth; + +{{>generatedAnnotation}} +public class ApiClient { + protected Map defaultHeaderMap = new HashMap(); + protected String basePath = "{{{basePath}}}"; + protected boolean debugging = false; + protected int connectionTimeout = 0; + private int readTimeout = 0; + + protected Client httpClient; + protected JSON json; + protected String tempFolderPath = null; + + protected Map authentications; + + protected DateFormat dateFormat; + + public ApiClient() { + json = new JSON(); + httpClient = buildHttpClient(debugging); + + this.dateFormat = new RFC3339DateFormat(); + + // Set default User-Agent. + setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}Swagger-Codegen/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap();{{#authMethods}}{{#isBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + } + + /** + * Gets the JSON instance to do JSON serialization and deserialization. + * @return JSON + */ + public JSON getJSON() { + return json; + } + + public Client getHttpClient() { + return httpClient; + } + + public ApiClient setHttpClient(Client httpClient) { + this.httpClient = httpClient; + return this; + } + + public String getBasePath() { + return basePath; + } + + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Get authentications (key: authentication name, value: authentication). + * @return Map of authentication object + */ + public Map getAuthentications() { + return authentications; + } + + /** + * Get authentication for the given name. + * + * @param authName The authentication name + * @return The authentication, null if not found + */ + public Authentication getAuthentication(String authName) { + return authentications.get(authName); + } + + /** + * Helper method to set username for the first HTTP basic authentication. + * @param username Username + */ + public void setUsername(String username) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setUsername(username); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set password for the first HTTP basic authentication. + * @param password Password + */ + public void setPassword(String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setPassword(password); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set API key value for the first API key authentication. + * @param apiKey API key + */ + public void setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + * @param apiKeyPrefix API key prefix + */ + public void setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set access token for the first OAuth2 authentication. + * @param accessToken Access token + */ + public void setAccessToken(String accessToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setAccessToken(accessToken); + return; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Set the User-Agent header's value (by adding to the default header map). + * @param userAgent Http user agent + * @return API client + */ + public ApiClient setUserAgent(String userAgent) { + addDefaultHeader("User-Agent", userAgent); + return this; + } + + /** + * Add a default header. + * + * @param key The header's key + * @param value The header's value + * @return API client + */ + public ApiClient addDefaultHeader(String key, String value) { + defaultHeaderMap.put(key, value); + return this; + } + + /** + * Check that whether debugging is enabled for this API client. + * @return True if debugging is switched on + */ + public boolean isDebugging() { + return debugging; + } + + /** + * Enable/disable debugging for this API client. + * + * @param debugging To enable (true) or disable (false) debugging + * @return API client + */ + public ApiClient setDebugging(boolean debugging) { + this.debugging = debugging; + // Rebuild HTTP Client according to the new "debugging" value. + this.httpClient = buildHttpClient(debugging); + return this; + } + + /** + * The path of temporary folder used to store downloaded files from endpoints + * with file response. The default value is null, i.e. using + * the system's default tempopary folder. + * + * @return Temp folder path + */ + public String getTempFolderPath() { + return tempFolderPath; + } + + /** + * Set temp folder path + * @param tempFolderPath Temp folder path + * @return API client + */ + public ApiClient setTempFolderPath(String tempFolderPath) { + this.tempFolderPath = tempFolderPath; + return this; + } + + /** + * Connect timeout (in milliseconds). + * @return Connection timeout + */ + public int getConnectTimeout() { + return connectionTimeout; + } + + /** + * Set the connect timeout (in milliseconds). + * A value of 0 means no timeout, otherwise values must be between 1 and + * {@link Integer#MAX_VALUE}. + * @param connectionTimeout Connection timeout in milliseconds + * @return API client + */ + public ApiClient setConnectTimeout(int connectionTimeout) { + this.connectionTimeout = connectionTimeout; + httpClient.property(ClientProperties.CONNECT_TIMEOUT, connectionTimeout); + return this; + } + + /** + * read timeout (in milliseconds). + * @return Read timeout + */ + public int getReadTimeout() { + return readTimeout; + } + + /** + * Set the read timeout (in milliseconds). + * A value of 0 means no timeout, otherwise values must be between 1 and + * {@link Integer#MAX_VALUE}. + * @param readTimeout Read timeout in milliseconds + * @return API client + */ + public ApiClient setReadTimeout(int readTimeout) { + this.readTimeout = readTimeout; + httpClient.property(ClientProperties.READ_TIMEOUT, readTimeout); + return this; + } + + /** + * Get the date format used to parse/format date parameters. + * @return Date format + */ + public DateFormat getDateFormat() { + return dateFormat; + } + + /** + * Set the date format used to parse/format date parameters. + * @param dateFormat Date format + * @return API client + */ + public ApiClient setDateFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + // also set the date format for model (de)serialization with Date properties + this.json.setDateFormat((DateFormat) dateFormat.clone()); + return this; + } + + /** + * Parse the given string into Date object. + * @param str String + * @return Date + */ + public Date parseDate(String str) { + try { + return dateFormat.parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(e); + } + } + + /** + * Format the given Date object into string. + * @param date Date + * @return Date in string format + */ + public String formatDate(Date date) { + return dateFormat.format(date); + } + + /** + * Format the given parameter object into string. + * @param param Object + * @return Object in string format + */ + public String parameterToString(Object param) { + if (param == null) { + return ""; + } else if (param instanceof Date) { + return formatDate((Date) param); + } else if (param instanceof Collection) { + StringBuilder b = new StringBuilder(); + for(Object o : (Collection)param) { + if(b.length() > 0) { + b.append(','); + } + b.append(String.valueOf(o)); + } + return b.toString(); + } else { + return String.valueOf(param); + } + } + + /* + * Format to {@code Pair} objects. + * @param collectionFormat Collection format + * @param name Name + * @param value Value + * @return List of pairs + */ + public List parameterToPairs(String collectionFormat, String name, Object value){ + List params = new ArrayList(); + + // preconditions + if (name == null || name.isEmpty() || value == null) return params; + + Collection valueCollection; + if (value instanceof Collection) { + valueCollection = (Collection) value; + } else { + params.add(new Pair(name, parameterToString(value))); + return params; + } + + if (valueCollection.isEmpty()){ + return params; + } + + // get the collection format (default: csv) + String format = (collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat); + + // create the params based on the collection format + if ("multi".equals(format)) { + for (Object item : valueCollection) { + params.add(new Pair(name, parameterToString(item))); + } + + return params; + } + + String delimiter = ","; + + if ("csv".equals(format)) { + delimiter = ","; + } else if ("ssv".equals(format)) { + delimiter = " "; + } else if ("tsv".equals(format)) { + delimiter = "\t"; + } else if ("pipes".equals(format)) { + delimiter = "|"; + } + + StringBuilder sb = new StringBuilder() ; + for (Object item : valueCollection) { + sb.append(delimiter); + sb.append(parameterToString(item)); + } + + params.add(new Pair(name, sb.substring(1))); + + return params; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * application/vnd.company+json + * "* / *" is also default to JSON + * @param mime MIME + * @return True if the MIME type is JSON + */ + public boolean isJsonMime(String mime) { + String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$"; + return mime != null && (mime.matches(jsonMime) || mime.equals("*/*")); + } + + /** + * Select the Accept header's value from the given accepts array: + * if JSON exists in the given array, use it; + * otherwise use all of them (joining into a string) + * + * @param accepts The accepts array to select from + * @return The Accept header to use. If the given array is empty, + * null will be returned (not to set the Accept header explicitly). + */ + public String selectHeaderAccept(String[] accepts) { + if (accepts.length == 0) { + return null; + } + for (String accept : accepts) { + if (isJsonMime(accept)) { + return accept; + } + } + return StringUtil.join(accepts, ","); + } + + /** + * Select the Content-Type header's value from the given array: + * if JSON exists in the given array, use it; + * otherwise use the first one of the array. + * + * @param contentTypes The Content-Type array to select from + * @return The Content-Type header to use. If the given array is empty, + * JSON will be used. + */ + public String selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0) { + return "application/json"; + } + for (String contentType : contentTypes) { + if (isJsonMime(contentType)) { + return contentType; + } + } + return contentTypes[0]; + } + + /** + * Escape the given string to be used as URL query value. + * @param str String + * @return Escaped string + */ + public String escapeString(String str) { + try { + return URLEncoder.encode(str, "utf8").replaceAll("\\+", "%20"); + } catch (UnsupportedEncodingException e) { + return str; + } + } + + /** + * Serialize the given Java object into string entity according the given + * Content-Type (only JSON is supported for now). + * @param obj Object + * @param formParams Form parameters + * @param contentType Context type + * @return Entity + * @throws ApiException API exception + */ + public Entity serialize(Object obj, Map formParams, String contentType) throws ApiException { + Entity entity; + if (contentType.startsWith("multipart/form-data")) { + MultiPart multiPart = new MultiPart(); + for (Entry param: formParams.entrySet()) { + if (param.getValue() instanceof File) { + File file = (File) param.getValue(); + FormDataContentDisposition contentDisp = FormDataContentDisposition.name(param.getKey()) + .fileName(file.getName()).size(file.length()).build(); + multiPart.bodyPart(new FormDataBodyPart(contentDisp, file, MediaType.APPLICATION_OCTET_STREAM_TYPE)); + } else { + FormDataContentDisposition contentDisp = FormDataContentDisposition.name(param.getKey()).build(); + multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(param.getValue()))); + } + } + entity = Entity.entity(multiPart, MediaType.MULTIPART_FORM_DATA_TYPE); + } else if (contentType.startsWith("application/x-www-form-urlencoded")) { + Form form = new Form(); + for (Entry param: formParams.entrySet()) { + form.param(param.getKey(), parameterToString(param.getValue())); + } + entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE); + } else { + // We let jersey handle the serialization + entity = Entity.entity(obj, contentType); + } + return entity; + } + + /** + * Deserialize response body to Java object according to the Content-Type. + * @param Type + * @param response Response + * @param returnType Return type + * @return Deserialize object + * @throws ApiException API exception + */ + @SuppressWarnings("unchecked") + public T deserialize(Response response, GenericType returnType) throws ApiException { + if (response == null || returnType == null) { + return null; + } + + if ("byte[]".equals(returnType.toString())) { + // Handle binary response (byte array). + return (T) response.readEntity(byte[].class); + } else if (returnType.getRawType() == File.class) { + // Handle file downloading. + T file = (T) downloadFileFromResponse(response); + return file; + } + + String contentType = null; + List contentTypes = response.getHeaders().get("Content-Type"); + if (contentTypes != null && !contentTypes.isEmpty()) + contentType = String.valueOf(contentTypes.get(0)); + + return response.readEntity(returnType); + } + + /** + * Download file from the given response. + * @param response Response + * @return File + * @throws ApiException If fail to read file content from response and write to disk + */ + public File downloadFileFromResponse(Response response) throws ApiException { + try { + File file = prepareDownloadFile(response); +{{^supportJava6}} + Files.copy(response.readEntity(InputStream.class), file.toPath(), StandardCopyOption.REPLACE_EXISTING); +{{/supportJava6}} +{{#supportJava6}} + // Java6 falls back to commons.io for file copying + FileUtils.copyToFile(response.readEntity(InputStream.class), file); +{{/supportJava6}} + return file; + } catch (IOException e) { + throw new ApiException(e); + } + } + + public File prepareDownloadFile(Response response) throws IOException { + String filename = null; + String contentDisposition = (String) response.getHeaders().getFirst("Content-Disposition"); + if (contentDisposition != null && !"".equals(contentDisposition)) { + // Get filename from the Content-Disposition header. + Pattern pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?"); + Matcher matcher = pattern.matcher(contentDisposition); + if (matcher.find()) + filename = matcher.group(1); + } + + String prefix; + String suffix = null; + if (filename == null) { + prefix = "download-"; + suffix = ""; + } else { + int pos = filename.lastIndexOf('.'); + if (pos == -1) { + prefix = filename + "-"; + } else { + prefix = filename.substring(0, pos) + "-"; + suffix = filename.substring(pos); + } + // File.createTempFile requires the prefix to be at least three characters long + if (prefix.length() < 3) + prefix = "download-"; + } + + if (tempFolderPath == null) + return File.createTempFile(prefix, suffix); + else + return File.createTempFile(prefix, suffix, new File(tempFolderPath)); + } + + /** + * Invoke API by sending HTTP request with the given options. + * + * @param Type + * @param path The sub-path of the HTTP URL + * @param method The request method, one of "GET", "POST", "PUT", "HEAD" and "DELETE" + * @param queryParams The query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param formParams The form parameters + * @param accept The request's Accept header + * @param contentType The request's Content-Type header + * @param authNames The authentications to apply + * @param returnType The return type into which to deserialize the response + * @return The response body in type of string + * @throws ApiException API exception + */ + public ApiResponse invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { + updateParamsForAuth(authNames, queryParams, headerParams); + + // Not using `.target(this.basePath).path(path)` below, + // to support (constant) query string in `path`, e.g. "/posts?draft=1" + WebTarget target = httpClient.target(this.basePath + path); + + if (queryParams != null) { + for (Pair queryParam : queryParams) { + if (queryParam.getValue() != null) { + target = target.queryParam(queryParam.getName(), queryParam.getValue()); + } + } + } + + Invocation.Builder invocationBuilder = target.request().accept(accept); + + for (Entry entry : headerParams.entrySet()) { + String value = entry.getValue(); + if (value != null) { + invocationBuilder = invocationBuilder.header(entry.getKey(), value); + } + } + + for (Entry entry : defaultHeaderMap.entrySet()) { + String key = entry.getKey(); + if (!headerParams.containsKey(key)) { + String value = entry.getValue(); + if (value != null) { + invocationBuilder = invocationBuilder.header(key, value); + } + } + } + + Entity entity = serialize(body, formParams, contentType); + + Response response = null; + + try { + if ("GET".equals(method)) { + response = invocationBuilder.get(); + } else if ("POST".equals(method)) { + response = invocationBuilder.post(entity); + } else if ("PUT".equals(method)) { + response = invocationBuilder.put(entity); + } else if ("DELETE".equals(method)) { + response = invocationBuilder.delete(); + } else if ("PATCH".equals(method)) { + response = invocationBuilder.method("PATCH", entity); + } else if ("HEAD".equals(method)) { + response = invocationBuilder.head(); + } else { + throw new ApiException(500, "unknown method type " + method); + } + + int statusCode = response.getStatusInfo().getStatusCode(); + Map> responseHeaders = buildResponseHeaders(response); + + if (response.getStatus() == Status.NO_CONTENT.getStatusCode()) { + return new ApiResponse<>(statusCode, responseHeaders); + } else if (response.getStatusInfo().getFamily() == Status.Family.SUCCESSFUL) { + if (returnType == null) + return new ApiResponse<>(statusCode, responseHeaders); + else + return new ApiResponse<>(statusCode, responseHeaders, deserialize(response, returnType)); + } else { + String message = "error"; + String respBody = null; + if (response.hasEntity()) { + try { + respBody = String.valueOf(response.readEntity(String.class)); + message = respBody; + } catch (RuntimeException e) { + // e.printStackTrace(); + } + } + throw new ApiException( + response.getStatus(), + message, + buildResponseHeaders(response), + respBody); + } + } finally { + try { + response.close(); + } catch (Exception e) { + // it's not critical, since the response object is local in method invokeAPI; that's fine, just continue + } + } + } + + /** + * Build the Client used to make HTTP requests. + * @param debugging Debug setting + * @return Client + */ + protected Client buildHttpClient(boolean debugging) { + final ClientConfig clientConfig = new ClientConfig(); + clientConfig.register(MultiPartFeature.class); + clientConfig.register(json); + clientConfig.register(JacksonFeature.class); + clientConfig.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true); + if (debugging) { +{{^supportJava6}} + clientConfig.register(new LoggingFeature(java.util.logging.Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME), java.util.logging.Level.INFO, LoggingFeature.Verbosity.PAYLOAD_ANY, 1024*50 /* Log payloads up to 50K */)); + clientConfig.property(LoggingFeature.LOGGING_FEATURE_VERBOSITY, LoggingFeature.Verbosity.PAYLOAD_ANY); + // Set logger to ALL + java.util.logging.Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME).setLevel(java.util.logging.Level.ALL); +{{/supportJava6}} +{{#supportJava6}} + clientConfig.register(new LoggingFilter(java.util.logging.Logger.getLogger(LoggingFilter.class.getName()), true)); +{{/supportJava6}} + } + performAdditionalClientConfiguration(clientConfig); + return ClientBuilder.newClient(clientConfig); + } + + protected void performAdditionalClientConfiguration(ClientConfig clientConfig) { + // No-op extension point + } + + protected Map> buildResponseHeaders(Response response) { + Map> responseHeaders = new HashMap>(); + for (Entry> entry: response.getHeaders().entrySet()) { + List values = entry.getValue(); + List headers = new ArrayList(); + for (Object o : values) { + headers.add(String.valueOf(o)); + } + responseHeaders.put(entry.getKey(), headers); + } + return responseHeaders; + } + + /** + * Update query and header parameters based on authentication settings. + * + * @param authNames The authentications to apply + */ + protected void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams) { + for (String authName : authNames) { + Authentication auth = authentications.get(authName); + if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + auth.applyToParams(queryParams, headerParams); + } + } +} diff --git a/libraries/jersey2/ApiResponse.mustache b/libraries/jersey2/ApiResponse.mustache new file mode 100644 index 00000000000..2f01685a0af --- /dev/null +++ b/libraries/jersey2/ApiResponse.mustache @@ -0,0 +1,48 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import java.util.List; +import java.util.Map; + +/** + * API response returned by API call. + * + * @param The type of data that is deserialized from response body + */ +public class ApiResponse { + private final int statusCode; + private final Map> headers; + private final T data; + + /** + * @param statusCode The status code of HTTP response + * @param headers The headers of HTTP response + */ + public ApiResponse(int statusCode, Map> headers) { + this(statusCode, headers, null); + } + + /** + * @param statusCode The status code of HTTP response + * @param headers The headers of HTTP response + * @param data The object deserialized from response bod + */ + public ApiResponse(int statusCode, Map> headers, T data) { + this.statusCode = statusCode; + this.headers = headers; + this.data = data; + } + + public int getStatusCode() { + return statusCode; + } + + public Map> getHeaders() { + return headers; + } + + public T getData() { + return data; + } +} diff --git a/libraries/jersey2/JSON.mustache b/libraries/jersey2/JSON.mustache new file mode 100644 index 00000000000..911391a6baf --- /dev/null +++ b/libraries/jersey2/JSON.mustache @@ -0,0 +1,62 @@ +package {{invokerPackage}}; + +{{#threetenbp}} +import org.threeten.bp.*; +{{/threetenbp}} +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.*; +{{#java8}} +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{/java8}} +{{#joda}} +import com.fasterxml.jackson.datatype.joda.JodaModule; +{{/joda}} +{{#threetenbp}} +import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; +{{/threetenbp}} + +import java.text.DateFormat; + +import javax.ws.rs.ext.ContextResolver; + +{{>generatedAnnotation}} +public class JSON implements ContextResolver { + private ObjectMapper mapper; + + public JSON() { + mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.setDateFormat(new RFC3339DateFormat()); + {{#java8}} + mapper.registerModule(new JavaTimeModule()); + {{/java8}} + {{#joda}} + mapper.registerModule(new JodaModule()); + {{/joda}} + {{#threetenbp}} + ThreeTenModule module = new ThreeTenModule(); + module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); + module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); + module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); + mapper.registerModule(module); + {{/threetenbp}} + } + + /** + * Set the date format for JSON (de)serialization with Date properties. + * @param dateFormat Date format + */ + public void setDateFormat(DateFormat dateFormat) { + mapper.setDateFormat(dateFormat); + } + + @Override + public ObjectMapper getContext(Class type) { + return mapper; + } +} diff --git a/libraries/jersey2/api.mustache b/libraries/jersey2/api.mustache new file mode 100644 index 00000000000..fed034609c8 --- /dev/null +++ b/libraries/jersey2/api.mustache @@ -0,0 +1,143 @@ +package {{package}}; + +import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.ApiResponse; +import {{invokerPackage}}.Configuration; +import {{invokerPackage}}.Pair; + +import javax.ws.rs.core.GenericType; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}} { + private ApiClient {{localVariablePrefix}}apiClient; + + public {{classname}}() { + this(Configuration.getDefaultApiClient()); + } + + public {{classname}}(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + public ApiClient getApiClient() { + return {{localVariablePrefix}}apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + {{#operation}} + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} + {{#returnType}} + * @return {{returnType}} + {{/returnType}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + {{#returnType}} + return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}).getData(); + {{/returnType}}{{^returnType}} + {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{/returnType}} + } + + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} + {{#returnType}} + * @return ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + {{/returnType}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + Object {{localVariablePrefix}}localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + } + {{/required}}{{/allParams}} + // create path and map variables + String {{localVariablePrefix}}localVarPath = "{{{path}}}"{{#pathParams}} + .replaceAll("\\{" + "{{baseName}}" + "\\}", {{localVariablePrefix}}apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; + + // query params + {{javaUtilPrefix}}List {{localVariablePrefix}}localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarFormParams = new {{javaUtilPrefix}}HashMap(); + + {{#queryParams}} + {{localVariablePrefix}}localVarQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); + {{/queryParams}} + + {{#headerParams}}if ({{paramName}} != null) + {{localVariablePrefix}}localVarHeaderParams.put("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}})); + {{/headerParams}} + + {{#formParams}}if ({{paramName}} != null) + {{localVariablePrefix}}localVarFormParams.put("{{baseName}}", {{paramName}}); + {{/formParams}} + + final String[] {{localVariablePrefix}}localVarAccepts = { + {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} + }; + final String {{localVariablePrefix}}localVarAccept = {{localVariablePrefix}}apiClient.selectHeaderAccept({{localVariablePrefix}}localVarAccepts); + + final String[] {{localVariablePrefix}}localVarContentTypes = { + {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} + }; + final String {{localVariablePrefix}}localVarContentType = {{localVariablePrefix}}apiClient.selectHeaderContentType({{localVariablePrefix}}localVarContentTypes); + + String[] {{localVariablePrefix}}localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + + {{#returnType}} + GenericType<{{{returnType}}}> {{localVariablePrefix}}localVarReturnType = new GenericType<{{{returnType}}}>() {}; + return {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarPostBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccept, {{localVariablePrefix}}localVarContentType, {{localVariablePrefix}}localVarAuthNames, {{localVariablePrefix}}localVarReturnType); + {{/returnType}}{{^returnType}} + return {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarPostBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccept, {{localVariablePrefix}}localVarContentType, {{localVariablePrefix}}localVarAuthNames, null); + {{/returnType}} + } + {{/operation}} +} +{{/operations}} diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache new file mode 100644 index 00000000000..19d8c2c6d84 --- /dev/null +++ b/libraries/jersey2/build.gradle.mustache @@ -0,0 +1,146 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + } + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + {{#java8}} + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + {{/java8}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + swagger_annotations_version = "1.5.17" + jackson_version = "2.8.9" + {{#supportJava6}} + jersey_version = "2.6" + commons_io_version=2.5 + commons_lang3_version=3.6 + {{/supportJava6}} + {{^supportJava6}} + jersey_version = "2.25.1" + {{/supportJava6}} + junit_version = "4.12" +} + +dependencies { + compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "org.glassfish.jersey.core:jersey-client:$jersey_version" + compile "org.glassfish.jersey.media:jersey-media-multipart:$jersey_version" + compile "org.glassfish.jersey.media:jersey-media-json-jackson:$jersey_version" + compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + {{#joda}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version", + {{/joda}} + {{#java8}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version", + {{/java8}} + {{#supportJava6}} + compile "commons-io:commons-io:$commons_io_version" + compile "org.apache.commons:commons-lang3:$commons_lang3_version" + {{/supportJava6}} + {{#threetenbp}} + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_version", + {{/threetenbp}} + {{^java8}} + compile "com.brsanthu:migbase64:2.2" + {{/java8}} + testCompile "junit:junit:$junit_version" +} diff --git a/libraries/jersey2/build.sbt.mustache b/libraries/jersey2/build.sbt.mustache new file mode 100644 index 00000000000..544297d481d --- /dev/null +++ b/libraries/jersey2/build.sbt.mustache @@ -0,0 +1,38 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "io.swagger" % "swagger-annotations" % "1.5.17", + "org.glassfish.jersey.core" % "jersey-client" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, + "org.glassfish.jersey.media" % "jersey-media-multipart" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, + "org.glassfish.jersey.media" % "jersey-media-json-jackson" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, + "com.fasterxml.jackson.core" % "jackson-core" % "{{^threetenbp}}2.8.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "{{^threetenbp}}2.8.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "{{^threetenbp}}2.8.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" % "compile", + {{#joda}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.8.9" % "compile", + {{/joda}} + {{#java8}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.8.9" % "compile", + {{/java8}} + {{#threetenbp}} + "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4" % "compile", + {{/threetenbp}} + {{^java8}} + "com.brsanthu" % "migbase64" % "2.2", + {{/java8}} + {{#supportJava6}} + "org.apache.commons" % "commons-lang3" % "3.6", + "commons-io" % "commons-io" % "2.5", + {{/supportJava6}} + "junit" % "junit" % "4.12" % "test", + "com.novocode" % "junit-interface" % "0.10" % "test" + ) + ) diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache new file mode 100644 index 00000000000..2dff93306a0 --- /dev/null +++ b/libraries/jersey2/pom.mustache @@ -0,0 +1,330 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{artifactUrl}} + {{artifactDescription}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.6 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + {{#java8}} + + 1.8 + 1.8 + {{/java8}} + {{^java8}} + + 1.7 + 1.7 + {{/java8}} + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-core-version} + + + + + org.glassfish.jersey.core + jersey-client + ${jersey-version} + + + org.glassfish.jersey.media + jersey-media-multipart + ${jersey-version} + + + org.glassfish.jersey.media + jersey-media-json-jackson + ${jersey-version} + + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-version} + + {{#withXml}} + + + + org.glassfish.jersey.media + jersey-media-jaxb + ${jersey-version} + + + {{/withXml}} + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + {{/joda}} + {{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{/java8}} + {{#threetenbp}} + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${jackson-version} + + {{/threetenbp}} + {{^java8}} + + + com.brsanthu + migbase64 + 2.2 + + {{/java8}} + {{#supportJava6}} + + org.apache.commons + commons-lang3 + ${commons_lang3_version} + + + commons-io + commons-io + ${commons_io_version} + + {{/supportJava6}} + {{#useBeanValidation}} + + + javax.validation + validation-api + 1.1.0.Final + provided + + {{/useBeanValidation}} + + + junit + junit + ${junit-version} + test + + + + UTF-8 + 1.5.18 + {{^supportJava6}} + 2.25.1 + {{/supportJava6}} + {{#supportJava6}} + 2.6 + 2.5 + 3.6 + {{/supportJava6}} + {{^threetenbp}}2.7.5{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} + 1.0.0 + 4.12 + + diff --git a/libraries/okhttp-gson/ApiCallback.mustache b/libraries/okhttp-gson/ApiCallback.mustache new file mode 100644 index 00000000000..4cc99a76ec3 --- /dev/null +++ b/libraries/okhttp-gson/ApiCallback.mustache @@ -0,0 +1,51 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import java.io.IOException; + +import java.util.Map; +import java.util.List; + +/** + * Callback for asynchronous API call. + * + * @param The return type + */ +public interface ApiCallback { + /** + * This is called when the API call fails. + * + * @param e The exception causing the failure + * @param statusCode Status code of the response if available, otherwise it would be 0 + * @param responseHeaders Headers of the response if available, otherwise it would be null + */ + void onFailure(ApiException e, int statusCode, Map> responseHeaders); + + /** + * This is called when the API call succeeded. + * + * @param result The result deserialized from response + * @param statusCode Status code of the response + * @param responseHeaders Headers of the response + */ + void onSuccess(T result, int statusCode, Map> responseHeaders); + + /** + * This is called when the API upload processing. + * + * @param bytesWritten bytes Written + * @param contentLength content length of request body + * @param done write end + */ + void onUploadProgress(long bytesWritten, long contentLength, boolean done); + + /** + * This is called when the API downlond processing. + * + * @param bytesRead bytes Read + * @param contentLength content lenngth of the response + * @param done Read end + */ + void onDownloadProgress(long bytesRead, long contentLength, boolean done); +} diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache new file mode 100644 index 00000000000..0ae00335726 --- /dev/null +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -0,0 +1,1227 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import com.squareup.okhttp.*; +import com.squareup.okhttp.internal.http.HttpMethod; +import com.squareup.okhttp.logging.HttpLoggingInterceptor; +import com.squareup.okhttp.logging.HttpLoggingInterceptor.Level; +import okio.BufferedSink; +import okio.Okio; +{{#joda}} +import org.joda.time.DateTime; +import org.joda.time.LocalDate; +import org.joda.time.format.DateTimeFormatter; +{{/joda}} +{{#threetenbp}} +import org.threeten.bp.LocalDate; +import org.threeten.bp.OffsetDateTime; +import org.threeten.bp.format.DateTimeFormatter; +{{/threetenbp}} + +import javax.net.ssl.*; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Type; +import java.net.URLConnection; +import java.net.URLEncoder; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.SecureRandom; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.text.DateFormat; +{{#java8}} +import java.time.LocalDate; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +{{/java8}} +import java.util.*; +import java.util.Map.Entry; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import {{invokerPackage}}.auth.Authentication; +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.OAuth; + +public class ApiClient { + + private String basePath = "{{{basePath}}}"; + private boolean debugging = false; + private Map defaultHeaderMap = new HashMap(); + private String tempFolderPath = null; + + private Map authentications; + + private DateFormat dateFormat; + private DateFormat datetimeFormat; + private boolean lenientDatetimeFormat; + private int dateLength; + + private InputStream sslCaCert; + private boolean verifyingSsl; + private KeyManager[] keyManagers; + + private OkHttpClient httpClient; + private JSON json; + + private HttpLoggingInterceptor loggingInterceptor; + + /* + * Constructor for ApiClient + */ + public ApiClient() { + httpClient = new OkHttpClient(); + + {{#useGzipFeature}} + // Enable gzip request compression + httpClient.interceptors().add(new GzipRequestInterceptor()); + {{/useGzipFeature}} + + verifyingSsl = true; + + json = new JSON(); + + // Set default User-Agent. + setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}Swagger-Codegen/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap();{{#authMethods}}{{#isBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + } + + /** + * Get base path + * + * @return Baes path + */ + public String getBasePath() { + return basePath; + } + + /** + * Set base path + * + * @param basePath Base path of the URL (e.g {{{basePath}}} + * @return An instance of OkHttpClient + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Get HTTP client + * + * @return An instance of OkHttpClient + */ + public OkHttpClient getHttpClient() { + return httpClient; + } + + /** + * Set HTTP client + * + * @param httpClient An instance of OkHttpClient + * @return Api Client + */ + public ApiClient setHttpClient(OkHttpClient httpClient) { + this.httpClient = httpClient; + return this; + } + + /** + * Get JSON + * + * @return JSON object + */ + public JSON getJSON() { + return json; + } + + /** + * Set JSON + * + * @param json JSON object + * @return Api client + */ + public ApiClient setJSON(JSON json) { + this.json = json; + return this; + } + + /** + * True if isVerifyingSsl flag is on + * + * @return True if isVerifySsl flag is on + */ + public boolean isVerifyingSsl() { + return verifyingSsl; + } + + /** + * Configure whether to verify certificate and hostname when making https requests. + * Default to true. + * NOTE: Do NOT set to false in production code, otherwise you would face multiple types of cryptographic attacks. + * + * @param verifyingSsl True to verify TLS/SSL connection + * @return ApiClient + */ + public ApiClient setVerifyingSsl(boolean verifyingSsl) { + this.verifyingSsl = verifyingSsl; + applySslSettings(); + return this; + } + + /** + * Get SSL CA cert. + * + * @return Input stream to the SSL CA cert + */ + public InputStream getSslCaCert() { + return sslCaCert; + } + + /** + * Configure the CA certificate to be trusted when making https requests. + * Use null to reset to default. + * + * @param sslCaCert input stream for SSL CA cert + * @return ApiClient + */ + public ApiClient setSslCaCert(InputStream sslCaCert) { + this.sslCaCert = sslCaCert; + applySslSettings(); + return this; + } + + public KeyManager[] getKeyManagers() { + return keyManagers; + } + + /** + * Configure client keys to use for authorization in an SSL session. + * Use null to reset to default. + * + * @param managers The KeyManagers to use + * @return ApiClient + */ + public ApiClient setKeyManagers(KeyManager[] managers) { + this.keyManagers = managers; + applySslSettings(); + return this; + } + + public DateFormat getDateFormat() { + return dateFormat; + } + + public ApiClient setDateFormat(DateFormat dateFormat) { + this.json.setDateFormat(dateFormat); + return this; + } + + public ApiClient setSqlDateFormat(DateFormat dateFormat) { + this.json.setSqlDateFormat(dateFormat); + return this; + } + + {{#joda}} + public ApiClient setDateTimeFormat(DateTimeFormatter dateFormat) { + this.json.setDateTimeFormat(dateFormat); + return this; + } + + public ApiClient setLocalDateFormat(DateTimeFormatter dateFormat) { + this.json.setLocalDateFormat(dateFormat); + return this; + } + + {{/joda}} + {{#jsr310}} + public ApiClient setOffsetDateTimeFormat(DateTimeFormatter dateFormat) { + this.json.setOffsetDateTimeFormat(dateFormat); + return this; + } + + public ApiClient setLocalDateFormat(DateTimeFormatter dateFormat) { + this.json.setLocalDateFormat(dateFormat); + return this; + } + + {{/jsr310}} + public ApiClient setLenientOnJson(boolean lenientOnJson) { + this.json.setLenientOnJson(lenientOnJson); + return this; + } + + /** + * Get authentications (key: authentication name, value: authentication). + * + * @return Map of authentication objects + */ + public Map getAuthentications() { + return authentications; + } + + /** + * Get authentication for the given name. + * + * @param authName The authentication name + * @return The authentication, null if not found + */ + public Authentication getAuthentication(String authName) { + return authentications.get(authName); + } + + /** + * Helper method to set username for the first HTTP basic authentication. + * + * @param username Username + */ + public void setUsername(String username) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setUsername(username); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set password for the first HTTP basic authentication. + * + * @param password Password + */ + public void setPassword(String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setPassword(password); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set API key value for the first API key authentication. + * + * @param apiKey API key + */ + public void setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + * + * @param apiKeyPrefix API key prefix + */ + public void setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set access token for the first OAuth2 authentication. + * + * @param accessToken Access token + */ + public void setAccessToken(String accessToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setAccessToken(accessToken); + return; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Set the User-Agent header's value (by adding to the default header map). + * + * @param userAgent HTTP request's user agent + * @return ApiClient + */ + public ApiClient setUserAgent(String userAgent) { + addDefaultHeader("User-Agent", userAgent); + return this; + } + + /** + * Add a default header. + * + * @param key The header's key + * @param value The header's value + * @return ApiClient + */ + public ApiClient addDefaultHeader(String key, String value) { + defaultHeaderMap.put(key, value); + return this; + } + + /** + * Check that whether debugging is enabled for this API client. + * + * @return True if debugging is enabled, false otherwise. + */ + public boolean isDebugging() { + return debugging; + } + + /** + * Enable/disable debugging for this API client. + * + * @param debugging To enable (true) or disable (false) debugging + * @return ApiClient + */ + public ApiClient setDebugging(boolean debugging) { + if (debugging != this.debugging) { + if (debugging) { + loggingInterceptor = new HttpLoggingInterceptor(); + loggingInterceptor.setLevel(Level.BODY); + httpClient.interceptors().add(loggingInterceptor); + } else { + httpClient.interceptors().remove(loggingInterceptor); + loggingInterceptor = null; + } + } + this.debugging = debugging; + return this; + } + + /** + * The path of temporary folder used to store downloaded files from endpoints + * with file response. The default value is null, i.e. using + * the system's default tempopary folder. + * + * @see createTempFile + * @return Temporary folder path + */ + public String getTempFolderPath() { + return tempFolderPath; + } + + /** + * Set the temporary folder path (for downloading files) + * + * @param tempFolderPath Temporary folder path + * @return ApiClient + */ + public ApiClient setTempFolderPath(String tempFolderPath) { + this.tempFolderPath = tempFolderPath; + return this; + } + + /** + * Get connection timeout (in milliseconds). + * + * @return Timeout in milliseconds + */ + public int getConnectTimeout() { + return httpClient.getConnectTimeout(); + } + + /** + * Sets the connect timeout (in milliseconds). + * A value of 0 means no timeout, otherwise values must be between 1 and + * {@link Integer#MAX_VALUE}. + * + * @param connectionTimeout connection timeout in milliseconds + * @return Api client + */ + public ApiClient setConnectTimeout(int connectionTimeout) { + httpClient.setConnectTimeout(connectionTimeout, TimeUnit.MILLISECONDS); + return this; + } + + /** + * Get read timeout (in milliseconds). + * + * @return Timeout in milliseconds + */ + public int getReadTimeout() { + return httpClient.getReadTimeout(); + } + + /** + * Sets the read timeout (in milliseconds). + * A value of 0 means no timeout, otherwise values must be between 1 and + * {@link Integer#MAX_VALUE}. + * + * @param readTimeout read timeout in milliseconds + * @return Api client + */ + public ApiClient setReadTimeout(int readTimeout) { + httpClient.setReadTimeout(readTimeout, TimeUnit.MILLISECONDS); + return this; + } + + /** + * Get write timeout (in milliseconds). + * + * @return Timeout in milliseconds + */ + public int getWriteTimeout() { + return httpClient.getWriteTimeout(); + } + + /** + * Sets the write timeout (in milliseconds). + * A value of 0 means no timeout, otherwise values must be between 1 and + * {@link Integer#MAX_VALUE}. + * + * @param writeTimeout connection timeout in milliseconds + * @return Api client + */ + public ApiClient setWriteTimeout(int writeTimeout) { + httpClient.setWriteTimeout(writeTimeout, TimeUnit.MILLISECONDS); + return this; + } + + /** + * Format the given parameter object into string. + * + * @param param Parameter + * @return String representation of the parameter + */ + public String parameterToString(Object param) { + if (param == null) { + return ""; + } else if (param instanceof Date {{#joda}}|| param instanceof DateTime || param instanceof LocalDate{{/joda}}{{#jsr310}}|| param instanceof OffsetDateTime || param instanceof LocalDate{{/jsr310}}) { + //Serialize to json string and remove the " enclosing characters + String jsonStr = json.serialize(param); + return jsonStr.substring(1, jsonStr.length() - 1); + } else if (param instanceof Collection) { + StringBuilder b = new StringBuilder(); + for (Object o : (Collection)param) { + if (b.length() > 0) { + b.append(","); + } + b.append(String.valueOf(o)); + } + return b.toString(); + } else { + return String.valueOf(param); + } + } + + /** + * Formats the specified query parameter to a list containing a single {@code Pair} object. + * + * Note that {@code value} must not be a collection. + * + * @param name The name of the parameter. + * @param value The value of the parameter. + * @return A list containing a single {@code Pair} object. + */ + public List parameterToPair(String name, Object value) { + List params = new ArrayList(); + + // preconditions + if (name == null || name.isEmpty() || value == null || value instanceof Collection) return params; + + params.add(new Pair(name, parameterToString(value))); + return params; + } + + /** + * Formats the specified collection query parameters to a list of {@code Pair} objects. + * + * Note that the values of each of the returned Pair objects are percent-encoded. + * + * @param collectionFormat The collection format of the parameter. + * @param name The name of the parameter. + * @param value The value of the parameter. + * @return A list of {@code Pair} objects. + */ + public List parameterToPairs(String collectionFormat, String name, Collection value) { + List params = new ArrayList(); + + // preconditions + if (name == null || name.isEmpty() || value == null || value.isEmpty()) { + return params; + } + + // create the params based on the collection format + if ("multi".equals(collectionFormat)) { + for (Object item : value) { + params.add(new Pair(name, escapeString(parameterToString(item)))); + } + return params; + } + + // collectionFormat is assumed to be "csv" by default + String delimiter = ","; + + // escape all delimiters except commas, which are URI reserved + // characters + if ("ssv".equals(collectionFormat)) { + delimiter = escapeString(" "); + } else if ("tsv".equals(collectionFormat)) { + delimiter = escapeString("\t"); + } else if ("pipes".equals(collectionFormat)) { + delimiter = escapeString("|"); + } + + StringBuilder sb = new StringBuilder() ; + for (Object item : value) { + sb.append(delimiter); + sb.append(escapeString(parameterToString(item))); + } + + params.add(new Pair(name, sb.substring(delimiter.length()))); + + return params; + } + + /** + * Sanitize filename by removing path. + * e.g. ../../sun.gif becomes sun.gif + * + * @param filename The filename to be sanitized + * @return The sanitized filename + */ + public String sanitizeFilename(String filename) { + return filename.replaceAll(".*[/\\\\]", ""); + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * application/vnd.company+json + * "* / *" is also default to JSON + * @param mime MIME (Multipurpose Internet Mail Extensions) + * @return True if the given MIME is JSON, false otherwise. + */ + public boolean isJsonMime(String mime) { + String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$"; + return mime != null && (mime.matches(jsonMime) || mime.equals("*/*")); + } + + /** + * Select the Accept header's value from the given accepts array: + * if JSON exists in the given array, use it; + * otherwise use all of them (joining into a string) + * + * @param accepts The accepts array to select from + * @return The Accept header to use. If the given array is empty, + * null will be returned (not to set the Accept header explicitly). + */ + public String selectHeaderAccept(String[] accepts) { + if (accepts.length == 0) { + return null; + } + for (String accept : accepts) { + if (isJsonMime(accept)) { + return accept; + } + } + return StringUtil.join(accepts, ","); + } + + /** + * Select the Content-Type header's value from the given array: + * if JSON exists in the given array, use it; + * otherwise use the first one of the array. + * + * @param contentTypes The Content-Type array to select from + * @return The Content-Type header to use. If the given array is empty, + * or matches "any", JSON will be used. + */ + public String selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0 || contentTypes[0].equals("*/*")) { + return "application/json"; + } + for (String contentType : contentTypes) { + if (isJsonMime(contentType)) { + return contentType; + } + } + return contentTypes[0]; + } + + /** + * Escape the given string to be used as URL query value. + * + * @param str String to be escaped + * @return Escaped string + */ + public String escapeString(String str) { + try { + return URLEncoder.encode(str, "utf8").replaceAll("\\+", "%20"); + } catch (UnsupportedEncodingException e) { + return str; + } + } + + /** + * Deserialize response body to Java object, according to the return type and + * the Content-Type response header. + * + * @param Type + * @param response HTTP response + * @param returnType The type of the Java object + * @return The deserialized Java object + * @throws ApiException If fail to deserialize response body, i.e. cannot read response body + * or the Content-Type of the response is not supported. + */ + @SuppressWarnings("unchecked") + public T deserialize(Response response, Type returnType) throws ApiException { + if (response == null || returnType == null) { + return null; + } + + if ("byte[]".equals(returnType.toString())) { + // Handle binary response (byte array). + try { + return (T) response.body().bytes(); + } catch (IOException e) { + throw new ApiException(e); + } + } else if (returnType.equals(File.class)) { + // Handle file downloading. + return (T) downloadFileFromResponse(response); + } + + String respBody; + try { + if (response.body() != null) + respBody = response.body().string(); + else + respBody = null; + } catch (IOException e) { + throw new ApiException(e); + } + + if (respBody == null || "".equals(respBody)) { + return null; + } + + String contentType = response.headers().get("Content-Type"); + if (contentType == null) { + // ensuring a default content type + contentType = "application/json"; + } + if (isJsonMime(contentType)) { + return json.deserialize(respBody, returnType); + } else if (returnType.equals(String.class)) { + // Expecting string, return the raw response body. + return (T) respBody; + } else { + throw new ApiException( + "Content type \"" + contentType + "\" is not supported for type: " + returnType, + response.code(), + response.headers().toMultimap(), + respBody); + } + } + + /** + * Serialize the given Java object into request body according to the object's + * class and the request Content-Type. + * + * @param obj The Java object + * @param contentType The request Content-Type + * @return The serialized request body + * @throws ApiException If fail to serialize the given object + */ + public RequestBody serialize(Object obj, String contentType) throws ApiException { + if (obj instanceof byte[]) { + // Binary (byte array) body parameter support. + return RequestBody.create(MediaType.parse(contentType), (byte[]) obj); + } else if (obj instanceof File) { + // File body parameter support. + return RequestBody.create(MediaType.parse(contentType), (File) obj); + } else if (isJsonMime(contentType)) { + String content; + if (obj != null) { + content = json.serialize(obj); + } else { + content = null; + } + return RequestBody.create(MediaType.parse(contentType), content); + } else { + throw new ApiException("Content type \"" + contentType + "\" is not supported"); + } + } + + /** + * Download file from the given response. + * + * @param response An instance of the Response object + * @throws ApiException If fail to read file content from response and write to disk + * @return Downloaded file + */ + public File downloadFileFromResponse(Response response) throws ApiException { + try { + File file = prepareDownloadFile(response); + BufferedSink sink = Okio.buffer(Okio.sink(file)); + sink.writeAll(response.body().source()); + sink.close(); + return file; + } catch (IOException e) { + throw new ApiException(e); + } + } + + /** + * Prepare file for download + * + * @param response An instance of the Response object + * @throws IOException If fail to prepare file for download + * @return Prepared file for the download + */ + public File prepareDownloadFile(Response response) throws IOException { + String filename = null; + String contentDisposition = response.header("Content-Disposition"); + if (contentDisposition != null && !"".equals(contentDisposition)) { + // Get filename from the Content-Disposition header. + Pattern pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?"); + Matcher matcher = pattern.matcher(contentDisposition); + if (matcher.find()) { + filename = sanitizeFilename(matcher.group(1)); + } + } + + String prefix = null; + String suffix = null; + if (filename == null) { + prefix = "download-"; + suffix = ""; + } else { + int pos = filename.lastIndexOf("."); + if (pos == -1) { + prefix = filename + "-"; + } else { + prefix = filename.substring(0, pos) + "-"; + suffix = filename.substring(pos); + } + // File.createTempFile requires the prefix to be at least three characters long + if (prefix.length() < 3) + prefix = "download-"; + } + + if (tempFolderPath == null) + return File.createTempFile(prefix, suffix); + else + return File.createTempFile(prefix, suffix, new File(tempFolderPath)); + } + + /** + * {@link #execute(Call, Type)} + * + * @param Type + * @param call An instance of the Call object + * @throws ApiException If fail to execute the call + * @return ApiResponse<T> + */ + public ApiResponse execute(Call call) throws ApiException { + return execute(call, null); + } + + /** + * Execute HTTP call and deserialize the HTTP response body into the given return type. + * + * @param returnType The return type used to deserialize HTTP response body + * @param The return type corresponding to (same with) returnType + * @param call Call + * @return ApiResponse object containing response status, headers and + * data, which is a Java object deserialized from response body and would be null + * when returnType is null. + * @throws ApiException If fail to execute the call + */ + public ApiResponse execute(Call call, Type returnType) throws ApiException { + try { + Response response = call.execute(); + T data = handleResponse(response, returnType); + return new ApiResponse(response.code(), response.headers().toMultimap(), data); + } catch (IOException e) { + throw new ApiException(e); + } + } + + /** + * {@link #executeAsync(Call, Type, ApiCallback)} + * + * @param Type + * @param call An instance of the Call object + * @param callback ApiCallback<T> + */ + public void executeAsync(Call call, ApiCallback callback) { + executeAsync(call, null, callback); + } + + /** + * Execute HTTP call asynchronously. + * + * @see #execute(Call, Type) + * @param Type + * @param call The callback to be executed when the API call finishes + * @param returnType Return type + * @param callback ApiCallback + */ + @SuppressWarnings("unchecked") + public void executeAsync(Call call, final Type returnType, final ApiCallback callback) { + call.enqueue(new Callback() { + @Override + public void onFailure(Request request, IOException e) { + callback.onFailure(new ApiException(e), 0, null); + } + + @Override + public void onResponse(Response response) throws IOException { + T result; + try { + result = (T) handleResponse(response, returnType); + } catch (ApiException e) { + callback.onFailure(e, response.code(), response.headers().toMultimap()); + return; + } + callback.onSuccess(result, response.code(), response.headers().toMultimap()); + } + }); + } + + /** + * Handle the given response, return the deserialized object when the response is successful. + * + * @param Type + * @param response Response + * @param returnType Return type + * @throws ApiException If the response has a unsuccessful status code or + * fail to deserialize the response body + * @return Type + */ + public T handleResponse(Response response, Type returnType) throws ApiException { + if (response.isSuccessful()) { + if (returnType == null || response.code() == 204) { + // returning null if the returnType is not defined, + // or the status code is 204 (No Content) + if (response.body() != null) { + try { + response.body().close(); + } catch (IOException e) { + throw new ApiException(response.message(), e, response.code(), response.headers().toMultimap()); + } + } + return null; + } else { + return deserialize(response, returnType); + } + } else { + String respBody = null; + if (response.body() != null) { + try { + respBody = response.body().string(); + } catch (IOException e) { + throw new ApiException(response.message(), e, response.code(), response.headers().toMultimap()); + } + } + throw new ApiException(response.message(), response.code(), response.headers().toMultimap(), respBody); + } + } + + /** + * Build HTTP call with the given options. + * + * @param path The sub-path of the HTTP URL + * @param method The request method, one of "GET", "HEAD", "OPTIONS", "POST", "PUT", "PATCH" and "DELETE" + * @param queryParams The query parameters + * @param collectionQueryParams The collection query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param formParams The form parameters + * @param authNames The authentications to apply + * @param progressRequestListener Progress request listener + * @return The HTTP call + * @throws ApiException If fail to serialize the request body object + */ + public Call buildCall(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map formParams, String[] authNames, ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException { + Request request = buildRequest(path, method, queryParams, collectionQueryParams, body, headerParams, formParams, authNames, progressRequestListener); + + return httpClient.newCall(request); + } + + /** + * Build an HTTP request with the given options. + * + * @param path The sub-path of the HTTP URL + * @param method The request method, one of "GET", "HEAD", "OPTIONS", "POST", "PUT", "PATCH" and "DELETE" + * @param queryParams The query parameters + * @param collectionQueryParams The collection query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param formParams The form parameters + * @param authNames The authentications to apply + * @param progressRequestListener Progress request listener + * @return The HTTP request + * @throws ApiException If fail to serialize the request body object + */ + public Request buildRequest(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map formParams, String[] authNames, ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException { + updateParamsForAuth(authNames, queryParams, headerParams); + + final String url = buildUrl(path, queryParams, collectionQueryParams); + final Request.Builder reqBuilder = new Request.Builder().url(url); + processHeaderParams(headerParams, reqBuilder); + + String contentType = (String) headerParams.get("Content-Type"); + // ensuring a default content type + if (contentType == null) { + contentType = "application/json"; + } + + RequestBody reqBody; + if (!HttpMethod.permitsRequestBody(method)) { + reqBody = null; + } else if ("application/x-www-form-urlencoded".equals(contentType)) { + reqBody = buildRequestBodyFormEncoding(formParams); + } else if ("multipart/form-data".equals(contentType)) { + reqBody = buildRequestBodyMultipart(formParams); + } else if (body == null) { + if ("DELETE".equals(method)) { + // allow calling DELETE without sending a request body + reqBody = null; + } else { + // use an empty request body (for POST, PUT and PATCH) + reqBody = RequestBody.create(MediaType.parse(contentType), ""); + } + } else { + reqBody = serialize(body, contentType); + } + + Request request = null; + + if(progressRequestListener != null && reqBody != null) { + ProgressRequestBody progressRequestBody = new ProgressRequestBody(reqBody, progressRequestListener); + request = reqBuilder.method(method, progressRequestBody).build(); + } else { + request = reqBuilder.method(method, reqBody).build(); + } + + return request; + } + + /** + * Build full URL by concatenating base path, the given sub path and query parameters. + * + * @param path The sub path + * @param queryParams The query parameters + * @param collectionQueryParams The collection query parameters + * @return The full URL + */ + public String buildUrl(String path, List queryParams, List collectionQueryParams) { + final StringBuilder url = new StringBuilder(); + url.append(basePath).append(path); + + if (queryParams != null && !queryParams.isEmpty()) { + // support (constant) query string in `path`, e.g. "/posts?draft=1" + String prefix = path.contains("?") ? "&" : "?"; + for (Pair param : queryParams) { + if (param.getValue() != null) { + if (prefix != null) { + url.append(prefix); + prefix = null; + } else { + url.append("&"); + } + String value = parameterToString(param.getValue()); + url.append(escapeString(param.getName())).append("=").append(escapeString(value)); + } + } + } + + if (collectionQueryParams != null && !collectionQueryParams.isEmpty()) { + String prefix = url.toString().contains("?") ? "&" : "?"; + for (Pair param : collectionQueryParams) { + if (param.getValue() != null) { + if (prefix != null) { + url.append(prefix); + prefix = null; + } else { + url.append("&"); + } + String value = parameterToString(param.getValue()); + // collection query parameter value already escaped as part of parameterToPairs + url.append(escapeString(param.getName())).append("=").append(value); + } + } + } + + return url.toString(); + } + + /** + * Set header parameters to the request builder, including default headers. + * + * @param headerParams Header parameters in the ofrm of Map + * @param reqBuilder Reqeust.Builder + */ + public void processHeaderParams(Map headerParams, Request.Builder reqBuilder) { + for (Entry param : headerParams.entrySet()) { + reqBuilder.header(param.getKey(), parameterToString(param.getValue())); + } + for (Entry header : defaultHeaderMap.entrySet()) { + if (!headerParams.containsKey(header.getKey())) { + reqBuilder.header(header.getKey(), parameterToString(header.getValue())); + } + } + } + + /** + * Update query and header parameters based on authentication settings. + * + * @param authNames The authentications to apply + * @param queryParams List of query parameters + * @param headerParams Map of header parameters + */ + public void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams) { + for (String authName : authNames) { + Authentication auth = authentications.get(authName); + if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + auth.applyToParams(queryParams, headerParams); + } + } + + /** + * Build a form-encoding request body with the given form parameters. + * + * @param formParams Form parameters in the form of Map + * @return RequestBody + */ + public RequestBody buildRequestBodyFormEncoding(Map formParams) { + FormEncodingBuilder formBuilder = new FormEncodingBuilder(); + for (Entry param : formParams.entrySet()) { + formBuilder.add(param.getKey(), parameterToString(param.getValue())); + } + return formBuilder.build(); + } + + /** + * Build a multipart (file uploading) request body with the given form parameters, + * which could contain text fields and file fields. + * + * @param formParams Form parameters in the form of Map + * @return RequestBody + */ + public RequestBody buildRequestBodyMultipart(Map formParams) { + MultipartBuilder mpBuilder = new MultipartBuilder().type(MultipartBuilder.FORM); + for (Entry param : formParams.entrySet()) { + if (param.getValue() instanceof File) { + File file = (File) param.getValue(); + Headers partHeaders = Headers.of("Content-Disposition", "form-data; name=\"" + param.getKey() + "\"; filename=\"" + file.getName() + "\""); + MediaType mediaType = MediaType.parse(guessContentTypeFromFile(file)); + mpBuilder.addPart(partHeaders, RequestBody.create(mediaType, file)); + } else { + Headers partHeaders = Headers.of("Content-Disposition", "form-data; name=\"" + param.getKey() + "\""); + mpBuilder.addPart(partHeaders, RequestBody.create(null, parameterToString(param.getValue()))); + } + } + return mpBuilder.build(); + } + + /** + * Guess Content-Type header from the given file (defaults to "application/octet-stream"). + * + * @param file The given file + * @return The guessed Content-Type + */ + public String guessContentTypeFromFile(File file) { + String contentType = URLConnection.guessContentTypeFromName(file.getName()); + if (contentType == null) { + return "application/octet-stream"; + } else { + return contentType; + } + } + + /** + * Apply SSL related settings to httpClient according to the current values of + * verifyingSsl and sslCaCert. + */ + private void applySslSettings() { + try { + TrustManager[] trustManagers = null; + HostnameVerifier hostnameVerifier = null; + if (!verifyingSsl) { + TrustManager trustAll = new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {} + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {} + @Override + public X509Certificate[] getAcceptedIssuers() { return null; } + }; + SSLContext sslContext = SSLContext.getInstance("TLS"); + trustManagers = new TrustManager[]{ trustAll }; + hostnameVerifier = new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { return true; } + }; + } else if (sslCaCert != null) { + char[] password = null; // Any password will work. + CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); + Collection certificates = certificateFactory.generateCertificates(sslCaCert); + if (certificates.isEmpty()) { + throw new IllegalArgumentException("expected non-empty set of trusted certificates"); + } + KeyStore caKeyStore = newEmptyKeyStore(password); + int index = 0; + for (Certificate certificate : certificates) { + String certificateAlias = "ca" + Integer.toString(index++); + caKeyStore.setCertificateEntry(certificateAlias, certificate); + } + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + trustManagerFactory.init(caKeyStore); + trustManagers = trustManagerFactory.getTrustManagers(); + } + + if (keyManagers != null || trustManagers != null) { + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(keyManagers, trustManagers, new SecureRandom()); + httpClient.setSslSocketFactory(sslContext.getSocketFactory()); + } else { + httpClient.setSslSocketFactory(null); + } + httpClient.setHostnameVerifier(hostnameVerifier); + } catch (GeneralSecurityException e) { + throw new RuntimeException(e); + } + } + + private KeyStore newEmptyKeyStore(char[] password) throws GeneralSecurityException { + try { + KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + keyStore.load(null, password); + return keyStore; + } catch (IOException e) { + throw new AssertionError(e); + } + } +} diff --git a/libraries/okhttp-gson/ApiResponse.mustache b/libraries/okhttp-gson/ApiResponse.mustache new file mode 100644 index 00000000000..3909393697c --- /dev/null +++ b/libraries/okhttp-gson/ApiResponse.mustache @@ -0,0 +1,48 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import java.util.List; +import java.util.Map; + +/** + * API response returned by API call. + * + * @param The type of data that is deserialized from response body + */ +public class ApiResponse { + final private int statusCode; + final private Map> headers; + final private T data; + + /** + * @param statusCode The status code of HTTP response + * @param headers The headers of HTTP response + */ + public ApiResponse(int statusCode, Map> headers) { + this(statusCode, headers, null); + } + + /** + * @param statusCode The status code of HTTP response + * @param headers The headers of HTTP response + * @param data The object deserialized from response bod + */ + public ApiResponse(int statusCode, Map> headers, T data) { + this.statusCode = statusCode; + this.headers = headers; + this.data = data; + } + + public int getStatusCode() { + return statusCode; + } + + public Map> getHeaders() { + return headers; + } + + public T getData() { + return data; + } +} diff --git a/libraries/okhttp-gson/GzipRequestInterceptor.mustache b/libraries/okhttp-gson/GzipRequestInterceptor.mustache new file mode 100644 index 00000000000..23224cf5d5b --- /dev/null +++ b/libraries/okhttp-gson/GzipRequestInterceptor.mustache @@ -0,0 +1,70 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import com.squareup.okhttp.*; +import okio.Buffer; +import okio.BufferedSink; +import okio.GzipSink; +import okio.Okio; + +import java.io.IOException; + +/** + * Encodes request bodies using gzip. + * + * Taken from https://github.com/square/okhttp/issues/350 + */ +class GzipRequestInterceptor implements Interceptor { + @Override public Response intercept(Chain chain) throws IOException { + Request originalRequest = chain.request(); + if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) { + return chain.proceed(originalRequest); + } + + Request compressedRequest = originalRequest.newBuilder() + .header("Content-Encoding", "gzip") + .method(originalRequest.method(), forceContentLength(gzip(originalRequest.body()))) + .build(); + return chain.proceed(compressedRequest); + } + + private RequestBody forceContentLength(final RequestBody requestBody) throws IOException { + final Buffer buffer = new Buffer(); + requestBody.writeTo(buffer); + return new RequestBody() { + @Override + public MediaType contentType() { + return requestBody.contentType(); + } + + @Override + public long contentLength() { + return buffer.size(); + } + + @Override + public void writeTo(BufferedSink sink) throws IOException { + sink.write(buffer.snapshot()); + } + }; + } + + private RequestBody gzip(final RequestBody body) { + return new RequestBody() { + @Override public MediaType contentType() { + return body.contentType(); + } + + @Override public long contentLength() { + return -1; // We don't know the compressed length in advance! + } + + @Override public void writeTo(BufferedSink sink) throws IOException { + BufferedSink gzipSink = Okio.buffer(new GzipSink(sink)); + body.writeTo(gzipSink); + gzipSink.close(); + } + }; + } +} \ No newline at end of file diff --git a/libraries/okhttp-gson/ProgressRequestBody.mustache b/libraries/okhttp-gson/ProgressRequestBody.mustache new file mode 100644 index 00000000000..0f15c1f415d --- /dev/null +++ b/libraries/okhttp-gson/ProgressRequestBody.mustache @@ -0,0 +1,66 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import com.squareup.okhttp.MediaType; +import com.squareup.okhttp.RequestBody; + +import java.io.IOException; + +import okio.Buffer; +import okio.BufferedSink; +import okio.ForwardingSink; +import okio.Okio; +import okio.Sink; + +public class ProgressRequestBody extends RequestBody { + + public interface ProgressRequestListener { + void onRequestProgress(long bytesWritten, long contentLength, boolean done); + } + + private final RequestBody requestBody; + + private final ProgressRequestListener progressListener; + + public ProgressRequestBody(RequestBody requestBody, ProgressRequestListener progressListener) { + this.requestBody = requestBody; + this.progressListener = progressListener; + } + + @Override + public MediaType contentType() { + return requestBody.contentType(); + } + + @Override + public long contentLength() throws IOException { + return requestBody.contentLength(); + } + + @Override + public void writeTo(BufferedSink sink) throws IOException { + BufferedSink bufferedSink = Okio.buffer(sink(sink)); + requestBody.writeTo(bufferedSink); + bufferedSink.flush(); + } + + private Sink sink(Sink sink) { + return new ForwardingSink(sink) { + + long bytesWritten = 0L; + long contentLength = 0L; + + @Override + public void write(Buffer source, long byteCount) throws IOException { + super.write(source, byteCount); + if (contentLength == 0) { + contentLength = contentLength(); + } + + bytesWritten += byteCount; + progressListener.onRequestProgress(bytesWritten, contentLength, bytesWritten == contentLength); + } + }; + } +} diff --git a/libraries/okhttp-gson/ProgressResponseBody.mustache b/libraries/okhttp-gson/ProgressResponseBody.mustache new file mode 100644 index 00000000000..3f53133697c --- /dev/null +++ b/libraries/okhttp-gson/ProgressResponseBody.mustache @@ -0,0 +1,65 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import com.squareup.okhttp.MediaType; +import com.squareup.okhttp.ResponseBody; + +import java.io.IOException; + +import okio.Buffer; +import okio.BufferedSource; +import okio.ForwardingSource; +import okio.Okio; +import okio.Source; + +public class ProgressResponseBody extends ResponseBody { + + public interface ProgressListener { + void update(long bytesRead, long contentLength, boolean done); + } + + private final ResponseBody responseBody; + private final ProgressListener progressListener; + private BufferedSource bufferedSource; + + public ProgressResponseBody(ResponseBody responseBody, ProgressListener progressListener) { + this.responseBody = responseBody; + this.progressListener = progressListener; + } + + @Override + public MediaType contentType() { + return responseBody.contentType(); + } + + @Override + public long contentLength() throws IOException { + return responseBody.contentLength(); + } + + @Override + public BufferedSource source() throws IOException { + if (bufferedSource == null) { + bufferedSource = Okio.buffer(source(responseBody.source())); + } + return bufferedSource; + } + + private Source source(Source source) { + return new ForwardingSource(source) { + long totalBytesRead = 0L; + + @Override + public long read(Buffer sink, long byteCount) throws IOException { + long bytesRead = super.read(sink, byteCount); + // read() returns the number of bytes read, or -1 if this source is exhausted. + totalBytesRead += bytesRead != -1 ? bytesRead : 0; + progressListener.update(totalBytesRead, responseBody.contentLength(), bytesRead == -1); + return bytesRead; + } + }; + } +} + + diff --git a/libraries/okhttp-gson/api.mustache b/libraries/okhttp-gson/api.mustache new file mode 100644 index 00000000000..ffc68bc7b5a --- /dev/null +++ b/libraries/okhttp-gson/api.mustache @@ -0,0 +1,268 @@ +{{>licenseInfo}} + +package {{package}}; + +import {{invokerPackage}}.ApiCallback; +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.ApiResponse; +import {{invokerPackage}}.Configuration; +import {{invokerPackage}}.Pair; +import {{invokerPackage}}.ProgressRequestBody; +import {{invokerPackage}}.ProgressResponseBody; +{{#performBeanValidation}} +import {{invokerPackage}}.BeanValidationException; +{{/performBeanValidation}} + +import com.google.gson.reflect.TypeToken; + +import java.io.IOException; + +{{#useBeanValidation}} +import javax.validation.constraints.*; +{{/useBeanValidation}} +{{#performBeanValidation}} +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.ValidatorFactory; +import javax.validation.executable.ExecutableValidator; +import java.util.Set; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +{{/performBeanValidation}} + +{{#imports}}import {{import}}; +{{/imports}} + +import java.lang.reflect.Type; +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +{{#operations}} +public class {{classname}} { + private ApiClient {{localVariablePrefix}}apiClient; + + public {{classname}}() { + this(Configuration.getDefaultApiClient()); + } + + public {{classname}}(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + public ApiClient getApiClient() { + return {{localVariablePrefix}}apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + {{#operation}} + /** + * Build call for {{operationId}}{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + * @param progressListener Progress listener + * @param progressRequestListener Progress request listener + * @return Call to execute + * @throws ApiException If fail to serialize the request body object + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public com.squareup.okhttp.Call {{operationId}}Call({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ProgressResponseBody.ProgressListener progressListener, final ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException { + Object {{localVariablePrefix}}localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + + // create path and map variables + String {{localVariablePrefix}}localVarPath = "{{{path}}}"{{#pathParams}} + .replaceAll("\\{" + "{{baseName}}" + "\\}", {{localVariablePrefix}}apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; + + {{javaUtilPrefix}}List {{localVariablePrefix}}localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}List {{localVariablePrefix}}localVarCollectionQueryParams = new {{javaUtilPrefix}}ArrayList();{{#queryParams}} + if ({{paramName}} != null) + {{localVariablePrefix}}{{#collectionFormat}}localVarCollectionQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPairs("{{{collectionFormat}}}", {{/collectionFormat}}{{^collectionFormat}}localVarQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPair({{/collectionFormat}}"{{baseName}}", {{paramName}}));{{/queryParams}} + + {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarHeaderParams = new {{javaUtilPrefix}}HashMap();{{#headerParams}} + if ({{paramName}} != null) + {{localVariablePrefix}}localVarHeaderParams.put("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}}));{{/headerParams}} + + {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarFormParams = new {{javaUtilPrefix}}HashMap();{{#formParams}} + if ({{paramName}} != null) + {{localVariablePrefix}}localVarFormParams.put("{{baseName}}", {{paramName}});{{/formParams}} + + final String[] {{localVariablePrefix}}localVarAccepts = { + {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} + }; + final String {{localVariablePrefix}}localVarAccept = {{localVariablePrefix}}apiClient.selectHeaderAccept({{localVariablePrefix}}localVarAccepts); + if ({{localVariablePrefix}}localVarAccept != null) {{localVariablePrefix}}localVarHeaderParams.put("Accept", {{localVariablePrefix}}localVarAccept); + + final String[] {{localVariablePrefix}}localVarContentTypes = { + {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} + }; + final String {{localVariablePrefix}}localVarContentType = {{localVariablePrefix}}apiClient.selectHeaderContentType({{localVariablePrefix}}localVarContentTypes); + {{localVariablePrefix}}localVarHeaderParams.put("Content-Type", {{localVariablePrefix}}localVarContentType); + + if(progressListener != null) { + apiClient.getHttpClient().networkInterceptors().add(new com.squareup.okhttp.Interceptor() { + @Override + public com.squareup.okhttp.Response intercept(com.squareup.okhttp.Interceptor.Chain chain) throws IOException { + com.squareup.okhttp.Response originalResponse = chain.proceed(chain.request()); + return originalResponse.newBuilder() + .body(new ProgressResponseBody(originalResponse.body(), progressListener)) + .build(); + } + }); + } + + String[] {{localVariablePrefix}}localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + return {{localVariablePrefix}}apiClient.buildCall({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarCollectionQueryParams, {{localVariablePrefix}}localVarPostBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAuthNames, progressRequestListener); + } + + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + @SuppressWarnings("rawtypes") + private com.squareup.okhttp.Call {{operationId}}ValidateBeforeCall({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ProgressResponseBody.ProgressListener progressListener, final ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException { + {{^performBeanValidation}} + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new ApiException("Missing the required parameter '{{paramName}}' when calling {{operationId}}(Async)"); + } + {{/required}}{{/allParams}} + + com.squareup.okhttp.Call {{localVariablePrefix}}call = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}progressListener, progressRequestListener); + return {{localVariablePrefix}}call; + + {{/performBeanValidation}} + {{#performBeanValidation}} + try { + ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); + ExecutableValidator executableValidator = factory.getValidator().forExecutables(); + + Object[] parameterValues = { {{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}} }; + Method method = this.getClass().getMethod("{{operationId}}WithHttpInfo"{{#allParams}}, {{#isListContainer}}java.util.List{{/isListContainer}}{{#isMapContainer}}java.util.Map{{/isMapContainer}}{{^isListContainer}}{{^isMapContainer}}{{{dataType}}}{{/isMapContainer}}{{/isListContainer}}.class{{/allParams}}); + Set> violations = executableValidator.validateParameters(this, method, + parameterValues); + + if (violations.size() == 0) { + com.squareup.okhttp.Call {{localVariablePrefix}}call = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}progressListener, progressRequestListener); + return {{localVariablePrefix}}call; + + } else { + throw new BeanValidationException((Set) violations); + } + } catch (NoSuchMethodException e) { + e.printStackTrace(); + throw new ApiException(e.getMessage()); + } catch (SecurityException e) { + e.printStackTrace(); + throw new ApiException(e.getMessage()); + } + + {{/performBeanValidation}} + } + + /** + * {{summary}} + * {{notes}}{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}}{{#returnType}} + * @return {{returnType}}{{/returnType}} + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + {{#returnType}}ApiResponse<{{{returnType}}}> {{localVariablePrefix}}resp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + return {{localVariablePrefix}}resp.getData();{{/returnType}} + } + + /** + * {{summary}} + * {{notes}}{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + * @return ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + com.squareup.okhttp.Call {{localVariablePrefix}}call = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}null, null); + {{#returnType}}Type {{localVariablePrefix}}localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType(); + return {{localVariablePrefix}}apiClient.execute({{localVariablePrefix}}call, {{localVariablePrefix}}localVarReturnType);{{/returnType}}{{^returnType}}return {{localVariablePrefix}}apiClient.execute({{localVariablePrefix}}call);{{/returnType}} + } + + /** + * {{summary}} (asynchronously) + * {{notes}}{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + * @param callback The callback to be executed when the API call finishes + * @return The request call + * @throws ApiException If fail to process the API call, e.g. serializing the request body object + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public com.squareup.okhttp.Call {{operationId}}Async({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ApiCallback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{localVariablePrefix}}callback) throws ApiException { + + ProgressResponseBody.ProgressListener progressListener = null; + ProgressRequestBody.ProgressRequestListener progressRequestListener = null; + + if (callback != null) { + progressListener = new ProgressResponseBody.ProgressListener() { + @Override + public void update(long bytesRead, long contentLength, boolean done) { + callback.onDownloadProgress(bytesRead, contentLength, done); + } + }; + + progressRequestListener = new ProgressRequestBody.ProgressRequestListener() { + @Override + public void onRequestProgress(long bytesWritten, long contentLength, boolean done) { + callback.onUploadProgress(bytesWritten, contentLength, done); + } + }; + } + + com.squareup.okhttp.Call {{localVariablePrefix}}call = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}progressListener, progressRequestListener); + {{#returnType}}Type {{localVariablePrefix}}localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType(); + {{localVariablePrefix}}apiClient.executeAsync({{localVariablePrefix}}call, {{localVariablePrefix}}localVarReturnType, {{localVariablePrefix}}callback);{{/returnType}}{{^returnType}}{{localVariablePrefix}}apiClient.executeAsync({{localVariablePrefix}}call, {{localVariablePrefix}}callback);{{/returnType}} + return {{localVariablePrefix}}call; + } + {{/operation}} +} +{{/operations}} \ No newline at end of file diff --git a/libraries/okhttp-gson/auth/HttpBasicAuth.mustache b/libraries/okhttp-gson/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..320903b0319 --- /dev/null +++ b/libraries/okhttp-gson/auth/HttpBasicAuth.mustache @@ -0,0 +1,43 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; + +import com.squareup.okhttp.Credentials; + +import java.util.Map; +import java.util.List; + +import java.io.UnsupportedEncodingException; + +public class HttpBasicAuth implements Authentication { + private String username; + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public void applyToParams(List queryParams, Map headerParams) { + if (username == null && password == null) { + return; + } + headerParams.put("Authorization", Credentials.basic( + username == null ? "" : username, + password == null ? "" : password)); + } +} diff --git a/libraries/okhttp-gson/build.gradle.mustache b/libraries/okhttp-gson/build.gradle.mustache new file mode 100644 index 00000000000..27fe1caaf25 --- /dev/null +++ b/libraries/okhttp-gson/build.gradle.mustache @@ -0,0 +1,115 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + } + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + sourceCompatibility = JavaVersion.VERSION_{{^java8}}1_7{{/java8}}{{#java8}}1_8{{/java8}} + targetCompatibility = JavaVersion.VERSION_{{^java8}}1_7{{/java8}}{{#java8}}1_8{{/java8}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +dependencies { + compile 'io.swagger:swagger-annotations:1.5.17' + compile 'com.squareup.okhttp:okhttp:2.7.5' + compile 'com.squareup.okhttp:logging-interceptor:2.7.5' + compile 'com.google.code.gson:gson:2.8.1' + compile 'io.gsonfire:gson-fire:1.8.0' + {{#joda}} + compile 'joda-time:joda-time:2.9.9' + {{/joda}} + {{#threetenbp}} + compile 'org.threeten:threetenbp:1.3.5' + {{/threetenbp}} + testCompile 'junit:junit:4.12' +} diff --git a/libraries/okhttp-gson/build.sbt.mustache b/libraries/okhttp-gson/build.sbt.mustache new file mode 100644 index 00000000000..fcf788885d6 --- /dev/null +++ b/libraries/okhttp-gson/build.sbt.mustache @@ -0,0 +1,26 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "io.swagger" % "swagger-annotations" % "1.5.17", + "com.squareup.okhttp" % "okhttp" % "2.7.5", + "com.squareup.okhttp" % "logging-interceptor" % "2.7.5", + "com.google.code.gson" % "gson" % "2.8.1", + {{#joda}} + "joda-time" % "joda-time" % "2.9.9" % "compile", + {{/joda}} + {{#threetenbp}} + "org.threeten" % "threetenbp" % "1.3.5" % "compile", + {{/threetenbp}} + "io.gsonfire" % "gson-fire" % "1.8.0" % "compile", + "junit" % "junit" % "4.12" % "test", + "com.novocode" % "junit-interface" % "0.10" % "test" + ) + ) diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache new file mode 100644 index 00000000000..b5119774a05 --- /dev/null +++ b/libraries/okhttp-gson/pom.mustache @@ -0,0 +1,287 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{artifactUrl}} + {{artifactDescription}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-core-version} + + + com.squareup.okhttp + okhttp + ${okhttp-version} + + + com.squareup.okhttp + logging-interceptor + ${okhttp-version} + + + com.google.code.gson + gson + ${gson-version} + + + io.gsonfire + gson-fire + ${gson-fire-version} + + {{#joda}} + + joda-time + joda-time + ${jodatime-version} + + {{/joda}} + {{#threetenbp}} + + org.threeten + threetenbp + ${threetenbp-version} + + {{/threetenbp}} + {{#useBeanValidation}} + + + javax.validation + validation-api + 1.1.0.Final + provided + + {{/useBeanValidation}} + {{#performBeanValidation}} + + + org.hibernate + hibernate-validator + 5.4.1.Final + + + javax.el + el-api + 2.2 + + {{/performBeanValidation}} + {{#parcelableModel}} + + + com.google.android + android + 4.1.1.4 + provided + + {{/parcelableModel}} + + + junit + junit + ${junit-version} + test + + + + {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}} + ${java.version} + ${java.version} + 1.8.0 + 1.5.18 + 2.7.5 + 2.8.1 + {{#joda}} + 2.9.9 + {{/joda}} + {{#threetenbp}} + 1.3.5 + {{/threetenbp}} + 1.0.0 + 4.12 + UTF-8 + + diff --git a/libraries/rest-assured/ApiClient.mustache b/libraries/rest-assured/ApiClient.mustache new file mode 100644 index 00000000000..2b269854872 --- /dev/null +++ b/libraries/rest-assured/ApiClient.mustache @@ -0,0 +1,59 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import {{apiPackage}}.*; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import io.restassured.RestAssured; +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.builder.ResponseSpecBuilder; +import io.restassured.response.Response; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; +{{/fullJavaUtil}} + +public class ApiClient { + + private final Config config; + + private ApiClient(Config config) { + this.config = config; + } + + public static ApiClient api(Config config) { + return new ApiClient(config); + } + + {{#apiInfo}} + {{#apis}} + public {{classname}} {{classVarName}}() { + return {{classname}}.{{classVarName}}(config.baseReqSpec.get()); + } + {{/apis}} + {{/apiInfo}} + + public static class Config { + private Supplier baseReqSpec; + + /** + * Use common specification for all operations + */ + public Config reqSpecSupplier(Supplier supplier) { + this.baseReqSpec = supplier; + return this; + } + + public static Config apiConfig() { + return new Config(); + } + } +} \ No newline at end of file diff --git a/libraries/rest-assured/GsonObjectMapper.mustache b/libraries/rest-assured/GsonObjectMapper.mustache new file mode 100644 index 00000000000..320d8141f95 --- /dev/null +++ b/libraries/rest-assured/GsonObjectMapper.mustache @@ -0,0 +1,30 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import io.restassured.mapper.ObjectMapper; +import io.restassured.mapper.ObjectMapperDeserializationContext; +import io.restassured.mapper.ObjectMapperSerializationContext; + +public class GsonObjectMapper implements ObjectMapper { + + private JSON json; + + private GsonObjectMapper() { + this.json = new JSON(); + } + + public static GsonObjectMapper gson() { + return new GsonObjectMapper(); + } + + @Override + public Object deserialize(ObjectMapperDeserializationContext context) { + return json.deserialize(context.getDataToDeserialize().asString(), context.getType()); + } + + @Override + public Object serialize(ObjectMapperSerializationContext context) { + return json.serialize(context.getObjectToSerialize()); + } +} \ No newline at end of file diff --git a/libraries/rest-assured/README.mustache b/libraries/rest-assured/README.mustache new file mode 100644 index 00000000000..56560172ee3 --- /dev/null +++ b/libraries/rest-assured/README.mustache @@ -0,0 +1,43 @@ +# {{artifactId}} + +## Requirements + +Building the API client library requires [Maven](https://maven.apache.org/) to be installed. + +## Installation & Usage + +To install the API client library to your local Maven repository, simply execute: + +```shell +mvn install +``` + +To deploy it to a remote Maven repository instead, configure the settings of the repository and execute: + +```shell +mvn deploy +``` + +Refer to the [official documentation](https://maven.apache.org/plugins/maven-deploy-plugin/usage.html) for more information. + +After the client library is installed/deployed, you can use it in your Maven project by adding the following to your *pom.xml*: + +```xml + + {{groupId}} + {{artifactId}} + {{artifactVersion}} + compile + + +``` + +## Recommendation + +It's recommended to create an instance of `ApiClient` per thread in a multithreaded environment to avoid any potential issues. + +## Author + +{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} +{{/hasMore}}{{/apis}}{{/apiInfo}} + diff --git a/libraries/rest-assured/ResponseSpecBuilders.mustache b/libraries/rest-assured/ResponseSpecBuilders.mustache new file mode 100644 index 00000000000..af7e7ac960f --- /dev/null +++ b/libraries/rest-assured/ResponseSpecBuilders.mustache @@ -0,0 +1,31 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import io.restassured.builder.ResponseSpecBuilder; +import io.restassured.response.Response; +import io.restassured.specification.ResponseSpecification; + +import java.util.function.Function; + +public class ResponseSpecBuilders { + + private ResponseSpecBuilders() { + } + + public static Function validatedWith(ResponseSpecification respSpec) { + return response -> response.then().spec(respSpec).extract().response(); + } + + public static Function validatedWith(ResponseSpecBuilder respSpec) { + return validatedWith(respSpec.build()); + } + + /** + * @param code expected status code + * @return ResponseSpecBuilder + */ + public static ResponseSpecBuilder shouldBeCode(int code) { + return new ResponseSpecBuilder().expectStatusCode(code); + } +} \ No newline at end of file diff --git a/libraries/rest-assured/api.mustache b/libraries/rest-assured/api.mustache new file mode 100644 index 00000000000..1d1a5d9ae54 --- /dev/null +++ b/libraries/rest-assured/api.mustache @@ -0,0 +1,243 @@ +{{>licenseInfo}} + +package {{package}}; + +import com.google.gson.reflect.TypeToken; +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import io.restassured.RestAssured; +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.builder.ResponseSpecBuilder; +import io.restassured.response.Response; + +import java.lang.reflect.Type; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; +{{/fullJavaUtil}} +import {{invokerPackage}}.JSON; + +import static io.restassured.http.Method.*; + +public class {{classname}} { + + private RequestSpecBuilder reqSpec; + + private JSON json; + + private {{classname}}(RequestSpecBuilder reqSpec) { + this.reqSpec = reqSpec; + this.json = new JSON(); + } + + public static {{classname}} {{classVarName}}(RequestSpecBuilder reqSpec) { + return new {{classname}}(reqSpec); + } + +{{#operations}} +{{#operation}} + + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{operationIdCamelCase}}Oper {{operationId}}() { + return new {{operationIdCamelCase}}Oper(reqSpec); + } +{{/operation}} +{{/operations}} + + /** + * Get JSON + * + * @return JSON object + */ + public JSON getJSON() { + return json; + } + + /** + * Set JSON + * + * @param json JSON object + * @return {{classname}} + */ + public {{classname}} setJSON(JSON json) { + this.json = json; + return this; + } + + /** + * Customise request specification + */ + public {{classname}} reqSpec(Consumer consumer) { + consumer.accept(reqSpec); + return this; + } + + {{#operations}} + {{#operation}} + /** + * {{summary}} + * {{notes}} + * + {{#allParams}} + * @see #{{#isPathParam}}{{paramName}}Path{{/isPathParam}}{{#isQueryParam}}{{paramName}}Query{{/isQueryParam}}{{#isFormParam}}{{^isFile}}{{paramName}}Form{{/isFile}}{{#isFile}}{{paramName}}MultiPart{{/isFile}}{{/isFormParam}}{{#isHeaderParam}}{{paramName}}Header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} + {{#returnType}} + * return {{{returnType}}} + {{/returnType}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public class {{operationIdCamelCase}}Oper { + + public static final String REQ_URI = "{{path}}"; + + private RequestSpecBuilder reqSpec; + + private ResponseSpecBuilder respSpec; + + public {{operationIdCamelCase}}Oper() { + this.reqSpec = new RequestSpecBuilder(); + {{#vendorExtensions}} + {{#x-contentType}} + reqSpec.setContentType("{{x-contentType}}"); + {{/x-contentType}} + {{#x-accepts}} + reqSpec.setAccept("{{x-accepts}}"); + {{/x-accepts}} + {{/vendorExtensions}} + this.respSpec = new ResponseSpecBuilder(); + } + + public {{operationIdCamelCase}}Oper(RequestSpecBuilder reqSpec) { + this.reqSpec = reqSpec; + {{#vendorExtensions}} + {{#x-contentType}} + reqSpec.setContentType("{{x-contentType}}"); + {{/x-contentType}} + {{#x-accepts}} + reqSpec.setAccept("{{x-accepts}}"); + {{/x-accepts}} + {{/vendorExtensions}} + this.respSpec = new ResponseSpecBuilder(); + } + + /** + * {{httpMethod}} {{path}} + */ + public T execute(Function handler) { + return handler.apply(RestAssured.given().spec(reqSpec.build()).expect().spec(respSpec.build()).when().request({{httpMethod}}, REQ_URI)); + } + {{#returnType}} + + /** + * {{httpMethod}} {{path}} + * @return {{{returnType}}} + */ + public {{{returnType}}} executeAs(Function handler) { + Type type = new TypeToken<{{{returnType}}}>(){}.getType(); + return getJSON().deserialize(execute(handler).asString(), type); + } + {{/returnType}} + {{#bodyParams}} + + /** + * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + */ + public {{operationIdCamelCase}}Oper body({{{dataType}}} {{paramName}}) { + reqSpec.setBody(getJSON().serialize({{paramName}})); + return this; + } + {{/bodyParams}} + {{#headerParams}} + + /** + * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + */ + public {{operationIdCamelCase}}Oper {{paramName}}Header(String {{paramName}}) { + reqSpec.addHeader("{{baseName}}", {{paramName}}); + return this; + } + {{/headerParams}} + {{#pathParams}} + + /** + * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + */ + public {{operationIdCamelCase}}Oper {{paramName}}Path(Object {{paramName}}) { + reqSpec.addPathParam("{{baseName}}", {{paramName}}); + return this; + } + {{/pathParams}} + {{#queryParams}} + + /** + * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + */ + public {{operationIdCamelCase}}Oper {{paramName}}Query(Object... {{paramName}}) { + reqSpec.addQueryParam("{{baseName}}", {{paramName}}); + return this; + } + {{/queryParams}} + {{#formParams}} + {{^isFile}} + + /** + * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + */ + public {{operationIdCamelCase}}Oper {{paramName}}Form(Object... {{paramName}}) { + reqSpec.addFormParam("{{baseName}}", {{paramName}}); + return this; + } + {{/isFile}} + {{/formParams}} + {{#formParams}} + {{#isFile}} + + /** + * It will assume that the control name is file and the is + * @see #reqSpec for customise + * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + */ + public {{operationIdCamelCase}}Oper {{paramName}}MultiPart({{{dataType}}} {{paramName}}) { + reqSpec.addMultiPart({{paramName}}); + return this; + } + {{/isFile}} + {{/formParams}} + + /** + * Customise request specification + */ + public {{operationIdCamelCase}}Oper reqSpec(Consumer consumer) { + consumer.accept(reqSpec); + return this; + } + + /** + * Customise response specification + */ + public {{operationIdCamelCase}}Oper respSpec(Consumer consumer) { + consumer.accept(respSpec); + return this; + } + } +{{/operation}} +{{/operations}} +} \ No newline at end of file diff --git a/libraries/rest-assured/api_doc.mustache b/libraries/rest-assured/api_doc.mustache new file mode 100644 index 00000000000..c8bf20319e7 --- /dev/null +++ b/libraries/rest-assured/api_doc.mustache @@ -0,0 +1,62 @@ +# {{classname}}{{#description}} +{{description}}{{/description}} + +All URIs are relative to *{{basePath}}* + +Method | HTTP request | Description +------------- | ------------- | ------------- +{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}} + +{{#operations}} +{{#operation}} + +# **{{operationId}}** +> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) + +{{summary}}{{#notes}} + +{{notes}}{{/notes}} + +### Example +```java +// Import classes: +//import {{invokerPackage}}.ApiClient; +//import io.restassured.builder.RequestSpecBuilder; +//import io.restassured.filter.log.ErrorLoggingFilter; + +{{classname}} api = ApiClient.api(ApiClient.Config.apiConfig().withReqSpecSupplier( + () -> new RequestSpecBuilder() + .setBaseUri("{{basePath}}"))).{{classVarName}}(); + +api.{{operationId}}(){{#allParams}}{{#required}}{{#isPathParam}} + .{{paramName}}Path({{paramName}}){{/isPathParam}}{{#isQueryParam}} + .{{paramName}}Query({{paramName}}){{/isQueryParam}}{{#isFormParam}}{{^isFile}} + .{{paramName}}Form({{paramName}}){{/isFile}}{{/isFormParam}}{{#isFormParam}}{{#isFile}} + .{{paramName}}MultiPart({{paramName}}){{/isFile}}{{/isFormParam}}{{#isHeaderParam}} + .{{paramName}}Header({{paramName}}){{/isHeaderParam}}{{#isBodyParam}} + .body({{paramName}}){{/isBodyParam}}{{/required}}{{/allParams}}.execute(r -> r.prettyPeek()); +``` + +### Parameters +{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} +Name | Type | Description | Notes +------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} +{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} +{{/allParams}} + +### Return type + +{{#returnType}}{{#returnTypeIsPrimitive}}**{{returnType}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{returnType}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}null (empty response body){{/returnType}} + +### Authorization + +{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{name}}](../README.md#{{name}}){{^-last}}, {{/-last}}{{/authMethods}} + +### HTTP request headers + + - **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} + - **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} + +{{/operation}} +{{/operations}} diff --git a/libraries/rest-assured/api_test.mustache b/libraries/rest-assured/api_test.mustache new file mode 100644 index 00000000000..5c17db415e3 --- /dev/null +++ b/libraries/rest-assured/api_test.mustache @@ -0,0 +1,65 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} +import {{invokerPackage}}.ApiClient; +import {{apiPackage}}.{{classname}}; +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.filter.log.ErrorLoggingFilter; +import org.junit.Before; +import org.junit.Test; +import org.junit.Ignore; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} +import static io.restassured.config.ObjectMapperConfig.objectMapperConfig; +import static io.restassured.config.RestAssuredConfig.config; +import static {{invokerPackage}}.GsonObjectMapper.gson; + +/** + * API tests for {{classname}} + */ +@Ignore +public class {{classname}}Test { + + private {{classname}} api; + + @Before + public void createApi() { + api = ApiClient.api(ApiClient.Config.apiConfig().reqSpecSupplier( + () -> new RequestSpecBuilder().setConfig(config().objectMapperConfig(objectMapperConfig().defaultObjectMapper(gson()))) + .addFilter(new ErrorLoggingFilter()) + .setBaseUri("{{{basePath}}}"))).{{classVarName}}(); + } +{{#operations}} +{{#operation}} + + {{#responses}} + /** + * {{message}} + */ + @Test + public void shouldSee{{code}}After{{operationIdCamelCase}}() { + {{#allParams}} + {{#isHeaderParam}}String {{paramName}} = null;{{/isHeaderParam}}{{^isHeaderParam}}{{{dataType}}} {{paramName}} = null;{{/isHeaderParam}} + {{/allParams}} + api.{{operationId}}(){{#allParams}}{{#required}}{{#isPathParam}} + .{{paramName}}Path({{paramName}}){{/isPathParam}}{{#isQueryParam}} + .{{paramName}}Query({{paramName}}){{/isQueryParam}}{{#isFormParam}}{{^isFile}} + .{{paramName}}Form({{paramName}}){{/isFile}}{{/isFormParam}}{{#isFormParam}}{{#isFile}} + .{{paramName}}MultiPart({{paramName}}){{/isFile}}{{/isFormParam}}{{#isHeaderParam}} + .{{paramName}}Header({{paramName}}){{/isHeaderParam}}{{#isBodyParam}} + .body({{paramName}}){{/isBodyParam}}{{/required}}{{/allParams}}.execute(r -> r.prettyPeek()); + // TODO: test validations + } + + {{/responses}} +{{/operation}} +{{/operations}} +} \ No newline at end of file diff --git a/libraries/rest-assured/build.gradle.mustache b/libraries/rest-assured/build.gradle.mustache new file mode 100644 index 00000000000..fc67b62d13e --- /dev/null +++ b/libraries/rest-assured/build.gradle.mustache @@ -0,0 +1,124 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.5.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 23 + buildToolsVersion '23.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 22 + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + swagger_annotations_version = "1.5.15" + rest_assured_version = "3.0.6" + junit_version = "4.12" + gson_version = "2.6.1" + gson_fire_version = "1.8.2" +{{#joda}} + jodatime_version = "2.9.9" +{{/joda}} +{{#threetenbp}} + threetenbp_version = "1.3.5" +{{/threetenbp}} + okio_version = "1.13.0" +} + +dependencies { + compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "io.rest-assured:scala-support:$rest_assured_version" + compile "io.gsonfire:gson-fire:$gson_fire_version" +{{#joda}} + compile "joda-time:joda-time:$jodatime_version" + compile 'com.google.code.gson:gson:$gson_version' +{{/joda}} +{{#threetenbp}} + compile "org.threeten:threetenbp:$threetenbp_version" +{{/threetenbp}} + compile "com.squareup.okio:okio:$okio_version" + testCompile "junit:junit:$junit_version" +} diff --git a/libraries/rest-assured/build.sbt.mustache b/libraries/rest-assured/build.sbt.mustache new file mode 100644 index 00000000000..289345c3a0a --- /dev/null +++ b/libraries/rest-assured/build.sbt.mustache @@ -0,0 +1,26 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "io.swagger" % "swagger-annotations" % "1.5.15", + "io.rest-assured" % "scala-support" % "3.0.6", + "com.google.code.gson" % "gson" % "2.6.1", + "io.gsonfire" % "gson-fire" % "1.8.2" % "compile", +{{#joda}} + "joda-time" % "joda-time" % "2.9.9" % "compile", +{{/joda}} +{{#threetenbp}} + "org.threeten" % "threetenbp" % "1.3.5" % "compile", +{{/threetenbp}} + "com.squareup.okio" % "okio" % "1.13.0" % "compile", + "junit" % "junit" % "4.12" % "test", + "com.novocode" % "junit-interface" % "0.10" % "test" + ) + ) diff --git a/libraries/rest-assured/pom.mustache b/libraries/rest-assured/pom.mustache new file mode 100644 index 00000000000..80f043340c2 --- /dev/null +++ b/libraries/rest-assured/pom.mustache @@ -0,0 +1,262 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{artifactUrl}} + {{artifactDescription}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add_sources + generate-sources + + add-source + + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-core-version} + + + io.rest-assured + rest-assured + ${rest-assured.version} + + + com.google.code.gson + gson + ${gson-version} + + {{#joda}} + + joda-time + joda-time + ${jodatime-version} + + {{/joda}} + {{#threetenbp}} + + org.threeten + threetenbp + ${threetenbp-version} + + {{/threetenbp}} + + io.gsonfire + gson-fire + ${gson-fire-version} + + + com.squareup.okio + okio + ${okio-version} + + + + junit + junit + ${junit-version} + test + + + + UTF-8 + 1.5.15 + 3.0.6 + 2.6.1 + 1.8.2 + 1.0.0 + {{#joda}} + 2.9.9 + {{/joda}} + {{#threetenbp}} + 1.3.5 + {{/threetenbp}} + 1.13.0 + 4.12 + + diff --git a/libraries/resteasy/ApiClient.mustache b/libraries/resteasy/ApiClient.mustache new file mode 100644 index 00000000000..a8b3ca6f5b8 --- /dev/null +++ b/libraries/resteasy/ApiClient.mustache @@ -0,0 +1,693 @@ +package {{invokerPackage}}; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.file.Files; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TimeZone; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.Form; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.jboss.logging.Logger; +import org.jboss.resteasy.client.jaxrs.internal.ClientConfiguration; +import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput; +import org.jboss.resteasy.spi.ResteasyProviderFactory; + +import {{invokerPackage}}.auth.Authentication; +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.OAuth; + +{{>generatedAnnotation}} +public class ApiClient { + private Map defaultHeaderMap = new HashMap(); + private String basePath = "{{{basePath}}}"; + private boolean debugging = false; + + private Client httpClient; + private JSON json; + private String tempFolderPath = null; + + private Map authentications; + + private int statusCode; + private Map> responseHeaders; + + private DateFormat dateFormat; + + public ApiClient() { + json = new JSON(); + httpClient = buildHttpClient(debugging); + + this.dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + + // Use UTC as the default time zone. + this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + + this.json.setDateFormat((DateFormat) dateFormat.clone()); + + // Set default User-Agent. + setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}Swagger-Codegen/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap();{{#authMethods}}{{#isBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + } + + /** + * Gets the JSON instance to do JSON serialization and deserialization. + */ + public JSON getJSON() { + return json; + } + + public Client getHttpClient() { + return httpClient; + } + + public ApiClient setHttpClient(Client httpClient) { + this.httpClient = httpClient; + return this; + } + + public String getBasePath() { + return basePath; + } + + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Gets the status code of the previous request + */ + public int getStatusCode() { + return statusCode; + } + + /** + * Gets the response headers of the previous request + */ + public Map> getResponseHeaders() { + return responseHeaders; + } + + /** + * Get authentications (key: authentication name, value: authentication). + */ + public Map getAuthentications() { + return authentications; + } + + /** + * Get authentication for the given name. + * + * @param authName The authentication name + * @return The authentication, null if not found + */ + public Authentication getAuthentication(String authName) { + return authentications.get(authName); + } + + /** + * Helper method to set username for the first HTTP basic authentication. + */ + public void setUsername(String username) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setUsername(username); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set password for the first HTTP basic authentication. + */ + public void setPassword(String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setPassword(password); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set API key value for the first API key authentication. + */ + public void setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + */ + public void setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set access token for the first OAuth2 authentication. + */ + public void setAccessToken(String accessToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setAccessToken(accessToken); + return; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Set the User-Agent header's value (by adding to the default header map). + */ + public ApiClient setUserAgent(String userAgent) { + addDefaultHeader("User-Agent", userAgent); + return this; + } + + /** + * Add a default header. + * + * @param key The header's key + * @param value The header's value + */ + public ApiClient addDefaultHeader(String key, String value) { + defaultHeaderMap.put(key, value); + return this; + } + + /** + * Check that whether debugging is enabled for this API client. + */ + public boolean isDebugging() { + return debugging; + } + + /** + * Enable/disable debugging for this API client. + * + * @param debugging To enable (true) or disable (false) debugging + */ + public ApiClient setDebugging(boolean debugging) { + this.debugging = debugging; + // Rebuild HTTP Client according to the new "debugging" value. + this.httpClient = buildHttpClient(debugging); + return this; + } + + /** + * The path of temporary folder used to store downloaded files from endpoints + * with file response. The default value is null, i.e. using + * the system's default tempopary folder. + * + * @see https://docs.oracle.com/javase/7/docs/api/java/io/File.html#createTempFile(java.lang.String,%20java.lang.String,%20java.io.File) + */ + public String getTempFolderPath() { + return tempFolderPath; + } + + public ApiClient setTempFolderPath(String tempFolderPath) { + this.tempFolderPath = tempFolderPath; + return this; + } + + /** + * Get the date format used to parse/format date parameters. + */ + public DateFormat getDateFormat() { + return dateFormat; + } + + /** + * Set the date format used to parse/format date parameters. + */ + public ApiClient setDateFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + // also set the date format for model (de)serialization with Date properties + this.json.setDateFormat((DateFormat) dateFormat.clone()); + return this; + } + + /** + * Parse the given string into Date object. + */ + public Date parseDate(String str) { + try { + return dateFormat.parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(e); + } + } + + /** + * Format the given Date object into string. + */ + public String formatDate(Date date) { + return dateFormat.format(date); + } + + /** + * Format the given parameter object into string. + */ + public String parameterToString(Object param) { + if (param == null) { + return ""; + } else if (param instanceof Date) { + return formatDate((Date) param); + } else if (param instanceof Collection) { + StringBuilder b = new StringBuilder(); + for(Object o : (Collection)param) { + if(b.length() > 0) { + b.append(","); + } + b.append(String.valueOf(o)); + } + return b.toString(); + } else { + return String.valueOf(param); + } + } + + /* + Format to {@code Pair} objects. + */ + public List parameterToPairs(String collectionFormat, String name, Object value){ + List params = new ArrayList(); + + // preconditions + if (name == null || name.isEmpty() || value == null) return params; + + Collection valueCollection = null; + if (value instanceof Collection) { + valueCollection = (Collection) value; + } else { + params.add(new Pair(name, parameterToString(value))); + return params; + } + + if (valueCollection.isEmpty()){ + return params; + } + + // get the collection format + collectionFormat = (collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat); // default: csv + + // create the params based on the collection format + if (collectionFormat.equals("multi")) { + for (Object item : valueCollection) { + params.add(new Pair(name, parameterToString(item))); + } + + return params; + } + + String delimiter = ","; + + if (collectionFormat.equals("csv")) { + delimiter = ","; + } else if (collectionFormat.equals("ssv")) { + delimiter = " "; + } else if (collectionFormat.equals("tsv")) { + delimiter = "\t"; + } else if (collectionFormat.equals("pipes")) { + delimiter = "|"; + } + + StringBuilder sb = new StringBuilder() ; + for (Object item : valueCollection) { + sb.append(delimiter); + sb.append(parameterToString(item)); + } + + params.add(new Pair(name, sb.substring(1))); + + return params; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * application/vnd.company+json + * @param mime MIME (Multipurpose Internet Mail Extensions) + * @return True if the given MIME is JSON, false otherwise. + */ + public boolean isJsonMime(String mime) { + String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$"; + return mime != null && (mime.matches(jsonMime) || mime.equals("*/*")); + } + + /** + * Select the Accept header's value from the given accepts array: + * if JSON exists in the given array, use it; + * otherwise use all of them (joining into a string) + * + * @param accepts The accepts array to select from + * @return The Accept header to use. If the given array is empty, + * null will be returned (not to set the Accept header explicitly). + */ + public String selectHeaderAccept(String[] accepts) { + if (accepts.length == 0) { + return null; + } + for (String accept : accepts) { + if (isJsonMime(accept)) { + return accept; + } + } + return StringUtil.join(accepts, ","); + } + + /** + * Select the Content-Type header's value from the given array: + * if JSON exists in the given array, use it; + * otherwise use the first one of the array. + * + * @param contentTypes The Content-Type array to select from + * @return The Content-Type header to use. If the given array is empty, + * JSON will be used. + */ + public String selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0) { + return "application/json"; + } + for (String contentType : contentTypes) { + if (isJsonMime(contentType)) { + return contentType; + } + } + return contentTypes[0]; + } + + /** + * Escape the given string to be used as URL query value. + */ + public String escapeString(String str) { + try { + return URLEncoder.encode(str, "utf8").replaceAll("\\+", "%20"); + } catch (UnsupportedEncodingException e) { + return str; + } + } + + /** + * Serialize the given Java object into string entity according the given + * Content-Type (only JSON is supported for now). + */ + public Entity serialize(Object obj, Map formParams, String contentType) throws ApiException { + Entity entity = null; + if (contentType.startsWith("multipart/form-data")) { + MultipartFormDataOutput multipart = new MultipartFormDataOutput(); + //MultiPart multiPart = new MultiPart(); + for (Entry param: formParams.entrySet()) { + if (param.getValue() instanceof File) { + File file = (File) param.getValue(); + try { + multipart.addFormData(param.getValue().toString(),new FileInputStream(file),MediaType.APPLICATION_OCTET_STREAM_TYPE); + } catch (FileNotFoundException e) { + throw new ApiException("Could not serialize multipart/form-data "+e.getMessage()); + } + } else { + multipart.addFormData(param.getValue().toString(),param.getValue().toString(),MediaType.APPLICATION_OCTET_STREAM_TYPE); + } + } + entity = Entity.entity(multipart.getFormData(), MediaType.MULTIPART_FORM_DATA_TYPE); + } else if (contentType.startsWith("application/x-www-form-urlencoded")) { + Form form = new Form(); + for (Entry param: formParams.entrySet()) { + form.param(param.getKey(), parameterToString(param.getValue())); + } + entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE); + } else { + // We let jersey handle the serialization + entity = Entity.entity(obj, contentType); + } + return entity; + } + + /** + * Deserialize response body to Java object according to the Content-Type. + */ + public T deserialize(Response response, GenericType returnType) throws ApiException { + if (response == null || returnType == null) { + return null; + } + + if ("byte[]".equals(returnType.toString())) { + // Handle binary response (byte array). + return (T) response.readEntity(byte[].class); + } else if (returnType.equals(File.class)) { + // Handle file downloading. + @SuppressWarnings("unchecked") + T file = (T) downloadFileFromResponse(response); + return file; + } + + String contentType = null; + List contentTypes = response.getHeaders().get("Content-Type"); + if (contentTypes != null && !contentTypes.isEmpty()) + contentType = String.valueOf(contentTypes.get(0)); + if (contentType == null) + throw new ApiException(500, "missing Content-Type in response"); + + return response.readEntity(returnType); + } + + /** + * Download file from the given response. + * @throws ApiException If fail to read file content from response and write to disk + */ + public File downloadFileFromResponse(Response response) throws ApiException { + try { + File file = prepareDownloadFile(response); +{{^supportJava6}} + Files.copy(response.readEntity(InputStream.class), file.toPath()); +{{/supportJava6}} +{{#supportJava6}} + // Java6 falls back to commons.io for file copying + FileUtils.copyToFile(response.readEntity(InputStream.class), file); +{{/supportJava6}} + return file; + } catch (IOException e) { + throw new ApiException(e); + } + } + + public File prepareDownloadFile(Response response) throws IOException { + String filename = null; + String contentDisposition = (String) response.getHeaders().getFirst("Content-Disposition"); + if (contentDisposition != null && !"".equals(contentDisposition)) { + // Get filename from the Content-Disposition header. + Pattern pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?"); + Matcher matcher = pattern.matcher(contentDisposition); + if (matcher.find()) + filename = matcher.group(1); + } + + String prefix = null; + String suffix = null; + if (filename == null) { + prefix = "download-"; + suffix = ""; + } else { + int pos = filename.lastIndexOf("."); + if (pos == -1) { + prefix = filename + "-"; + } else { + prefix = filename.substring(0, pos) + "-"; + suffix = filename.substring(pos); + } + // File.createTempFile requires the prefix to be at least three characters long + if (prefix.length() < 3) + prefix = "download-"; + } + + if (tempFolderPath == null) + return File.createTempFile(prefix, suffix); + else + return File.createTempFile(prefix, suffix, new File(tempFolderPath)); + } + + /** + * Invoke API by sending HTTP request with the given options. + * + * @param path The sub-path of the HTTP URL + * @param method The request method, one of "GET", "POST", "PUT", "HEAD" and "DELETE" + * @param queryParams The query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param formParams The form parameters + * @param accept The request's Accept header + * @param contentType The request's Content-Type header + * @param authNames The authentications to apply + * @param returnType The return type into which to deserialize the response + * @return The response body in type of string + */ + public T invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { + updateParamsForAuth(authNames, queryParams, headerParams); + + // Not using `.target(this.basePath).path(path)` below, + // to support (constant) query string in `path`, e.g. "/posts?draft=1" + WebTarget target = httpClient.target(this.basePath + path); + + if (queryParams != null) { + for (Pair queryParam : queryParams) { + if (queryParam.getValue() != null) { + target = target.queryParam(queryParam.getName(), queryParam.getValue()); + } + } + } + + Invocation.Builder invocationBuilder = target.request().accept(accept); + + for (Entry headerParamsEnrty : headerParams.entrySet()) { + String value = headerParamsEnrty.getValue(); + if (value != null) { + invocationBuilder = invocationBuilder.header(headerParamsEnrty.getKey(), value); + } + } + + for (Entry defaultHeaderEnrty: defaultHeaderMap.entrySet()) { + if (!headerParams.containsKey(defaultHeaderEnrty.getKey())) { + String value = defaultHeaderEnrty.getKey(); + if (value != null) { + invocationBuilder = invocationBuilder.header(defaultHeaderEnrty.getKey(), value); + } + } + } + + Entity entity = serialize(body, formParams, contentType); + + Response response = null; + + if ("GET".equals(method)) { + response = invocationBuilder.get(); + } else if ("POST".equals(method)) { + response = invocationBuilder.post(entity); + } else if ("PUT".equals(method)) { + response = invocationBuilder.put(entity); + } else if ("DELETE".equals(method)) { + response = invocationBuilder.delete(); + } else if ("PATCH".equals(method)) { + response = invocationBuilder.header("X-HTTP-Method-Override", "PATCH").post(entity); + } else if ("HEAD".equals(method)) { + response = invocationBuilder.head(); + } else { + throw new ApiException(500, "unknown method type " + method); + } + + statusCode = response.getStatusInfo().getStatusCode(); + responseHeaders = buildResponseHeaders(response); + + if (response.getStatus() == Status.NO_CONTENT.getStatusCode()) { + return null; + } else if (response.getStatusInfo().getFamily().equals(Status.Family.SUCCESSFUL)) { + if (returnType == null) + return null; + else + return deserialize(response, returnType); + } else { + String message = "error"; + String respBody = null; + if (response.hasEntity()) { + try { + respBody = String.valueOf(response.readEntity(String.class)); + message = respBody; + } catch (RuntimeException e) { + // e.printStackTrace(); + } + } + throw new ApiException( + response.getStatus(), + message, + buildResponseHeaders(response), + respBody); + } + } + + /** + * Build the Client used to make HTTP requests. + */ + private Client buildHttpClient(boolean debugging) { + final ClientConfiguration clientConfig = new ClientConfiguration(ResteasyProviderFactory.getInstance()); + clientConfig.register(json); + if(debugging){ + clientConfig.register(Logger.class); + } + return ClientBuilder.newClient(clientConfig); + } + private Map> buildResponseHeaders(Response response) { + Map> responseHeaders = new HashMap>(); + for (Entry> entry: response.getHeaders().entrySet()) { + List values = entry.getValue(); + List headers = new ArrayList(); + for (Object o : values) { + headers.add(String.valueOf(o)); + } + responseHeaders.put(entry.getKey(), headers); + } + return responseHeaders; + } + + /** + * Update query and header parameters based on authentication settings. + * + * @param authNames The authentications to apply + */ + private void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams) { + for (String authName : authNames) { + Authentication auth = authentications.get(authName); + if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + auth.applyToParams(queryParams, headerParams); + } + } +} diff --git a/libraries/resteasy/JSON.mustache b/libraries/resteasy/JSON.mustache new file mode 100644 index 00000000000..27d2aa65d23 --- /dev/null +++ b/libraries/resteasy/JSON.mustache @@ -0,0 +1,48 @@ +package {{invokerPackage}}; + +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.*; +{{#java8}} +import com.fasterxml.jackson.datatype.jsr310.*; +{{/java8}} +{{^java8}} +import com.fasterxml.jackson.datatype.joda.*; +{{/java8}} + +import java.text.DateFormat; + +import javax.ws.rs.ext.ContextResolver; + +{{>generatedAnnotation}} +public class JSON implements ContextResolver { + private ObjectMapper mapper; + + public JSON() { + mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.setDateFormat(new RFC3339DateFormat()); + {{#java8}} + mapper.registerModule(new JavaTimeModule()); + {{/java8}} + {{^java8}} + mapper.registerModule(new JodaModule()); + {{/java8}} + } + + /** + * Set the date format for JSON (de)serialization with Date properties. + */ + public void setDateFormat(DateFormat dateFormat) { + mapper.setDateFormat(dateFormat); + } + + @Override + public ObjectMapper getContext(Class type) { + return mapper; + } +} diff --git a/libraries/resteasy/api.mustache b/libraries/resteasy/api.mustache new file mode 100644 index 00000000000..f3fd01ed61b --- /dev/null +++ b/libraries/resteasy/api.mustache @@ -0,0 +1,109 @@ +package {{package}}; + +import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.Configuration; +import {{invokerPackage}}.Pair; + +import javax.ws.rs.core.GenericType; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}} { + private ApiClient {{localVariablePrefix}}apiClient; + + public {{classname}}() { + this(Configuration.getDefaultApiClient()); + } + + public {{classname}}(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + public ApiClient getApiClient() { + return {{localVariablePrefix}}apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + {{#operation}} + /** + * {{summary}} + * {{notes}}{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}}{{#returnType}} + * @return {{{returnType}}}{{/returnType}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + Object {{localVariablePrefix}}localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + } + {{/required}}{{/allParams}} + // create path and map variables + String {{localVariablePrefix}}localVarPath = "{{{path}}}".replaceAll("\\{format\\}","json"){{#pathParams}} + .replaceAll("\\{" + "{{baseName}}" + "\\}", {{localVariablePrefix}}apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; + + // query params + {{javaUtilPrefix}}List {{localVariablePrefix}}localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarFormParams = new {{javaUtilPrefix}}HashMap(); + + {{#queryParams}} + {{localVariablePrefix}}localVarQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); + {{/queryParams}} + + {{#headerParams}}if ({{paramName}} != null) + {{localVariablePrefix}}localVarHeaderParams.put("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}})); + {{/headerParams}} + + {{#formParams}}if ({{paramName}} != null) + {{localVariablePrefix}}localVarFormParams.put("{{baseName}}", {{paramName}}); + {{/formParams}} + + final String[] {{localVariablePrefix}}localVarAccepts = { + {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} + }; + final String {{localVariablePrefix}}localVarAccept = {{localVariablePrefix}}apiClient.selectHeaderAccept({{localVariablePrefix}}localVarAccepts); + + final String[] {{localVariablePrefix}}localVarContentTypes = { + {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} + }; + final String {{localVariablePrefix}}localVarContentType = {{localVariablePrefix}}apiClient.selectHeaderContentType({{localVariablePrefix}}localVarContentTypes); + + String[] {{localVariablePrefix}}localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + + {{#returnType}} + GenericType<{{{returnType}}}> {{localVariablePrefix}}localVarReturnType = new GenericType<{{{returnType}}}>() {}; + return {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarPostBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccept, {{localVariablePrefix}}localVarContentType, {{localVariablePrefix}}localVarAuthNames, {{localVariablePrefix}}localVarReturnType); + {{/returnType}}{{^returnType}} + {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarPostBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccept, {{localVariablePrefix}}localVarContentType, {{localVariablePrefix}}localVarAuthNames, null); + {{/returnType}} + } + {{/operation}} +} +{{/operations}} diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache new file mode 100644 index 00000000000..fc42da3e68c --- /dev/null +++ b/libraries/resteasy/build.gradle.mustache @@ -0,0 +1,147 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.5.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 23 + buildToolsVersion '23.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 23 + } + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + {{#java8}} + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + {{/java8}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + swagger_annotations_version = "1.5.8" + jackson_version = "2.6.4" + jersey_version = "2.22.2" + resteasy_version = "3.1.3.Final" + {{^java8}} + jodatime_version = "2.9.4" + {{/java8}} + {{#supportJava6}} + commons_io_version=2.5 + commons_lang3_version=3.5 + {{/supportJava6}} + junit_version = "4.12" +} + +dependencies { + compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "org.jboss.resteasy:resteasy-client:$resteasy_version" + compile "org.jboss.resteasy:resteasy-multipart-provider:$resteasy_version" + compile "org.jboss.resteasy:resteasy-jackson2-provider:$resteasy_version" + compile "org.glassfish.jersey.core:jersey-client:$jersey_version" + compile "org.glassfish.jersey.media:jersey-media-multipart:$jersey_version" + compile "org.glassfish.jersey.media:jersey-media-json-jackson:$jersey_version" + compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_version" + {{#java8}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{/java8}} + {{^java8}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + compile "joda-time:joda-time:$jodatime_version" + compile "com.brsanthu:migbase64:2.2" + {{/java8}} + {{#supportJava6}} + compile "commons-io:commons-io:$commons_io_version" + compile "org.apache.commons:commons-lang3:$commons_lang3_version" + {{/supportJava6}} + testCompile "junit:junit:$junit_version" +} diff --git a/libraries/resteasy/build.sbt.mustache b/libraries/resteasy/build.sbt.mustache new file mode 100644 index 00000000000..348d29d96d1 --- /dev/null +++ b/libraries/resteasy/build.sbt.mustache @@ -0,0 +1,34 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "io.swagger" % "swagger-annotations" % "1.5.8", + "org.glassfish.jersey.core" % "jersey-client" % "2.22.2", + "org.glassfish.jersey.media" % "jersey-media-multipart" % "2.22.2", + "org.glassfish.jersey.media" % "jersey-media-json-jackson" % "2.22.2", + "com.fasterxml.jackson.core" % "jackson-core" % "2.7.5", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.7.5", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.7.5", + {{#java8}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.7.5", + {{/java8}} + {{^java8}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.7.5", + "joda-time" % "joda-time" % "2.9.4", + "com.brsanthu" % "migbase64" % "2.2", + {{/java8}} + {{#supportJava6}} + "org.apache.commons" % "commons-lang3" % "3.5", + "commons-io" % "commons-io" % "2.5", + {{/supportJava6}} + "junit" % "junit" % "4.12" % "test", + "com.novocode" % "junit-interface" % "0.10" % "test" + ) + ) diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache new file mode 100644 index 00000000000..2b4a9aa5537 --- /dev/null +++ b/libraries/resteasy/pom.mustache @@ -0,0 +1,263 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + + scm:git:git@github.com:swagger-api/swagger-mustache.git + scm:git:git@github.com:swagger-api/swagger-codegen.git + https://github.com/swagger-api/swagger-codegen + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.6 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.5.1 + + {{#java8}} + + 1.8 + 1.8 + {{/java8}} + {{^java8}} + + 1.7 + 1.7 + {{/java8}} + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + + + + + io.swagger + swagger-annotations + ${swagger-core-version} + + + + org.jboss.resteasy + resteasy-client + ${resteasy-version} + + + org.jboss.resteasy + resteasy-multipart-provider + ${resteasy-version} + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-version} + + {{#withXml}} + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson-version} + + + {{/withXml}} + {{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{/java8}} + {{^java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + + joda-time + joda-time + ${jodatime-version} + + + + + com.brsanthu + migbase64 + 2.2 + + {{/java8}} + + {{#supportJava6}} + + org.apache.commons + commons-lang3 + ${commons_lang3_version} + + + + commons-io + commons-io + ${commons_io_version} + + {{/supportJava6}} + + org.jboss.resteasy + resteasy-jackson2-provider + 3.1.3.Final + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${jackson-version} + + + + junit + junit + ${junit-version} + test + + + + UTF-8 + 1.5.18 + 3.1.3.Final + 2.6.4 + {{^java8}} + 2.9.9 + {{/java8}} + {{#supportJava6}} + 2.5 + 3.6 + {{/supportJava6}} + 1.0.0 + 4.12 + + diff --git a/libraries/resttemplate/ApiClient.mustache b/libraries/resttemplate/ApiClient.mustache new file mode 100644 index 00000000000..54f2b14573b --- /dev/null +++ b/libraries/resttemplate/ApiClient.mustache @@ -0,0 +1,678 @@ +package {{invokerPackage}}; + +{{#withXml}} +import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; +{{/withXml}} +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpRequest; +import org.springframework.http.HttpStatus; +import org.springframework.http.InvalidMediaTypeException; +import org.springframework.http.MediaType; +import org.springframework.http.RequestEntity; +import org.springframework.http.RequestEntity.BodyBuilder; +import org.springframework.http.ResponseEntity; +import org.springframework.http.client.BufferingClientHttpRequestFactory; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.http.client.ClientHttpResponse; +{{#withXml}} +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter; +{{/withXml}} +import org.springframework.stereotype.Component; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.util.StringUtils; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; +{{#threetenbp}} +import org.threeten.bp.*; +import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter; +import com.fasterxml.jackson.databind.ObjectMapper; +{{/threetenbp}} + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; +import java.text.DateFormat; +import java.text.ParseException; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TimeZone; + +import {{invokerPackage}}.auth.Authentication; +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.OAuth; + +{{>generatedAnnotation}} +@Component("{{invokerPackage}}.ApiClient") +public class ApiClient { + public enum CollectionFormat { + CSV(","), TSV("\t"), SSV(" "), PIPES("|"), MULTI(null); + + private final String separator; + private CollectionFormat(String separator) { + this.separator = separator; + } + + private String collectionToString(Collection collection) { + return StringUtils.collectionToDelimitedString(collection, separator); + } + } + + private boolean debugging = false; + + private HttpHeaders defaultHeaders = new HttpHeaders(); + + private String basePath = "{{basePath}}"; + + private RestTemplate restTemplate; + + private Map authentications; + + private HttpStatus statusCode; + private MultiValueMap responseHeaders; + + private DateFormat dateFormat; + + public ApiClient() { + this.restTemplate = buildRestTemplate(); + init(); + } + + @Autowired + public ApiClient(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + init(); + } + + protected void init() { + // Use RFC3339 format for date and datetime. + // See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14 + this.dateFormat = new RFC3339DateFormat(); + + // Use UTC as the default time zone. + this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + + // Set default User-Agent. + setUserAgent("Java-SDK"); + + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap();{{#authMethods}}{{#isBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + } + + /** + * Get the current base path + * @return String the base path + */ + public String getBasePath() { + return basePath; + } + + /** + * Set the base path, which should include the host + * @param basePath the base path + * @return ApiClient this client + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Gets the status code of the previous request + * @return HttpStatus the status code + */ + public HttpStatus getStatusCode() { + return statusCode; + } + + /** + * Gets the response headers of the previous request + * @return MultiValueMap a map of response headers + */ + public MultiValueMap getResponseHeaders() { + return responseHeaders; + } + + /** + * Get authentications (key: authentication name, value: authentication). + * @return Map the currently configured authentication types + */ + public Map getAuthentications() { + return authentications; + } + + /** + * Get authentication for the given name. + * + * @param authName The authentication name + * @return The authentication, null if not found + */ + public Authentication getAuthentication(String authName) { + return authentications.get(authName); + } + + /** + * Helper method to set username for the first HTTP basic authentication. + * @param username the username + */ + public void setUsername(String username) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setUsername(username); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set password for the first HTTP basic authentication. + * @param password the password + */ + public void setPassword(String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setPassword(password); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set API key value for the first API key authentication. + * @param apiKey the API key + */ + public void setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + * @param apiKeyPrefix the API key prefix + */ + public void setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set access token for the first OAuth2 authentication. + * @param accessToken the access token + */ + public void setAccessToken(String accessToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setAccessToken(accessToken); + return; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Set the User-Agent header's value (by adding to the default header map). + * @param userAgent the user agent string + * @return ApiClient this client + */ + public ApiClient setUserAgent(String userAgent) { + addDefaultHeader("User-Agent", userAgent); + return this; + } + + /** + * Add a default header. + * + * @param name The header's name + * @param value The header's value + * @return ApiClient this client + */ + public ApiClient addDefaultHeader(String name, String value) { + if (defaultHeaders.containsKey(name)) { + defaultHeaders.remove(name); + } + defaultHeaders.add(name, value); + return this; + } + + public void setDebugging(boolean debugging) { + List currentInterceptors = this.restTemplate.getInterceptors(); + if(debugging) { + if (currentInterceptors == null) { + currentInterceptors = new ArrayList(); + } + ClientHttpRequestInterceptor interceptor = new ApiClientHttpRequestInterceptor(); + currentInterceptors.add(interceptor); + this.restTemplate.setInterceptors(currentInterceptors); + } else { + if (currentInterceptors != null && !currentInterceptors.isEmpty()) { + Iterator iter = currentInterceptors.iterator(); + while (iter.hasNext()) { + ClientHttpRequestInterceptor interceptor = iter.next(); + if (interceptor instanceof ApiClientHttpRequestInterceptor) { + iter.remove(); + } + } + this.restTemplate.setInterceptors(currentInterceptors); + } + } + this.debugging = debugging; + } + + /** + * Check that whether debugging is enabled for this API client. + * @return boolean true if this client is enabled for debugging, false otherwise + */ + public boolean isDebugging() { + return debugging; + } + + /** + * Get the date format used to parse/format date parameters. + * @return DateFormat format + */ + public DateFormat getDateFormat() { + return dateFormat; + } + + /** + * Set the date format used to parse/format date parameters. + * @param dateFormat Date format + * @return API client + */ + public ApiClient setDateFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + {{#threetenbp}} + for(HttpMessageConverter converter:restTemplate.getMessageConverters()){ + if(converter instanceof AbstractJackson2HttpMessageConverter){ + ObjectMapper mapper = ((AbstractJackson2HttpMessageConverter)converter).getObjectMapper(); + mapper.setDateFormat(dateFormat); + } + } + {{/threetenbp}} + return this; + } + + /** + * Parse the given string into Date object. + */ + public Date parseDate(String str) { + try { + return dateFormat.parse(str); + } catch (ParseException e) { + throw new RuntimeException(e); + } + } + + /** + * Format the given Date object into string. + */ + public String formatDate(Date date) { + return dateFormat.format(date); + } + + /** + * Format the given parameter object into string. + * @param param the object to convert + * @return String the parameter represented as a String + */ + public String parameterToString(Object param) { + if (param == null) { + return ""; + } else if (param instanceof Date) { + return formatDate( (Date) param); + } else if (param instanceof Collection) { + StringBuilder b = new StringBuilder(); + for(Object o : (Collection) param) { + if(b.length() > 0) { + b.append(","); + } + b.append(String.valueOf(o)); + } + return b.toString(); + } else { + return String.valueOf(param); + } + } + + /** + * Converts a parameter to a {@link MultiValueMap} for use in REST requests + * @param collectionFormat The format to convert to + * @param name The name of the parameter + * @param value The parameter's value + * @return a Map containing the String value(s) of the input parameter + */ + public MultiValueMap parameterToMultiValueMap(CollectionFormat collectionFormat, String name, Object value) { + final MultiValueMap params = new LinkedMultiValueMap(); + + if (name == null || name.isEmpty() || value == null) { + return params; + } + + if(collectionFormat == null) { + collectionFormat = CollectionFormat.CSV; + } + + Collection valueCollection = null; + if (value instanceof Collection) { + valueCollection = (Collection) value; + } else { + params.add(name, parameterToString(value)); + return params; + } + + if (valueCollection.isEmpty()){ + return params; + } + + if (collectionFormat.equals(CollectionFormat.MULTI)) { + for (Object item : valueCollection) { + params.add(name, parameterToString(item)); + } + return params; + } + + List values = new ArrayList(); + for(Object o : valueCollection) { + values.add(parameterToString(o)); + } + params.add(name, collectionFormat.collectionToString(values)); + + return params; + } + + /** + * Check if the given {@code String} is a JSON MIME. + * @param mediaType the input MediaType + * @return boolean true if the MediaType represents JSON, false otherwise + */ + public boolean isJsonMime(String mediaType) { + // "* / *" is default to JSON + if ("*/*".equals(mediaType)) { + return true; + } + + try { + return isJsonMime(MediaType.parseMediaType(mediaType)); + } catch (InvalidMediaTypeException e) { + } + return false; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * @param mediaType the input MediaType + * @return boolean true if the MediaType represents JSON, false otherwise + */ + public boolean isJsonMime(MediaType mediaType) { + return mediaType != null && (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType) || mediaType.getSubtype().matches("^.*\\+json[;]?\\s*$")); + } + + /** + * Select the Accept header's value from the given accepts array: + * if JSON exists in the given array, use it; + * otherwise use all of them (joining into a string) + * + * @param accepts The accepts array to select from + * @return List The list of MediaTypes to use for the Accept header + */ + public List selectHeaderAccept(String[] accepts) { + if (accepts.length == 0) { + return null; + } + for (String accept : accepts) { + MediaType mediaType = MediaType.parseMediaType(accept); + if (isJsonMime(mediaType)) { + return Collections.singletonList(mediaType); + } + } + return MediaType.parseMediaTypes(StringUtils.arrayToCommaDelimitedString(accepts)); + } + + /** + * Select the Content-Type header's value from the given array: + * if JSON exists in the given array, use it; + * otherwise use the first one of the array. + * + * @param contentTypes The Content-Type array to select from + * @return MediaType The Content-Type header to use. If the given array is empty, JSON will be used. + */ + public MediaType selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0) { + return MediaType.APPLICATION_JSON; + } + for (String contentType : contentTypes) { + MediaType mediaType = MediaType.parseMediaType(contentType); + if (isJsonMime(mediaType)) { + return mediaType; + } + } + return MediaType.parseMediaType(contentTypes[0]); + } + + /** + * Select the body to use for the request + * @param obj the body object + * @param formParams the form parameters + * @param contentType the content type of the request + * @return Object the selected body + */ + protected Object selectBody(Object obj, MultiValueMap formParams, MediaType contentType) { + boolean isForm = MediaType.MULTIPART_FORM_DATA.isCompatibleWith(contentType) || MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(contentType); + return isForm ? formParams : obj; + } + + /** + * Invoke API by sending HTTP request with the given options. + * + * @param the return type to use + * @param path The sub-path of the HTTP URL + * @param method The request method + * @param queryParams The query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param formParams The form parameters + * @param accept The request's Accept header + * @param contentType The request's Content-Type header + * @param authNames The authentications to apply + * @param returnType The return type into which to deserialize the response + * @return The response body in chosen type + */ + public T invokeAPI(String path, HttpMethod method, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { + updateParamsForAuth(authNames, queryParams, headerParams); + + final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(path); + if (queryParams != null) { + builder.queryParams(queryParams); + } + + final BodyBuilder requestBuilder = RequestEntity.method(method, builder.build().toUri()); + if(accept != null) { + requestBuilder.accept(accept.toArray(new MediaType[accept.size()])); + } + if(contentType != null) { + requestBuilder.contentType(contentType); + } + + addHeadersToRequest(headerParams, requestBuilder); + addHeadersToRequest(defaultHeaders, requestBuilder); + + RequestEntity requestEntity = requestBuilder.body(selectBody(body, formParams, contentType)); + + ResponseEntity responseEntity = restTemplate.exchange(requestEntity, returnType); + + statusCode = responseEntity.getStatusCode(); + responseHeaders = responseEntity.getHeaders(); + + if (responseEntity.getStatusCode() == HttpStatus.NO_CONTENT) { + return null; + } else if (responseEntity.getStatusCode().is2xxSuccessful()) { + if (returnType == null) { + return null; + } + return responseEntity.getBody(); + } else { + // The error handler built into the RestTemplate should handle 400 and 500 series errors. + throw new RestClientException("API returned " + statusCode + " and it wasn't handled by the RestTemplate error handler"); + } + } + + /** + * Add headers to the request that is being built + * @param headers The headers to add + * @param requestBuilder The current request + */ + protected void addHeadersToRequest(HttpHeaders headers, BodyBuilder requestBuilder) { + for (Entry> entry : headers.entrySet()) { + List values = entry.getValue(); + for(String value : values) { + if (value != null) { + requestBuilder.header(entry.getKey(), value); + } + } + } + } + + /** + * Build the RestTemplate used to make HTTP requests. + * @return RestTemplate + */ + protected RestTemplate buildRestTemplate() { + {{#withXml}}List> messageConverters = new ArrayList>(); + messageConverters.add(new MappingJackson2HttpMessageConverter()); + XmlMapper xmlMapper = new XmlMapper(); + xmlMapper.configure(ToXmlGenerator.Feature.WRITE_XML_DECLARATION, true); + messageConverters.add(new MappingJackson2XmlHttpMessageConverter(xmlMapper)); + + RestTemplate restTemplate = new RestTemplate(messageConverters); + {{/withXml}}{{^withXml}}RestTemplate restTemplate = new RestTemplate();{{/withXml}} + {{#threetenbp}} + for(HttpMessageConverter converter:restTemplate.getMessageConverters()){ + if(converter instanceof AbstractJackson2HttpMessageConverter){ + ObjectMapper mapper = ((AbstractJackson2HttpMessageConverter)converter).getObjectMapper(); + ThreeTenModule module = new ThreeTenModule(); + module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); + module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); + module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); + mapper.registerModule(module); + } + } + {{/threetenbp}} + // This allows us to read the response more than once - Necessary for debugging. + restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(restTemplate.getRequestFactory())); + return restTemplate; + } + + /** + * Update query and header parameters based on authentication settings. + * + * @param authNames The authentications to apply + * @param queryParams The query parameters + * @param headerParams The header parameters + */ + private void updateParamsForAuth(String[] authNames, MultiValueMap queryParams, HttpHeaders headerParams) { + for (String authName : authNames) { + Authentication auth = authentications.get(authName); + if (auth == null) { + throw new RestClientException("Authentication undefined: " + authName); + } + auth.applyToParams(queryParams, headerParams); + } + } + + private class ApiClientHttpRequestInterceptor implements ClientHttpRequestInterceptor { + private final Log log = LogFactory.getLog(ApiClientHttpRequestInterceptor.class); + + @Override + public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { + logRequest(request, body); + ClientHttpResponse response = execution.execute(request, body); + logResponse(response); + return response; + } + + private void logRequest(HttpRequest request, byte[] body) throws UnsupportedEncodingException { + log.info("URI: " + request.getURI()); + log.info("HTTP Method: " + request.getMethod()); + log.info("HTTP Headers: " + headersToString(request.getHeaders())); + log.info("Request Body: " + new String(body, StandardCharsets.UTF_8)); + } + + private void logResponse(ClientHttpResponse response) throws IOException { + log.info("HTTP Status Code: " + response.getRawStatusCode()); + log.info("Status Text: " + response.getStatusText()); + log.info("HTTP Headers: " + headersToString(response.getHeaders())); + log.info("Response Body: " + bodyToString(response.getBody())); + } + + private String headersToString(HttpHeaders headers) { + StringBuilder builder = new StringBuilder(); + for(Entry> entry : headers.entrySet()) { + builder.append(entry.getKey()).append("=["); + for(String value : entry.getValue()) { + builder.append(value).append(","); + } + builder.setLength(builder.length() - 1); // Get rid of trailing comma + builder.append("],"); + } + builder.setLength(builder.length() - 1); // Get rid of trailing comma + return builder.toString(); + } + + private String bodyToString(InputStream body) throws IOException { + StringBuilder builder = new StringBuilder(); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(body, StandardCharsets.UTF_8)); + String line = bufferedReader.readLine(); + while (line != null) { + builder.append(line).append(System.lineSeparator()); + line = bufferedReader.readLine(); + } + bufferedReader.close(); + return builder.toString(); + } + } +} diff --git a/libraries/resttemplate/api.mustache b/libraries/resttemplate/api.mustache new file mode 100644 index 00000000000..f48180f4381 --- /dev/null +++ b/libraries/resttemplate/api.mustache @@ -0,0 +1,107 @@ +package {{package}}; + +import {{invokerPackage}}.ApiClient; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}}import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map;{{/fullJavaUtil}} + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.util.UriComponentsBuilder; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.core.io.FileSystemResource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; + +{{>generatedAnnotation}} +@Component("{{package}}.{{classname}}") +{{#operations}} +public class {{classname}} { + private ApiClient {{localVariablePrefix}}apiClient; + + public {{classname}}() { + this(new ApiClient()); + } + + @Autowired + public {{classname}}(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + public ApiClient getApiClient() { + return {{localVariablePrefix}}apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + {{#operation}} + /** + * {{summary}} + * {{notes}} +{{#responses}} *

{{code}}{{#message}} - {{message}}{{/message}} +{{/responses}}{{#allParams}} * @param {{paramName}} {{description}}{{^description}}The {{paramName}} parameter{{/description}} +{{/allParams}}{{#returnType}} * @return {{returnType}} +{{/returnType}} * @throws RestClientException if an error occurs while attempting to invoke the API +{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation +{{/externalDocs}} + */ + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { + Object {{localVariablePrefix}}postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + } + {{/required}}{{/allParams}}{{#hasPathParams}} + // create path and map variables + final Map uriVariables = new HashMap();{{#pathParams}} + uriVariables.put("{{baseName}}", {{{paramName}}});{{/pathParams}}{{/hasPathParams}} + String {{localVariablePrefix}}path = UriComponentsBuilder.fromPath("{{{path}}}"){{#hasPathParams}}.buildAndExpand(uriVariables){{/hasPathParams}}{{^hasPathParams}}.build(){{/hasPathParams}}.toUriString(); + + final MultiValueMap {{localVariablePrefix}}queryParams = new LinkedMultiValueMap(); + final HttpHeaders {{localVariablePrefix}}headerParams = new HttpHeaders(); + final MultiValueMap {{localVariablePrefix}}formParams = new LinkedMultiValueMap();{{#hasQueryParams}} + + {{#queryParams}}{{localVariablePrefix}}queryParams.putAll({{localVariablePrefix}}apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase()){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{#hasMore}} + {{/hasMore}}{{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}} + + {{#headerParams}}if ({{paramName}} != null) + {{localVariablePrefix}}headerParams.add("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}}));{{#hasMore}} + {{/hasMore}}{{/headerParams}}{{/hasHeaderParams}}{{#hasFormParams}} + + {{#formParams}}if ({{paramName}} != null) + {{localVariablePrefix}}formParams.add("{{baseName}}", {{#isFile}}new FileSystemResource({{paramName}}){{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} + {{/hasMore}}{{/formParams}}{{/hasFormParams}} + + final String[] {{localVariablePrefix}}accepts = { {{#hasProduces}} + {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} + {{/hasProduces}}}; + final List {{localVariablePrefix}}accept = {{localVariablePrefix}}apiClient.selectHeaderAccept({{localVariablePrefix}}accepts); + final String[] {{localVariablePrefix}}contentTypes = { {{#hasConsumes}} + {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} + {{/hasConsumes}}}; + final MediaType {{localVariablePrefix}}contentType = {{localVariablePrefix}}apiClient.selectHeaderContentType({{localVariablePrefix}}contentTypes); + + String[] {{localVariablePrefix}}authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + + {{#returnType}}ParameterizedTypeReference<{{{returnType}}}> {{localVariablePrefix}}returnType = new ParameterizedTypeReference<{{{returnType}}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference {{localVariablePrefix}}returnType = new ParameterizedTypeReference() {};{{/returnType}} + {{#returnType}}return {{/returnType}}{{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}path, HttpMethod.{{httpMethod}}, {{localVariablePrefix}}queryParams, {{localVariablePrefix}}postBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames, {{localVariablePrefix}}returnType); + } + {{/operation}} +} +{{/operations}} diff --git a/libraries/resttemplate/api_test.mustache b/libraries/resttemplate/api_test.mustache new file mode 100644 index 00000000000..127ac2defc5 --- /dev/null +++ b/libraries/resttemplate/api_test.mustache @@ -0,0 +1,44 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Test; +import org.junit.Ignore; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +@Ignore +public class {{classname}}Test { + + private final {{classname}} api = new {{classname}}(); + + {{#operations}}{{#operation}} + /** + * {{summary}} + * + * {{notes}} + * + * @throws ApiException + * if the Api call fails + */ + @Test + public void {{operationId}}Test() { + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + + // TODO: test validations + } + {{/operation}}{{/operations}} +} diff --git a/libraries/resttemplate/auth/ApiKeyAuth.mustache b/libraries/resttemplate/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..8b8c40fde75 --- /dev/null +++ b/libraries/resttemplate/auth/ApiKeyAuth.mustache @@ -0,0 +1,60 @@ +package {{invokerPackage}}.auth; + +import org.springframework.http.HttpHeaders; +import org.springframework.util.MultiValueMap; + +{{>generatedAnnotation}} +public class ApiKeyAuth implements Authentication { + private final String location; + private final String paramName; + + private String apiKey; + private String apiKeyPrefix; + + public ApiKeyAuth(String location, String paramName) { + this.location = location; + this.paramName = paramName; + } + + public String getLocation() { + return location; + } + + public String getParamName() { + return paramName; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + public String getApiKeyPrefix() { + return apiKeyPrefix; + } + + public void setApiKeyPrefix(String apiKeyPrefix) { + this.apiKeyPrefix = apiKeyPrefix; + } + + @Override + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams) { + if (apiKey == null) { + return; + } + String value; + if (apiKeyPrefix != null) { + value = apiKeyPrefix + " " + apiKey; + } else { + value = apiKey; + } + if (location.equals("query")) { + queryParams.add(paramName, value); + } else if (location.equals("header")) { + headerParams.add(paramName, value); + } + } +} diff --git a/libraries/resttemplate/auth/Authentication.mustache b/libraries/resttemplate/auth/Authentication.mustache new file mode 100644 index 00000000000..586de70836a --- /dev/null +++ b/libraries/resttemplate/auth/Authentication.mustache @@ -0,0 +1,13 @@ +package {{invokerPackage}}.auth; + +import org.springframework.http.HttpHeaders; +import org.springframework.util.MultiValueMap; + +public interface Authentication { + /** + * Apply authentication settings to header and / or query parameters. + * @param queryParams The query parameters for the request + * @param headerParams The header parameters for the request + */ + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams); +} diff --git a/libraries/resttemplate/auth/HttpBasicAuth.mustache b/libraries/resttemplate/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..5f535b3698a --- /dev/null +++ b/libraries/resttemplate/auth/HttpBasicAuth.mustache @@ -0,0 +1,39 @@ +package {{invokerPackage}}.auth; + +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; + +import org.springframework.http.HttpHeaders; +import org.springframework.util.Base64Utils; +import org.springframework.util.MultiValueMap; + +{{>generatedAnnotation}} +public class HttpBasicAuth implements Authentication { + private String username; + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams) { + if (username == null && password == null) { + return; + } + String str = (username == null ? "" : username) + ":" + (password == null ? "" : password); + headerParams.add(HttpHeaders.AUTHORIZATION, "Basic " + Base64Utils.encodeToString(str.getBytes(StandardCharsets.UTF_8))); + } +} diff --git a/libraries/resttemplate/auth/OAuth.mustache b/libraries/resttemplate/auth/OAuth.mustache new file mode 100644 index 00000000000..fbb2f7f9c72 --- /dev/null +++ b/libraries/resttemplate/auth/OAuth.mustache @@ -0,0 +1,24 @@ +package {{invokerPackage}}.auth; + +import org.springframework.http.HttpHeaders; +import org.springframework.util.MultiValueMap; + +{{>generatedAnnotation}} +public class OAuth implements Authentication { + private String accessToken; + + public String getAccessToken() { + return accessToken; + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + @Override + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams) { + if (accessToken != null) { + headerParams.add(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken); + } + } +} diff --git a/libraries/resttemplate/auth/OAuthFlow.mustache b/libraries/resttemplate/auth/OAuthFlow.mustache new file mode 100644 index 00000000000..7ab35f6d890 --- /dev/null +++ b/libraries/resttemplate/auth/OAuthFlow.mustache @@ -0,0 +1,5 @@ +package {{invokerPackage}}.auth; + +public enum OAuthFlow { + accessCode, implicit, password, application +} \ No newline at end of file diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache new file mode 100644 index 00000000000..e4fc1caa4f0 --- /dev/null +++ b/libraries/resttemplate/build.gradle.mustache @@ -0,0 +1,140 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.5.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 23 + buildToolsVersion '23.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 22 + } + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + {{#java8}} + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + {{/java8}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + swagger_annotations_version = "1.5.17" + jackson_version = "2.8.9" + spring_web_version = "4.3.9.RELEASE" + jodatime_version = "2.9.9" + junit_version = "4.12" + {{#threetenbp}} + jackson_threeten_version = "2.6.4" + {{/threetenbp}} +} + +dependencies { + compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "org.springframework:spring-web:$spring_web_version" + compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + {{#java8}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{/java8}} + {{#joda}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + compile "joda-time:joda-time:$jodatime_version" + {{/joda}} + {{#threetenbp}} + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threeten_version" + {{/threetenbp}} + {{#withXml}} + compile "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jackson_version" + {{/withXml}} + testCompile "junit:junit:$junit_version" +} diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache new file mode 100644 index 00000000000..e2bdc3a8b68 --- /dev/null +++ b/libraries/resttemplate/pom.mustache @@ -0,0 +1,301 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{artifactUrl}} + {{artifactDescription}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + {{#java8}} + + 1.8 + 1.8 + {{/java8}} + {{^java8}} + + 1.7 + 1.7 + {{/java8}} + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-annotations-version} + + + + + org.springframework + spring-web + ${spring-web-version} + + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-version} + + + com.fasterxml.jackson.jaxrs + jackson-jaxrs-json-provider + ${jackson-version} + + {{#withXml}} + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson-version} + + + {{/withXml}} + {{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{/java8}} + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + + joda-time + joda-time + ${jodatime-version} + + {{/joda}} + {{#threetenbp}} + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${jackson-threetenbp-version} + + {{/threetenbp}} + + + + junit + junit + ${junit-version} + test + + + + UTF-8 + 1.5.17 + 4.3.9.RELEASE + 2.8.9 + {{#joda}} + 2.9.9 + {{/joda}} + {{#threetenbp}} + 2.6.4 + {{/threetenbp}} + 1.0.0 + 4.12 + + diff --git a/libraries/retrofit/ApiClient.mustache b/libraries/retrofit/ApiClient.mustache new file mode 100644 index 00000000000..7c45e926bcf --- /dev/null +++ b/libraries/retrofit/ApiClient.mustache @@ -0,0 +1,418 @@ +package {{invokerPackage}}; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Type; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; +import org.joda.time.DateTime; +import org.joda.time.LocalDate; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.ISODateTimeFormat; + +import retrofit.RestAdapter; +import retrofit.client.OkClient; +import retrofit.converter.ConversionException; +import retrofit.converter.Converter; +import retrofit.converter.GsonConverter; +import retrofit.mime.TypedByteArray; +import retrofit.mime.TypedInput; +import retrofit.mime.TypedOutput; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonParseException; +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import com.squareup.okhttp.Interceptor; +import com.squareup.okhttp.OkHttpClient; + +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.OAuth; +import {{invokerPackage}}.auth.OAuth.AccessTokenListener; +import {{invokerPackage}}.auth.OAuthFlow; + + +public class ApiClient { + + private Map apiAuthorizations; + private OkHttpClient okClient; + private RestAdapter.Builder adapterBuilder; + + public ApiClient() { + apiAuthorizations = new LinkedHashMap(); + createDefaultAdapter(); + } + + public ApiClient(String[] authNames) { + this(); + for(String authName : authNames) { + {{#hasAuthMethods}} + Interceptor auth; + {{#authMethods}}if ("{{name}}".equals(authName)) { + {{#isBasic}} + auth = new HttpBasicAuth(); + {{/isBasic}} + {{#isApiKey}} + auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}");{{/isApiKey}} + {{#isOAuth}} + auth = new OAuth(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{#hasMore}}, {{/hasMore}}{{/scopes}}"); + {{/isOAuth}} + } else {{/authMethods}}{ + throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); + } + addAuthorization(authName, auth); + {{/hasAuthMethods}} + {{^hasAuthMethods}} + throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); + {{/hasAuthMethods}} + } + } + + /** + * Basic constructor for single auth name + * @param authName Authentication name + */ + public ApiClient(String authName) { + this(new String[]{authName}); + } + + /** + * Helper constructor for single api key + * @param authName Authentication name + * @param apiKey API key + */ + public ApiClient(String authName, String apiKey) { + this(authName); + this.setApiKey(apiKey); + } + + /** + * Helper constructor for single basic auth or password oauth2 + * @param authName Authentication name + * @param username Username + * @param password Password + */ + public ApiClient(String authName, String username, String password) { + this(authName); + this.setCredentials(username, password); + } + + /** + * Helper constructor for single password oauth2 + * @param authName Authentication name + * @param clientId Client ID + * @param secret Client secret + * @param username Username + * @param password Password + */ + public ApiClient(String authName, String clientId, String secret, String username, String password) { + this(authName); + this.getTokenEndPoint() + .setClientId(clientId) + .setClientSecret(secret) + .setUsername(username) + .setPassword(password); + } + + public void createDefaultAdapter() { + Gson gson = new GsonBuilder() + .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ") + .registerTypeAdapter(DateTime.class, new DateTimeTypeAdapter()) + .registerTypeAdapter(LocalDate.class, new LocalDateTypeAdapter()) + .create(); + + okClient = new OkHttpClient(); + + adapterBuilder = new RestAdapter + .Builder() + .setEndpoint("{{{basePath}}}") + .setClient(new OkClient(okClient)) + .setConverter(new GsonConverterWrapper(gson)); + } + + public S createService(Class serviceClass) { + return adapterBuilder.build().create(serviceClass); + + } + + /** + * Helper method to configure the first api key found + * @param apiKey API key + */ + private void setApiKey(String apiKey) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof ApiKeyAuth) { + ApiKeyAuth keyAuth = (ApiKeyAuth) apiAuthorization; + keyAuth.setApiKey(apiKey); + return; + } + } + } + + /** + * Helper method to configure the username/password for basic auth or password oauth + * @param username Username + * @param password Password + */ + private void setCredentials(String username, String password) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof HttpBasicAuth) { + HttpBasicAuth basicAuth = (HttpBasicAuth) apiAuthorization; + basicAuth.setCredentials(username, password); + return; + } + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.getTokenRequestBuilder().setUsername(username).setPassword(password); + return; + } + } + } + + /** + * Helper method to configure the token endpoint of the first oauth found in the apiAuthorizations (there should be only one) + * @return Token request builder + */ + public TokenRequestBuilder getTokenEndPoint() { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + return oauth.getTokenRequestBuilder(); + } + } + return null; + } + + /** + * Helper method to configure authorization endpoint of the first oauth found in the apiAuthorizations (there should be only one) + * @return Authentication request builder + */ + public AuthenticationRequestBuilder getAuthorizationEndPoint() { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + return oauth.getAuthenticationRequestBuilder(); + } + } + return null; + } + + /** + * Helper method to pre-set the oauth access token of the first oauth found in the apiAuthorizations (there should be only one) + * @param accessToken Access token + */ + public void setAccessToken(String accessToken) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.setAccessToken(accessToken); + return; + } + } + } + + /** + * Helper method to configure the oauth accessCode/implicit flow parameters + * @param clientId Client ID + * @param clientSecret Client secret + * @param redirectURI Redirect URI + */ + public void configureAuthorizationFlow(String clientId, String clientSecret, String redirectURI) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.getTokenRequestBuilder() + .setClientId(clientId) + .setClientSecret(clientSecret) + .setRedirectURI(redirectURI); + oauth.getAuthenticationRequestBuilder() + .setClientId(clientId) + .setRedirectURI(redirectURI); + return; + } + } + } + + /** + * Configures a listener which is notified when a new access token is received. + * @param accessTokenListener Access token listener + */ + public void registerAccessTokenListener(AccessTokenListener accessTokenListener) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.registerAccessTokenListener(accessTokenListener); + return; + } + } + } + + /** + * Adds an authorization to be used by the client + * @param authName Authentication name + * @param authorization Authorization + */ + public void addAuthorization(String authName, Interceptor authorization) { + if (apiAuthorizations.containsKey(authName)) { + throw new RuntimeException("auth name \"" + authName + "\" already in api authorizations"); + } + apiAuthorizations.put(authName, authorization); + okClient.interceptors().add(authorization); + } + + public Map getApiAuthorizations() { + return apiAuthorizations; + } + + public void setApiAuthorizations(Map apiAuthorizations) { + this.apiAuthorizations = apiAuthorizations; + } + + public RestAdapter.Builder getAdapterBuilder() { + return adapterBuilder; + } + + public void setAdapterBuilder(RestAdapter.Builder adapterBuilder) { + this.adapterBuilder = adapterBuilder; + } + + public OkHttpClient getOkClient() { + return okClient; + } + + public void addAuthsToOkClient(OkHttpClient okClient) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + okClient.interceptors().add(apiAuthorization); + } + } + + /** + * Clones the okClient given in parameter, adds the auth interceptors and uses it to configure the RestAdapter + * @param okClient OkHttp client + */ + public void configureFromOkclient(OkHttpClient okClient) { + OkHttpClient clone = okClient.clone(); + addAuthsToOkClient(clone); + adapterBuilder.setClient(new OkClient(clone)); + } +} + +/** + * This wrapper is to take care of this case: + * when the deserialization fails due to JsonParseException and the + * expected type is String, then just return the body string. + */ +class GsonConverterWrapper implements Converter { + private GsonConverter converter; + + public GsonConverterWrapper(Gson gson) { + converter = new GsonConverter(gson); + } + + @Override public Object fromBody(TypedInput body, Type type) throws ConversionException { + byte[] bodyBytes = readInBytes(body); + TypedByteArray newBody = new TypedByteArray(body.mimeType(), bodyBytes); + try { + return converter.fromBody(newBody, type); + } catch (ConversionException e) { + if (e.getCause() instanceof JsonParseException && type.equals(String.class)) { + return new String(bodyBytes); + } else { + throw e; + } + } + } + + @Override public TypedOutput toBody(Object object) { + return converter.toBody(object); + } + + private byte[] readInBytes(TypedInput body) throws ConversionException { + InputStream in = null; + try { + in = body.in(); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + byte[] buffer = new byte[0xFFFF]; + for (int len; (len = in.read(buffer)) != -1;) + os.write(buffer, 0, len); + os.flush(); + return os.toByteArray(); + } catch (IOException e) { + throw new ConversionException(e); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException ignored) { + } + } + } + + } +} + +/** + * Gson TypeAdapter for Joda DateTime type + */ +class DateTimeTypeAdapter extends TypeAdapter { + + private final DateTimeFormatter parseFormatter = ISODateTimeFormat.dateOptionalTimeParser(); + private final DateTimeFormatter printFormatter = ISODateTimeFormat.dateTime(); + + @Override + public void write(JsonWriter out, DateTime date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(printFormatter.print(date)); + } + } + + @Override + public DateTime read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + return parseFormatter.parseDateTime(date); + } + } +} + +/** + * Gson TypeAdapter for Joda DateTime type + */ +class LocalDateTypeAdapter extends TypeAdapter { + + private final DateTimeFormatter formatter = ISODateTimeFormat.date(); + + @Override + public void write(JsonWriter out, LocalDate date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.print(date)); + } + } + + @Override + public LocalDate read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + return formatter.parseLocalDate(date); + } + } +} diff --git a/libraries/retrofit/CollectionFormats.mustache b/libraries/retrofit/CollectionFormats.mustache new file mode 100644 index 00000000000..a549ea59d1c --- /dev/null +++ b/libraries/retrofit/CollectionFormats.mustache @@ -0,0 +1,95 @@ +package {{invokerPackage}}; + +import java.util.Arrays; +import java.util.List; + +public class CollectionFormats { + + public static class CSVParams { + + protected List params; + + public CSVParams() { + } + + public CSVParams(List params) { + this.params = params; + } + + public CSVParams(String... params) { + this.params = Arrays.asList(params); + } + + public List getParams() { + return params; + } + + public void setParams(List params) { + this.params = params; + } + + @Override + public String toString() { + return StringUtil.join(params.toArray(new String[0]), ","); + } + + } + + public static class SSVParams extends CSVParams { + + public SSVParams() { + } + + public SSVParams(List params) { + super(params); + } + + public SSVParams(String... params) { + super(params); + } + + @Override + public String toString() { + return StringUtil.join(params.toArray(new String[0]), " "); + } + } + + public static class TSVParams extends CSVParams { + + public TSVParams() { + } + + public TSVParams(List params) { + super(params); + } + + public TSVParams(String... params) { + super(params); + } + + @Override + public String toString() { + return StringUtil.join( params.toArray(new String[0]), "\t"); + } + } + + public static class PIPESParams extends CSVParams { + + public PIPESParams() { + } + + public PIPESParams(List params) { + super(params); + } + + public PIPESParams(String... params) { + super(params); + } + + @Override + public String toString() { + return StringUtil.join(params.toArray(new String[0]), "|"); + } + } + +} diff --git a/libraries/retrofit/README.mustache b/libraries/retrofit/README.mustache new file mode 100644 index 00000000000..56560172ee3 --- /dev/null +++ b/libraries/retrofit/README.mustache @@ -0,0 +1,43 @@ +# {{artifactId}} + +## Requirements + +Building the API client library requires [Maven](https://maven.apache.org/) to be installed. + +## Installation & Usage + +To install the API client library to your local Maven repository, simply execute: + +```shell +mvn install +``` + +To deploy it to a remote Maven repository instead, configure the settings of the repository and execute: + +```shell +mvn deploy +``` + +Refer to the [official documentation](https://maven.apache.org/plugins/maven-deploy-plugin/usage.html) for more information. + +After the client library is installed/deployed, you can use it in your Maven project by adding the following to your *pom.xml*: + +```xml + + {{groupId}} + {{artifactId}} + {{artifactVersion}} + compile + + +``` + +## Recommendation + +It's recommended to create an instance of `ApiClient` per thread in a multithreaded environment to avoid any potential issues. + +## Author + +{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} +{{/hasMore}}{{/apis}}{{/apiInfo}} + diff --git a/libraries/retrofit/api.mustache b/libraries/retrofit/api.mustache new file mode 100644 index 00000000000..46df0ecedf3 --- /dev/null +++ b/libraries/retrofit/api.mustache @@ -0,0 +1,62 @@ +package {{package}}; + +import {{invokerPackage}}.CollectionFormats.*; + +import retrofit.Callback; +import retrofit.http.*; +import retrofit.mime.*; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +{{#operations}} +public interface {{classname}} { + {{#operation}} + /** + * {{summary}} + * Sync method + * {{notes}} +{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} +{{/allParams}} + * @return {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}} +{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation +{{/externalDocs}} + */ + {{#formParams}}{{#-first}} + {{#isMultipart}}@retrofit.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit.http.FormUrlEncoded{{/isMultipart}}{{/-first}}{{/formParams}} + @{{httpMethod}}("{{{path}}}") + {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}} {{operationId}}({{^allParams}});{{/allParams}} + {{#allParams}}{{>libraries/retrofit/queryParams}}{{>libraries/retrofit/pathParams}}{{>libraries/retrofit/headerParams}}{{>libraries/retrofit/bodyParams}}{{>libraries/retrofit/formParams}}{{#hasMore}}, {{/hasMore}}{{^hasMore}} + );{{/hasMore}}{{/allParams}} + + /** + * {{summary}} + * Async method +{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} +{{/allParams}} + * @param cb callback method +{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation +{{/externalDocs}} + */ + {{#formParams}}{{#-first}} + {{#isMultipart}}@retrofit.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit.http.FormUrlEncoded{{/isMultipart}}{{/-first}}{{/formParams}} + @{{httpMethod}}("{{{path}}}") + void {{operationId}}( + {{#allParams}}{{>libraries/retrofit/queryParams}}{{>libraries/retrofit/pathParams}}{{>libraries/retrofit/headerParams}}{{>libraries/retrofit/bodyParams}}{{>libraries/retrofit/formParams}}, {{/allParams}}Callback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> cb + ); + {{/operation}} +} +{{/operations}} diff --git a/libraries/retrofit/api_test.mustache b/libraries/retrofit/api_test.mustache new file mode 100644 index 00000000000..a34cfe0e12b --- /dev/null +++ b/libraries/retrofit/api_test.mustache @@ -0,0 +1,44 @@ +package {{package}}; + +import {{invokerPackage}}.ApiClient; +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Before; +import org.junit.Test; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +public class {{classname}}Test { + + private {{classname}} api; + + @Before + public void setup() { + api = new ApiClient().createService({{classname}}.class); + } + + {{#operations}}{{#operation}} + /** + * {{summary}} + * + * {{notes}} + */ + @Test + public void {{operationId}}Test() { + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + // {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + + // TODO: test validations + } + {{/operation}}{{/operations}} +} diff --git a/libraries/retrofit/auth/ApiKeyAuth.mustache b/libraries/retrofit/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..f6a86f22ab4 --- /dev/null +++ b/libraries/retrofit/auth/ApiKeyAuth.mustache @@ -0,0 +1,68 @@ +package {{invokerPackage}}.auth; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import com.squareup.okhttp.Interceptor; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; + +public class ApiKeyAuth implements Interceptor { + private final String location; + private final String paramName; + + private String apiKey; + + public ApiKeyAuth(String location, String paramName) { + this.location = location; + this.paramName = paramName; + } + + public String getLocation() { + return location; + } + + public String getParamName() { + return paramName; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + @Override + public Response intercept(Chain chain) throws IOException { + String paramValue; + Request request = chain.request(); + + if ("query".equals(location)) { + String newQuery = request.uri().getQuery(); + paramValue = paramName + "=" + apiKey; + if (newQuery == null) { + newQuery = paramValue; + } else { + newQuery += "&" + paramValue; + } + + URI newUri; + try { + newUri = new URI(request.uri().getScheme(), request.uri().getAuthority(), + request.uri().getPath(), newQuery, request.uri().getFragment()); + } catch (URISyntaxException e) { + throw new IOException(e); + } + + request = request.newBuilder().url(newUri.toURL()).build(); + } else if ("header".equals(location)) { + request = request.newBuilder() + .addHeader(paramName, apiKey) + .build(); + } + return chain.proceed(request); + } +} diff --git a/libraries/retrofit/auth/HttpBasicAuth.mustache b/libraries/retrofit/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..394592f64d9 --- /dev/null +++ b/libraries/retrofit/auth/HttpBasicAuth.mustache @@ -0,0 +1,49 @@ +package {{invokerPackage}}.auth; + +import java.io.IOException; + +import com.squareup.okhttp.Credentials; +import com.squareup.okhttp.Interceptor; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; + +public class HttpBasicAuth implements Interceptor { + + private String username; + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public void setCredentials(String username, String password) { + this.username = username; + this.password = password; + } + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + + // If the request already have an authorization (eg. Basic auth), do nothing + if (request.header("Authorization") == null) { + String credentials = Credentials.basic(username, password); + request = request.newBuilder() + .addHeader("Authorization", credentials) + .build(); + } + return chain.proceed(request); + } +} diff --git a/libraries/retrofit/auth/OAuth.mustache b/libraries/retrofit/auth/OAuth.mustache new file mode 100644 index 00000000000..4c39f4e629e --- /dev/null +++ b/libraries/retrofit/auth/OAuth.mustache @@ -0,0 +1,185 @@ +package {{invokerPackage}}.auth; + +import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; +import static java.net.HttpURLConnection.HTTP_FORBIDDEN; + +import java.io.IOException; +import java.util.Map; + +import org.apache.oltu.oauth2.client.OAuthClient; +import org.apache.oltu.oauth2.client.request.OAuthBearerClientRequest; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; +import org.apache.oltu.oauth2.client.response.OAuthJSONAccessTokenResponse; +import org.apache.oltu.oauth2.common.exception.OAuthProblemException; +import org.apache.oltu.oauth2.common.exception.OAuthSystemException; +import org.apache.oltu.oauth2.common.message.types.GrantType; +import org.apache.oltu.oauth2.common.token.BasicOAuthToken; + +import com.squareup.okhttp.Interceptor; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Request.Builder; +import com.squareup.okhttp.Response; + +public class OAuth implements Interceptor { + + public interface AccessTokenListener { + public void notify(BasicOAuthToken token); + } + + private volatile String accessToken; + private OAuthClient oauthClient; + + private TokenRequestBuilder tokenRequestBuilder; + private AuthenticationRequestBuilder authenticationRequestBuilder; + + private AccessTokenListener accessTokenListener; + + public OAuth( OkHttpClient client, TokenRequestBuilder requestBuilder ) { + this.oauthClient = new OAuthClient(new OAuthOkHttpClient(client)); + this.tokenRequestBuilder = requestBuilder; + } + + public OAuth(TokenRequestBuilder requestBuilder ) { + this(new OkHttpClient(), requestBuilder); + } + + public OAuth(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { + this(OAuthClientRequest.tokenLocation(tokenUrl).setScope(scopes)); + setFlow(flow); + authenticationRequestBuilder = OAuthClientRequest.authorizationLocation(authorizationUrl); + } + + public void setFlow(OAuthFlow flow) { + switch(flow) { + case accessCode: + case implicit: + tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE); + break; + case password: + tokenRequestBuilder.setGrantType(GrantType.PASSWORD); + break; + case application: + tokenRequestBuilder.setGrantType(GrantType.CLIENT_CREDENTIALS); + break; + default: + break; + } + } + + @Override + public Response intercept(Chain chain) + throws IOException { + + return retryingIntercept(chain, true); + } + + private Response retryingIntercept(Chain chain, boolean updateTokenAndRetryOnAuthorizationFailure) throws IOException { + Request request = chain.request(); + + // If the request already have an authorization (eg. Basic auth), do nothing + if (request.header("Authorization") != null) { + return chain.proceed(request); + } + + // If first time, get the token + OAuthClientRequest oAuthRequest; + if (getAccessToken() == null) { + updateAccessToken(null); + } + + if (getAccessToken() != null) { + // Build the request + Builder rb = request.newBuilder(); + + String requestAccessToken = new String(getAccessToken()); + try { + oAuthRequest = new OAuthBearerClientRequest(request.urlString()) + .setAccessToken(requestAccessToken) + .buildHeaderMessage(); + } catch (OAuthSystemException e) { + throw new IOException(e); + } + + for ( Map.Entry header : oAuthRequest.getHeaders().entrySet() ) { + rb.addHeader(header.getKey(), header.getValue()); + } + rb.url( oAuthRequest.getLocationUri()); + + //Execute the request + Response response = chain.proceed(rb.build()); + + // 401/403 most likely indicates that access token has expired. Unless it happens two times in a row. + if ( response != null && (response.code() == HTTP_UNAUTHORIZED || response.code() == HTTP_FORBIDDEN) && updateTokenAndRetryOnAuthorizationFailure ) { + try { + if (updateAccessToken(requestAccessToken)) { + response.body().close(); + return retryingIntercept( chain, false ); + } + } catch (Exception e) { + response.body().close(); + throw e; + } + } + return response; + } else { + return chain.proceed(chain.request()); + } + } + + /* + * Returns true if the access token has been updated + */ + public synchronized boolean updateAccessToken(String requestAccessToken) throws IOException { + if (getAccessToken() == null || getAccessToken().equals(requestAccessToken)) { + try { + OAuthJSONAccessTokenResponse accessTokenResponse = oauthClient.accessToken(this.tokenRequestBuilder.buildBodyMessage()); + if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { + setAccessToken(accessTokenResponse.getAccessToken()); + if (accessTokenListener != null) { + accessTokenListener.notify((BasicOAuthToken) accessTokenResponse.getOAuthToken()); + } + return !getAccessToken().equals(requestAccessToken); + } else { + return false; + } + } catch (OAuthSystemException e) { + throw new IOException(e); + } catch (OAuthProblemException e) { + throw new IOException(e); + } + } + return true; + } + + public void registerAccessTokenListener(AccessTokenListener accessTokenListener) { + this.accessTokenListener = accessTokenListener; + } + + public synchronized String getAccessToken() { + return accessToken; + } + + public synchronized void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + public TokenRequestBuilder getTokenRequestBuilder() { + return tokenRequestBuilder; + } + + public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) { + this.tokenRequestBuilder = tokenRequestBuilder; + } + + public AuthenticationRequestBuilder getAuthenticationRequestBuilder() { + return authenticationRequestBuilder; + } + + public void setAuthenticationRequestBuilder(AuthenticationRequestBuilder authenticationRequestBuilder) { + this.authenticationRequestBuilder = authenticationRequestBuilder; + } + +} diff --git a/libraries/retrofit/auth/OAuthOkHttpClient.mustache b/libraries/retrofit/auth/OAuthOkHttpClient.mustache new file mode 100644 index 00000000000..ea195f7df04 --- /dev/null +++ b/libraries/retrofit/auth/OAuthOkHttpClient.mustache @@ -0,0 +1,69 @@ +package {{invokerPackage}}.auth; + +import java.io.IOException; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.oltu.oauth2.client.HttpClient; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest; +import org.apache.oltu.oauth2.client.response.OAuthClientResponse; +import org.apache.oltu.oauth2.client.response.OAuthClientResponseFactory; +import org.apache.oltu.oauth2.common.exception.OAuthProblemException; +import org.apache.oltu.oauth2.common.exception.OAuthSystemException; + +import com.squareup.okhttp.MediaType; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.RequestBody; +import com.squareup.okhttp.Response; + + +public class OAuthOkHttpClient implements HttpClient { + + private OkHttpClient client; + + public OAuthOkHttpClient() { + this.client = new OkHttpClient(); + } + + public OAuthOkHttpClient(OkHttpClient client) { + this.client = client; + } + + public T execute(OAuthClientRequest request, Map headers, + String requestMethod, Class responseClass) + throws OAuthSystemException, OAuthProblemException { + + MediaType mediaType = MediaType.parse("application/json"); + Request.Builder requestBuilder = new Request.Builder().url(request.getLocationUri()); + + if(headers != null) { + for (Entry entry : headers.entrySet()) { + if (entry.getKey().equalsIgnoreCase("Content-Type")) { + mediaType = MediaType.parse(entry.getValue()); + } else { + requestBuilder.addHeader(entry.getKey(), entry.getValue()); + } + } + } + + RequestBody body = request.getBody() != null ? RequestBody.create(mediaType, request.getBody()) : null; + requestBuilder.method(requestMethod, body); + + try { + Response response = client.newCall(requestBuilder.build()).execute(); + return OAuthClientResponseFactory.createCustomResponse( + response.body().string(), + response.body().contentType().toString(), + response.code(), + responseClass); + } catch (IOException e) { + throw new OAuthSystemException(e); + } + } + + public void shutdown() { + // Nothing to do here + } + +} diff --git a/libraries/retrofit/bodyParams.mustache b/libraries/retrofit/bodyParams.mustache new file mode 100644 index 00000000000..81de324b691 --- /dev/null +++ b/libraries/retrofit/bodyParams.mustache @@ -0,0 +1 @@ +{{#isBodyParam}}@retrofit.http.Body {{{dataType}}} {{paramName}}{{/isBodyParam}} \ No newline at end of file diff --git a/libraries/retrofit/build.gradle.mustache b/libraries/retrofit/build.gradle.mustache new file mode 100644 index 00000000000..60dec7e1260 --- /dev/null +++ b/libraries/retrofit/build.gradle.mustache @@ -0,0 +1,118 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + } + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + okhttp_version = "2.7.5" + oltu_version = "1.0.1" + retrofit_version = "1.9.0" + swagger_annotations_version = "1.5.8" + junit_version = "4.12" + jodatime_version = "2.9.3" +} + +dependencies { + compile "com.squareup.okhttp:okhttp:$okhttp_version" + compile "com.squareup.retrofit:retrofit:$retrofit_version" + compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version" + compile "joda-time:joda-time:$jodatime_version" + testCompile "junit:junit:$junit_version" +} diff --git a/libraries/retrofit/build.sbt.mustache b/libraries/retrofit/build.sbt.mustache new file mode 100644 index 00000000000..56f6cee13ab --- /dev/null +++ b/libraries/retrofit/build.sbt.mustache @@ -0,0 +1,20 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "com.squareup.okhttp" % "okhttp" % "2.7.5" % "compile", + "com.squareup.retrofit" % "retrofit" % "1.9.0" % "compile", + "io.swagger" % "swagger-annotations" % "1.5.8" % "compile", + "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", + "joda-time" % "joda-time" % "2.9.3" % "compile", + "junit" % "junit" % "4.12" % "test", + "com.novocode" % "junit-interface" % "0.10" % "test" + ) + ) diff --git a/libraries/retrofit/formParams.mustache b/libraries/retrofit/formParams.mustache new file mode 100644 index 00000000000..f1f9027ae51 --- /dev/null +++ b/libraries/retrofit/formParams.mustache @@ -0,0 +1 @@ +{{#isFormParam}}{{#notFile}}{{#isMultipart}}@retrofit.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit.http.Field{{/isMultipart}}("{{baseName}}") {{{dataType}}} {{paramName}}{{/notFile}}{{#isFile}}{{#isMultipart}}@retrofit.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit.http.Field{{/isMultipart}}("{{baseName}}") TypedFile {{paramName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file diff --git a/libraries/retrofit/headerParams.mustache b/libraries/retrofit/headerParams.mustache new file mode 100644 index 00000000000..5d6da4a9437 --- /dev/null +++ b/libraries/retrofit/headerParams.mustache @@ -0,0 +1 @@ +{{#isHeaderParam}}@retrofit.http.Header("{{baseName}}") {{{dataType}}} {{paramName}}{{/isHeaderParam}} \ No newline at end of file diff --git a/libraries/retrofit/pathParams.mustache b/libraries/retrofit/pathParams.mustache new file mode 100644 index 00000000000..7b8be8442e0 --- /dev/null +++ b/libraries/retrofit/pathParams.mustache @@ -0,0 +1 @@ +{{#isPathParam}}@retrofit.http.Path("{{baseName}}") {{{dataType}}} {{paramName}}{{/isPathParam}} \ No newline at end of file diff --git a/libraries/retrofit/pom.mustache b/libraries/retrofit/pom.mustache new file mode 100644 index 00000000000..b4ceff3aac0 --- /dev/null +++ b/libraries/retrofit/pom.mustache @@ -0,0 +1,254 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{artifactUrl}} + {{artifactDescription}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}} + {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}} + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-core-version} + + + com.squareup.retrofit + retrofit + ${retrofit-version} + + + org.apache.oltu.oauth2 + org.apache.oltu.oauth2.client + ${oltu-version} + + + com.squareup.okhttp + okhttp + ${okhttp-version} + + + joda-time + joda-time + ${jodatime-version} + + + {{#parcelableModel}} + + + com.google.android + android + 4.1.1.4 + provided + + {{/parcelableModel}} + + + + junit + junit + ${junit-version} + test + + + + UTF-8 + 1.5.18 + 1.9.0 + 2.7.5 + 2.9.9 + 1.0.1 + 1.0.0 + 4.12 + + diff --git a/libraries/retrofit/queryParams.mustache b/libraries/retrofit/queryParams.mustache new file mode 100644 index 00000000000..2a580ab34ec --- /dev/null +++ b/libraries/retrofit/queryParams.mustache @@ -0,0 +1 @@ +{{#isQueryParam}}@retrofit.http.Query("{{baseName}}") {{#collectionFormat}}{{#isCollectionFormatMulti}}{{{dataType}}}{{/isCollectionFormatMulti}}{{^isCollectionFormatMulti}}{{{collectionFormat.toUpperCase}}}Params{{/isCollectionFormatMulti}}{{/collectionFormat}}{{^collectionFormat}}{{{dataType}}}{{/collectionFormat}} {{paramName}}{{/isQueryParam}} \ No newline at end of file diff --git a/libraries/retrofit2/ApiClient.mustache b/libraries/retrofit2/ApiClient.mustache new file mode 100644 index 00000000000..66d3056e540 --- /dev/null +++ b/libraries/retrofit2/ApiClient.mustache @@ -0,0 +1,420 @@ +package {{invokerPackage}}; + +import com.google.gson.Gson; +import com.google.gson.JsonParseException; +import com.google.gson.JsonElement; +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.RequestBody; +import okhttp3.ResponseBody; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; +{{#joda}} +import org.joda.time.format.DateTimeFormatter; +{{/joda}} +{{#threetenbp}} +import org.threeten.bp.format.DateTimeFormatter; +{{/threetenbp}} +import retrofit2.Converter; +import retrofit2.Retrofit; +{{#useRxJava}} +import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; +{{/useRxJava}} +{{#useRxJava2}} +import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; +{{/useRxJava2}} +import retrofit2.converter.gson.GsonConverterFactory; +import retrofit2.converter.scalars.ScalarsConverterFactory; +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.OAuth; +import {{invokerPackage}}.auth.OAuth.AccessTokenListener; +import {{invokerPackage}}.auth.OAuthFlow; + +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.text.DateFormat; +{{#java8}} +import java.time.format.DateTimeFormatter; +{{/java8}} +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.HashMap; + +public class ApiClient { + + private Map apiAuthorizations; + private OkHttpClient.Builder okBuilder; + private Retrofit.Builder adapterBuilder; + private JSON json; + + public ApiClient() { + apiAuthorizations = new LinkedHashMap(); + createDefaultAdapter(); + } + + public ApiClient(String[] authNames) { + this(); + for(String authName : authNames) { + {{#hasAuthMethods}} + Interceptor auth; + {{#authMethods}}if ("{{name}}".equals(authName)) { + {{#isBasic}} + auth = new HttpBasicAuth(); + {{/isBasic}} + {{#isApiKey}} + auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"); + {{/isApiKey}} + {{#isOAuth}} + auth = new OAuth(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{#hasMore}}, {{/hasMore}}{{/scopes}}"); + {{/isOAuth}} + } else {{/authMethods}}{ + throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); + } + + addAuthorization(authName, auth); + {{/hasAuthMethods}} + {{^hasAuthMethods}} + throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); + {{/hasAuthMethods}} + } + } + + /** + * Basic constructor for single auth name + * @param authName Authentication name + */ + public ApiClient(String authName) { + this(new String[]{authName}); + } + + /** + * Helper constructor for single api key + * @param authName Authentication name + * @param apiKey API key + */ + public ApiClient(String authName, String apiKey) { + this(authName); + this.setApiKey(apiKey); + } + + /** + * Helper constructor for single basic auth or password oauth2 + * @param authName Authentication name + * @param username Username + * @param password Password + */ + public ApiClient(String authName, String username, String password) { + this(authName); + this.setCredentials(username, password); + } + + /** + * Helper constructor for single password oauth2 + * @param authName Authentication name + * @param clientId Client ID + * @param secret Client Secret + * @param username Username + * @param password Password + */ + public ApiClient(String authName, String clientId, String secret, String username, String password) { + this(authName); + this.getTokenEndPoint() + .setClientId(clientId) + .setClientSecret(secret) + .setUsername(username) + .setPassword(password); + } + + public void createDefaultAdapter() { + json = new JSON(); + okBuilder = new OkHttpClient.Builder(); + + String baseUrl = "{{{basePath}}}"; + if (!baseUrl.endsWith("/")) + baseUrl = baseUrl + "/"; + + adapterBuilder = new Retrofit + .Builder() + .baseUrl(baseUrl) + {{#useRxJava}} + .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) + {{/useRxJava}}{{#useRxJava2}} + .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) + {{/useRxJava2}} + .addConverterFactory(ScalarsConverterFactory.create()) + .addConverterFactory(GsonCustomConverterFactory.create(json.getGson())); + } + + public S createService(Class serviceClass) { + return adapterBuilder + .client(okBuilder.build()) + .build() + .create(serviceClass); + } + + public ApiClient setDateFormat(DateFormat dateFormat) { + this.json.setDateFormat(dateFormat); + return this; + } + + public ApiClient setSqlDateFormat(DateFormat dateFormat) { + this.json.setSqlDateFormat(dateFormat); + return this; + } + + {{#joda}} + public ApiClient setDateTimeFormat(DateTimeFormatter dateFormat) { + this.json.setDateTimeFormat(dateFormat); + return this; + } + + public ApiClient setLocalDateFormat(DateTimeFormatter dateFormat) { + this.json.setLocalDateFormat(dateFormat); + return this; + } + + {{/joda}} + {{#jsr310}} + public ApiClient setOffsetDateTimeFormat(DateTimeFormatter dateFormat) { + this.json.setOffsetDateTimeFormat(dateFormat); + return this; + } + + public ApiClient setLocalDateFormat(DateTimeFormatter dateFormat) { + this.json.setLocalDateFormat(dateFormat); + return this; + } + + {{/jsr310}} + + /** + * Helper method to configure the first api key found + * @param apiKey API key + * @return ApiClient + */ + public ApiClient setApiKey(String apiKey) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof ApiKeyAuth) { + ApiKeyAuth keyAuth = (ApiKeyAuth) apiAuthorization; + keyAuth.setApiKey(apiKey); + return this; + } + } + return this; + } + + /** + * Helper method to configure the username/password for basic auth or password oauth + * @param username Username + * @param password Password + * @return ApiClient + */ + public ApiClient setCredentials(String username, String password) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof HttpBasicAuth) { + HttpBasicAuth basicAuth = (HttpBasicAuth) apiAuthorization; + basicAuth.setCredentials(username, password); + return this; + } + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.getTokenRequestBuilder().setUsername(username).setPassword(password); + return this; + } + } + return this; + } + + /** + * Helper method to configure the token endpoint of the first oauth found in the apiAuthorizations (there should be only one) + * @return Token request builder + */ + public TokenRequestBuilder getTokenEndPoint() { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + return oauth.getTokenRequestBuilder(); + } + } + return null; + } + + /** + * Helper method to configure authorization endpoint of the first oauth found in the apiAuthorizations (there should be only one) + * @return Authentication request builder + */ + public AuthenticationRequestBuilder getAuthorizationEndPoint() { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + return oauth.getAuthenticationRequestBuilder(); + } + } + return null; + } + + /** + * Helper method to pre-set the oauth access token of the first oauth found in the apiAuthorizations (there should be only one) + * @param accessToken Access token + * @return ApiClient + */ + public ApiClient setAccessToken(String accessToken) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.setAccessToken(accessToken); + return this; + } + } + return this; + } + + /** + * Helper method to configure the oauth accessCode/implicit flow parameters + * @param clientId Client ID + * @param clientSecret Client secret + * @param redirectURI Redirect URI + * @return ApiClient + */ + public ApiClient configureAuthorizationFlow(String clientId, String clientSecret, String redirectURI) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.getTokenRequestBuilder() + .setClientId(clientId) + .setClientSecret(clientSecret) + .setRedirectURI(redirectURI); + oauth.getAuthenticationRequestBuilder() + .setClientId(clientId) + .setRedirectURI(redirectURI); + return this; + } + } + return this; + } + + /** + * Configures a listener which is notified when a new access token is received. + * @param accessTokenListener Access token listener + * @return ApiClient + */ + public ApiClient registerAccessTokenListener(AccessTokenListener accessTokenListener) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.registerAccessTokenListener(accessTokenListener); + return this; + } + } + return this; + } + + /** + * Adds an authorization to be used by the client + * @param authName Authentication name + * @param authorization Authorization interceptor + * @return ApiClient + */ + public ApiClient addAuthorization(String authName, Interceptor authorization) { + if (apiAuthorizations.containsKey(authName)) { + throw new RuntimeException("auth name \"" + authName + "\" already in api authorizations"); + } + apiAuthorizations.put(authName, authorization); + okBuilder.addInterceptor(authorization); + return this; + } + + public Map getApiAuthorizations() { + return apiAuthorizations; + } + + public ApiClient setApiAuthorizations(Map apiAuthorizations) { + this.apiAuthorizations = apiAuthorizations; + return this; + } + + public Retrofit.Builder getAdapterBuilder() { + return adapterBuilder; + } + + public ApiClient setAdapterBuilder(Retrofit.Builder adapterBuilder) { + this.adapterBuilder = adapterBuilder; + return this; + } + + public OkHttpClient.Builder getOkBuilder() { + return okBuilder; + } + + public void addAuthsToOkBuilder(OkHttpClient.Builder okBuilder) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + okBuilder.addInterceptor(apiAuthorization); + } + } + + /** + * Clones the okBuilder given in parameter, adds the auth interceptors and uses it to configure the Retrofit + * @param okClient An instance of OK HTTP client + */ + public void configureFromOkclient(OkHttpClient okClient) { + this.okBuilder = okClient.newBuilder(); + addAuthsToOkBuilder(this.okBuilder); + } +} + +/** + * This wrapper is to take care of this case: + * when the deserialization fails due to JsonParseException and the + * expected type is String, then just return the body string. + */ +class GsonResponseBodyConverterToString implements Converter { + private final Gson gson; + private final Type type; + + GsonResponseBodyConverterToString(Gson gson, Type type) { + this.gson = gson; + this.type = type; + } + + @Override public T convert(ResponseBody value) throws IOException { + String returned = value.string(); + try { + return gson.fromJson(returned, type); + } + catch (JsonParseException e) { + return (T) returned; + } + } +} + +class GsonCustomConverterFactory extends Converter.Factory +{ + private final Gson gson; + private final GsonConverterFactory gsonConverterFactory; + + public static GsonCustomConverterFactory create(Gson gson) { + return new GsonCustomConverterFactory(gson); + } + + private GsonCustomConverterFactory(Gson gson) { + if (gson == null) + throw new NullPointerException("gson == null"); + this.gson = gson; + this.gsonConverterFactory = GsonConverterFactory.create(gson); + } + + @Override + public Converter responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { + if (type.equals(String.class)) + return new GsonResponseBodyConverterToString(gson, type); + else + return gsonConverterFactory.responseBodyConverter(type, annotations, retrofit); + } + + @Override + public Converter requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { + return gsonConverterFactory.requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit); + } +} diff --git a/libraries/retrofit2/CollectionFormats.mustache b/libraries/retrofit2/CollectionFormats.mustache new file mode 100644 index 00000000000..8c91c335dfc --- /dev/null +++ b/libraries/retrofit2/CollectionFormats.mustache @@ -0,0 +1,95 @@ +package {{invokerPackage}}; + +import java.util.Arrays; +import java.util.List; + +public class CollectionFormats { + + public static class CSVParams { + + protected List params; + + public CSVParams() { + } + + public CSVParams(List params) { + this.params = params; + } + + public CSVParams(String... params) { + this.params = Arrays.asList(params); + } + + public List getParams() { + return params; + } + + public void setParams(List params) { + this.params = params; + } + + @Override + public String toString() { + return StringUtil.join(params.toArray(new String[0]), ","); + } + + } + + public static class SSVParams extends CSVParams { + + public SSVParams() { + } + + public SSVParams(List params) { + super(params); + } + + public SSVParams(String... params) { + super(params); + } + + @Override + public String toString() { + return StringUtil.join(params.toArray(new String[0]), " "); + } + } + + public static class TSVParams extends CSVParams { + + public TSVParams() { + } + + public TSVParams(List params) { + super(params); + } + + public TSVParams(String... params) { + super(params); + } + + @Override + public String toString() { + return StringUtil.join( params.toArray(new String[0]), "\t"); + } + } + + public static class PIPESParams extends CSVParams { + + public PIPESParams() { + } + + public PIPESParams(List params) { + super(params); + } + + public PIPESParams(String... params) { + super(params); + } + + @Override + public String toString() { + return StringUtil.join(params.toArray(new String[0]), "|"); + } + } + +} diff --git a/libraries/retrofit2/JSON.mustache b/libraries/retrofit2/JSON.mustache new file mode 100644 index 00000000000..abab9159d79 --- /dev/null +++ b/libraries/retrofit2/JSON.mustache @@ -0,0 +1,446 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonParseException; +import com.google.gson.TypeAdapter; +import com.google.gson.internal.bind.util.ISO8601Utils; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import com.google.gson.JsonElement; +import io.gsonfire.GsonFireBuilder; +import io.gsonfire.TypeSelector; +{{#joda}} +import org.joda.time.DateTime; +import org.joda.time.LocalDate; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.DateTimeFormatterBuilder; +import org.joda.time.format.ISODateTimeFormat; +{{/joda}} +{{#threetenbp}} +import org.threeten.bp.LocalDate; +import org.threeten.bp.OffsetDateTime; +import org.threeten.bp.format.DateTimeFormatter; +{{/threetenbp}} + +import {{modelPackage}}.*; + +import java.io.IOException; +import java.io.StringReader; +import java.lang.reflect.Type; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.ParsePosition; +{{#java8}} +import java.time.LocalDate; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +{{/java8}} +import java.util.Date; +import java.util.Map; +import java.util.HashMap; + +public class JSON { + private Gson gson; + private DateTypeAdapter dateTypeAdapter = new DateTypeAdapter(); + private SqlDateTypeAdapter sqlDateTypeAdapter = new SqlDateTypeAdapter(); + {{#joda}} + private DateTimeTypeAdapter dateTimeTypeAdapter = new DateTimeTypeAdapter(); + private LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter(); + {{/joda}} + {{#jsr310}} + private OffsetDateTimeTypeAdapter offsetDateTimeTypeAdapter = new OffsetDateTimeTypeAdapter(); + private LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter(); + {{/jsr310}} + + public static GsonBuilder createGson() { + GsonFireBuilder fireBuilder = new GsonFireBuilder() + {{#parent}} + .registerTypeSelector({{classname}}.class, new TypeSelector() { + @Override + public Class getClassForElement(JsonElement readElement) { + Map classByDiscriminatorValue = new HashMap(); + {{#children}} + classByDiscriminatorValue.put("{{name}}".toUpperCase(), {{classname}}.class); + {{/children}} + classByDiscriminatorValue.put("{{classname}}".toUpperCase(), {{classname}}.class); + return getClassByDiscriminator( + classByDiscriminatorValue, + getDiscriminatorValue(readElement, "{{discriminator}}")); + } + }) + {{/parent}} + ; + return fireBuilder.createGsonBuilder(); + } + + private static String getDiscriminatorValue(JsonElement readElement, String discriminatorField) { + JsonElement element = readElement.getAsJsonObject().get(discriminatorField); + if(null == element) { + throw new IllegalArgumentException("missing discriminator field: <" + discriminatorField + ">"); + } + return element.getAsString(); + } + + private static Class getClassByDiscriminator(Map classByDiscriminatorValue, String discriminatorValue) { + Class clazz = (Class) classByDiscriminatorValue.get(discriminatorValue.toUpperCase()); + if(null == clazz) { + throw new IllegalArgumentException("cannot determine model class of name: <" + discriminatorValue + ">"); + } + return clazz; + } + + public JSON() { + gson = createGson() + .registerTypeAdapter(Date.class, dateTypeAdapter) + .registerTypeAdapter(java.sql.Date.class, sqlDateTypeAdapter) + {{#joda}} + .registerTypeAdapter(DateTime.class, dateTimeTypeAdapter) + .registerTypeAdapter(LocalDate.class, localDateTypeAdapter) + {{/joda}} + {{#jsr310}} + .registerTypeAdapter(OffsetDateTime.class, offsetDateTimeTypeAdapter) + .registerTypeAdapter(LocalDate.class, localDateTypeAdapter) + {{/jsr310}} + .create(); + } + + /** + * Get Gson. + * + * @return Gson + */ + public Gson getGson() { + return gson; + } + + /** + * Set Gson. + * + * @param gson Gson + * @return JSON + */ + public JSON setGson(Gson gson) { + this.gson = gson; + return this; + } + + {{#joda}} + /** + * Gson TypeAdapter for Joda DateTime type + */ + public static class DateTimeTypeAdapter extends TypeAdapter { + + private DateTimeFormatter formatter; + + public DateTimeTypeAdapter() { + this(new DateTimeFormatterBuilder() + .append(ISODateTimeFormat.dateTime().getPrinter(), ISODateTimeFormat.dateOptionalTimeParser().getParser()) + .toFormatter()); + } + + public DateTimeTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } + + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } + + @Override + public void write(JsonWriter out, DateTime date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.print(date)); + } + } + + @Override + public DateTime read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + return formatter.parseDateTime(date); + } + } + } + + /** + * Gson TypeAdapter for Joda LocalDate type + */ + public class LocalDateTypeAdapter extends TypeAdapter { + + private DateTimeFormatter formatter; + + public LocalDateTypeAdapter() { + this(ISODateTimeFormat.date()); + } + + public LocalDateTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } + + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } + + @Override + public void write(JsonWriter out, LocalDate date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.print(date)); + } + } + + @Override + public LocalDate read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + return formatter.parseLocalDate(date); + } + } + } + + public JSON setDateTimeFormat(DateTimeFormatter dateFormat) { + dateTimeTypeAdapter.setFormat(dateFormat); + return this; + } + + public JSON setLocalDateFormat(DateTimeFormatter dateFormat) { + localDateTypeAdapter.setFormat(dateFormat); + return this; + } + + {{/joda}} + {{#jsr310}} + /** + * Gson TypeAdapter for JSR310 OffsetDateTime type + */ + public static class OffsetDateTimeTypeAdapter extends TypeAdapter { + + private DateTimeFormatter formatter; + + public OffsetDateTimeTypeAdapter() { + this(DateTimeFormatter.ISO_OFFSET_DATE_TIME); + } + + public OffsetDateTimeTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } + + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } + + @Override + public void write(JsonWriter out, OffsetDateTime date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.format(date)); + } + } + + @Override + public OffsetDateTime read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + if (date.endsWith("+0000")) { + date = date.substring(0, date.length()-5) + "Z"; + } + return OffsetDateTime.parse(date, formatter); + } + } + } + + /** + * Gson TypeAdapter for JSR310 LocalDate type + */ + public class LocalDateTypeAdapter extends TypeAdapter { + + private DateTimeFormatter formatter; + + public LocalDateTypeAdapter() { + this(DateTimeFormatter.ISO_LOCAL_DATE); + } + + public LocalDateTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } + + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } + + @Override + public void write(JsonWriter out, LocalDate date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.format(date)); + } + } + + @Override + public LocalDate read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + return LocalDate.parse(date, formatter); + } + } + } + + public JSON setOffsetDateTimeFormat(DateTimeFormatter dateFormat) { + offsetDateTimeTypeAdapter.setFormat(dateFormat); + return this; + } + + public JSON setLocalDateFormat(DateTimeFormatter dateFormat) { + localDateTypeAdapter.setFormat(dateFormat); + return this; + } + + {{/jsr310}} + /** + * Gson TypeAdapter for java.sql.Date type + * If the dateFormat is null, a simple "yyyy-MM-dd" format will be used + * (more efficient than SimpleDateFormat). + */ + public static class SqlDateTypeAdapter extends TypeAdapter { + + private DateFormat dateFormat; + + public SqlDateTypeAdapter() { + } + + public SqlDateTypeAdapter(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + public void setFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + @Override + public void write(JsonWriter out, java.sql.Date date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + String value; + if (dateFormat != null) { + value = dateFormat.format(date); + } else { + value = date.toString(); + } + out.value(value); + } + } + + @Override + public java.sql.Date read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + try { + if (dateFormat != null) { + return new java.sql.Date(dateFormat.parse(date).getTime()); + } + return new java.sql.Date(ISO8601Utils.parse(date, new ParsePosition(0)).getTime()); + } catch (ParseException e) { + throw new JsonParseException(e); + } + } + } + } + + /** + * Gson TypeAdapter for java.util.Date type + * If the dateFormat is null, ISO8601Utils will be used. + */ + public static class DateTypeAdapter extends TypeAdapter { + + private DateFormat dateFormat; + + public DateTypeAdapter() { + } + + public DateTypeAdapter(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + public void setFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + @Override + public void write(JsonWriter out, Date date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + String value; + if (dateFormat != null) { + value = dateFormat.format(date); + } else { + value = ISO8601Utils.format(date, true); + } + out.value(value); + } + } + + @Override + public Date read(JsonReader in) throws IOException { + try { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + try { + if (dateFormat != null) { + return dateFormat.parse(date); + } + return ISO8601Utils.parse(date, new ParsePosition(0)); + } catch (ParseException e) { + throw new JsonParseException(e); + } + } + } catch (IllegalArgumentException e) { + throw new JsonParseException(e); + } + } + } + + public JSON setDateFormat(DateFormat dateFormat) { + dateTypeAdapter.setFormat(dateFormat); + return this; + } + + public JSON setSqlDateFormat(DateFormat dateFormat) { + sqlDateTypeAdapter.setFormat(dateFormat); + return this; + } + +} diff --git a/libraries/retrofit2/README.mustache b/libraries/retrofit2/README.mustache new file mode 100644 index 00000000000..9d744b8589e --- /dev/null +++ b/libraries/retrofit2/README.mustache @@ -0,0 +1,39 @@ +# {{artifactId}} + +## Requirements + +Building the API client library requires [Maven](https://maven.apache.org/) to be installed. + +## Installation & Usage + +To install the API client library to your local Maven repository, simply execute: + +```shell +mvn install +``` + +To deploy it to a remote Maven repository instead, configure the settings of the repository and execute: + +```shell +mvn deploy +``` + +Refer to the [official documentation](https://maven.apache.org/plugins/maven-deploy-plugin/usage.html) for more information. + +After the client library is installed/deployed, you can use it in your Maven project by adding the following to your *pom.xml*: + +```xml + + {{groupId}} + {{artifactId}} + {{artifactVersion}} + compile + + +``` + +## Author + +{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} +{{/hasMore}}{{/apis}}{{/apiInfo}} + diff --git a/libraries/retrofit2/api.mustache b/libraries/retrofit2/api.mustache new file mode 100644 index 00000000000..f6eb4c2dd07 --- /dev/null +++ b/libraries/retrofit2/api.mustache @@ -0,0 +1,77 @@ +package {{package}}; + +import {{invokerPackage}}.CollectionFormats.*; + +{{#useRxJava}} +import rx.Observable; +{{/useRxJava}} +{{#useRxJava2}} +import io.reactivex.Observable; +{{/useRxJava2}} +{{^returnType}} +{{#useRxJava2}} +import io.reactivex.Completable; +{{/useRxJava2}} +{{/returnType}} +{{#doNotUseRx}} +import retrofit2.Call; +{{/doNotUseRx}} +import retrofit2.http.*; + +import okhttp3.RequestBody; +import okhttp3.ResponseBody; +import okhttp3.MultipartBody; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +{{#operations}} +public interface {{classname}} { + {{#operation}} + /** + * {{summary}} + * {{notes}} +{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} +{{/allParams}} + * @return {{^doNotUseRx}}{{#useRxJava}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/useRxJava}}{{#useRxJava2}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{returnType}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{/doNotUseRx}}{{#doNotUseRx}}Call<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/doNotUseRx}} +{{#isDeprecated}} + * @deprecated +{{/isDeprecated}} +{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation +{{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + {{#formParams}} + {{#-first}} + {{#isMultipart}}@retrofit2.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit2.http.FormUrlEncoded{{/isMultipart}} + {{/-first}} + {{/formParams}} + {{^formParams}} + {{#prioritizedContentTypes}} + {{#-first}} + @Headers({ + "Content-Type:{{{mediaType}}}" + }) + {{/-first}} + {{/prioritizedContentTypes}} + {{/formParams}} + @{{httpMethod}}("{{{path}}}") + {{^doNotUseRx}}{{#useRxJava}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/useRxJava}}{{#useRxJava2}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{{returnType}}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{/doNotUseRx}}{{#doNotUseRx}}Call<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/doNotUseRx}} {{operationId}}({{^allParams}});{{/allParams}} + {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{#hasMore}}, {{/hasMore}}{{^hasMore}} + );{{/hasMore}}{{/allParams}} + + {{/operation}} +} +{{/operations}} diff --git a/libraries/retrofit2/api_test.mustache b/libraries/retrofit2/api_test.mustache new file mode 100644 index 00000000000..0a85ef5095c --- /dev/null +++ b/libraries/retrofit2/api_test.mustache @@ -0,0 +1,46 @@ +package {{package}}; + +import {{invokerPackage}}.ApiClient; +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Before; +import org.junit.Test; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +public class {{classname}}Test { + + private {{classname}} api; + + @Before + public void setup() { + api = new ApiClient().createService({{classname}}.class); + } + + {{#operations}} + {{#operation}} + /** + * {{summary}} + * + * {{notes}} + */ + @Test + public void {{operationId}}Test() { + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + // {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + + // TODO: test validations + } + {{/operation}} + {{/operations}} +} diff --git a/libraries/retrofit2/auth/ApiKeyAuth.mustache b/libraries/retrofit2/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..2f4bae3dd02 --- /dev/null +++ b/libraries/retrofit2/auth/ApiKeyAuth.mustache @@ -0,0 +1,68 @@ +package {{invokerPackage}}.auth; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +public class ApiKeyAuth implements Interceptor { + private final String location; + private final String paramName; + + private String apiKey; + + public ApiKeyAuth(String location, String paramName) { + this.location = location; + this.paramName = paramName; + } + + public String getLocation() { + return location; + } + + public String getParamName() { + return paramName; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + @Override + public Response intercept(Chain chain) throws IOException { + String paramValue; + Request request = chain.request(); + + if ("query".equals(location)) { + String newQuery = request.url().uri().getQuery(); + paramValue = paramName + "=" + apiKey; + if (newQuery == null) { + newQuery = paramValue; + } else { + newQuery += "&" + paramValue; + } + + URI newUri; + try { + newUri = new URI(request.url().uri().getScheme(), request.url().uri().getAuthority(), + request.url().uri().getPath(), newQuery, request.url().uri().getFragment()); + } catch (URISyntaxException e) { + throw new IOException(e); + } + + request = request.newBuilder().url(newUri.toURL()).build(); + } else if ("header".equals(location)) { + request = request.newBuilder() + .addHeader(paramName, apiKey) + .build(); + } + return chain.proceed(request); + } +} diff --git a/libraries/retrofit2/auth/HttpBasicAuth.mustache b/libraries/retrofit2/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..d4588426662 --- /dev/null +++ b/libraries/retrofit2/auth/HttpBasicAuth.mustache @@ -0,0 +1,50 @@ +package {{invokerPackage}}.auth; + +import java.io.IOException; + +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.Credentials; + +public class HttpBasicAuth implements Interceptor { + + private String username; + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public void setCredentials(String username, String password) { + this.username = username; + this.password = password; + } + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + + // If the request already have an authorization (eg. Basic auth), do nothing + if (request.header("Authorization") == null) { + String credentials = Credentials.basic(username, password); + request = request.newBuilder() + .addHeader("Authorization", credentials) + .build(); + } + return chain.proceed(request); + } +} diff --git a/libraries/retrofit2/auth/OAuth.mustache b/libraries/retrofit2/auth/OAuth.mustache new file mode 100644 index 00000000000..80ec7b3946c --- /dev/null +++ b/libraries/retrofit2/auth/OAuth.mustache @@ -0,0 +1,185 @@ +package {{invokerPackage}}.auth; + +import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; +import static java.net.HttpURLConnection.HTTP_FORBIDDEN; + +import java.io.IOException; +import java.util.Map; + +import org.apache.oltu.oauth2.client.OAuthClient; +import org.apache.oltu.oauth2.client.request.OAuthBearerClientRequest; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; +import org.apache.oltu.oauth2.client.response.OAuthJSONAccessTokenResponse; +import org.apache.oltu.oauth2.common.exception.OAuthProblemException; +import org.apache.oltu.oauth2.common.exception.OAuthSystemException; +import org.apache.oltu.oauth2.common.message.types.GrantType; +import org.apache.oltu.oauth2.common.token.BasicOAuthToken; + +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Request.Builder; +import okhttp3.Response; + +public class OAuth implements Interceptor { + + public interface AccessTokenListener { + public void notify(BasicOAuthToken token); + } + + private volatile String accessToken; + private OAuthClient oauthClient; + + private TokenRequestBuilder tokenRequestBuilder; + private AuthenticationRequestBuilder authenticationRequestBuilder; + + private AccessTokenListener accessTokenListener; + + public OAuth( OkHttpClient client, TokenRequestBuilder requestBuilder ) { + this.oauthClient = new OAuthClient(new OAuthOkHttpClient(client)); + this.tokenRequestBuilder = requestBuilder; + } + + public OAuth(TokenRequestBuilder requestBuilder ) { + this(new OkHttpClient(), requestBuilder); + } + + public OAuth(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { + this(OAuthClientRequest.tokenLocation(tokenUrl).setScope(scopes)); + setFlow(flow); + authenticationRequestBuilder = OAuthClientRequest.authorizationLocation(authorizationUrl); + } + + public void setFlow(OAuthFlow flow) { + switch(flow) { + case accessCode: + case implicit: + tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE); + break; + case password: + tokenRequestBuilder.setGrantType(GrantType.PASSWORD); + break; + case application: + tokenRequestBuilder.setGrantType(GrantType.CLIENT_CREDENTIALS); + break; + default: + break; + } + } + + @Override + public Response intercept(Chain chain) + throws IOException { + + return retryingIntercept(chain, true); + } + + private Response retryingIntercept(Chain chain, boolean updateTokenAndRetryOnAuthorizationFailure) throws IOException { + Request request = chain.request(); + + // If the request already have an authorization (eg. Basic auth), do nothing + if (request.header("Authorization") != null) { + return chain.proceed(request); + } + + // If first time, get the token + OAuthClientRequest oAuthRequest; + if (getAccessToken() == null) { + updateAccessToken(null); + } + + if (getAccessToken() != null) { + // Build the request + Builder rb = request.newBuilder(); + + String requestAccessToken = new String(getAccessToken()); + try { + oAuthRequest = new OAuthBearerClientRequest(request.url().toString()) + .setAccessToken(requestAccessToken) + .buildHeaderMessage(); + } catch (OAuthSystemException e) { + throw new IOException(e); + } + + for ( Map.Entry header : oAuthRequest.getHeaders().entrySet() ) { + rb.addHeader(header.getKey(), header.getValue()); + } + rb.url( oAuthRequest.getLocationUri()); + + //Execute the request + Response response = chain.proceed(rb.build()); + + // 401/403 most likely indicates that access token has expired. Unless it happens two times in a row. + if ( response != null && (response.code() == HTTP_UNAUTHORIZED || response.code() == HTTP_FORBIDDEN) && updateTokenAndRetryOnAuthorizationFailure ) { + try { + if (updateAccessToken(requestAccessToken)) { + response.body().close(); + return retryingIntercept( chain, false ); + } + } catch (Exception e) { + response.body().close(); + throw e; + } + } + return response; + } else { + return chain.proceed(chain.request()); + } + } + + /* + * Returns true if the access token has been updated + */ + public synchronized boolean updateAccessToken(String requestAccessToken) throws IOException { + if (getAccessToken() == null || getAccessToken().equals(requestAccessToken)) { + try { + OAuthJSONAccessTokenResponse accessTokenResponse = oauthClient.accessToken(this.tokenRequestBuilder.buildBodyMessage()); + if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { + setAccessToken(accessTokenResponse.getAccessToken()); + if (accessTokenListener != null) { + accessTokenListener.notify((BasicOAuthToken) accessTokenResponse.getOAuthToken()); + } + return !getAccessToken().equals(requestAccessToken); + } else { + return false; + } + } catch (OAuthSystemException e) { + throw new IOException(e); + } catch (OAuthProblemException e) { + throw new IOException(e); + } + } + return true; + } + + public void registerAccessTokenListener(AccessTokenListener accessTokenListener) { + this.accessTokenListener = accessTokenListener; + } + + public synchronized String getAccessToken() { + return accessToken; + } + + public synchronized void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + public TokenRequestBuilder getTokenRequestBuilder() { + return tokenRequestBuilder; + } + + public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) { + this.tokenRequestBuilder = tokenRequestBuilder; + } + + public AuthenticationRequestBuilder getAuthenticationRequestBuilder() { + return authenticationRequestBuilder; + } + + public void setAuthenticationRequestBuilder(AuthenticationRequestBuilder authenticationRequestBuilder) { + this.authenticationRequestBuilder = authenticationRequestBuilder; + } + +} diff --git a/libraries/retrofit2/auth/OAuthOkHttpClient.mustache b/libraries/retrofit2/auth/OAuthOkHttpClient.mustache new file mode 100644 index 00000000000..423fa1ba0e5 --- /dev/null +++ b/libraries/retrofit2/auth/OAuthOkHttpClient.mustache @@ -0,0 +1,72 @@ +package {{invokerPackage}}.auth; + +import java.io.IOException; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.oltu.oauth2.client.HttpClient; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest; +import org.apache.oltu.oauth2.client.response.OAuthClientResponse; +import org.apache.oltu.oauth2.client.response.OAuthClientResponseFactory; +import org.apache.oltu.oauth2.common.exception.OAuthProblemException; +import org.apache.oltu.oauth2.common.exception.OAuthSystemException; + + +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Request.Builder; +import okhttp3.Response; +import okhttp3.MediaType; +import okhttp3.RequestBody; + + +public class OAuthOkHttpClient implements HttpClient { + + private OkHttpClient client; + + public OAuthOkHttpClient() { + this.client = new OkHttpClient(); + } + + public OAuthOkHttpClient(OkHttpClient client) { + this.client = client; + } + + public T execute(OAuthClientRequest request, Map headers, + String requestMethod, Class responseClass) + throws OAuthSystemException, OAuthProblemException { + + MediaType mediaType = MediaType.parse("application/json"); + Request.Builder requestBuilder = new Request.Builder().url(request.getLocationUri()); + + if(headers != null) { + for (Entry entry : headers.entrySet()) { + if (entry.getKey().equalsIgnoreCase("Content-Type")) { + mediaType = MediaType.parse(entry.getValue()); + } else { + requestBuilder.addHeader(entry.getKey(), entry.getValue()); + } + } + } + + RequestBody body = request.getBody() != null ? RequestBody.create(mediaType, request.getBody()) : null; + requestBuilder.method(requestMethod, body); + + try { + Response response = client.newCall(requestBuilder.build()).execute(); + return OAuthClientResponseFactory.createCustomResponse( + response.body().string(), + response.body().contentType().toString(), + response.code(), + responseClass); + } catch (IOException e) { + throw new OAuthSystemException(e); + } + } + + public void shutdown() { + // Nothing to do here + } + +} diff --git a/libraries/retrofit2/bodyParams.mustache b/libraries/retrofit2/bodyParams.mustache new file mode 100644 index 00000000000..97b03fcb717 --- /dev/null +++ b/libraries/retrofit2/bodyParams.mustache @@ -0,0 +1 @@ +{{#isBodyParam}}@retrofit2.http.Body {{{dataType}}} {{paramName}}{{/isBodyParam}} \ No newline at end of file diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache new file mode 100644 index 00000000000..f341375f821 --- /dev/null +++ b/libraries/retrofit2/build.gradle.mustache @@ -0,0 +1,164 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + } + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + sourceCompatibility = JavaVersion.VERSION_{{^java8}}1_7{{/java8}}{{#java8}}1_8{{/java8}} + targetCompatibility = JavaVersion.VERSION_{{^java8}}1_7{{/java8}}{{#java8}}1_8{{/java8}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + oltu_version = "1.0.1" + retrofit_version = "2.3.0" + {{#usePlayWS}} + {{#play24}} + jackson_version = "2.6.6" + play_version = "2.4.11" + {{/play24}} + {{#play25}} + jackson_version = "2.7.8" + play_version = "2.5.14" + {{/play25}} + {{/usePlayWS}} + swagger_annotations_version = "1.5.17" + junit_version = "4.12" + {{#useRxJava}} + rx_java_version = "1.3.0" + {{/useRxJava}} + {{#useRxJava2}} + rx_java_version = "2.1.1" + {{/useRxJava2}} + {{#joda}} + jodatime_version = "2.9.9" + {{/joda}} + {{#threetenbp}} + threetenbp_version = "1.3.5" + {{/threetenbp}} + json_fire_version = "1.8.0" +} + +dependencies { + compile "com.squareup.retrofit2:retrofit:$retrofit_version" + compile "com.squareup.retrofit2:converter-scalars:$retrofit_version" + compile "com.squareup.retrofit2:converter-gson:$retrofit_version" + {{#useRxJava}} + compile "com.squareup.retrofit2:adapter-rxjava:$retrofit_version" + compile "io.reactivex:rxjava:$rx_java_version" + {{/useRxJava}} + {{#useRxJava2}} + compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' + compile "io.reactivex.rxjava2:rxjava:$rx_java_version" + {{/useRxJava2}} + compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile ("org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version"){ + exclude group:'org.apache.oltu.oauth2' , module: 'org.apache.oltu.oauth2.common' + } + compile "io.gsonfire:gson-fire:$json_fire_version" + {{#joda}} + compile "joda-time:joda-time:$jodatime_version" + {{/joda}} + {{#threetenbp}} + compile "org.threeten:threetenbp:$threetenbp_version" + {{/threetenbp}} + {{#usePlayWS}} + compile "com.typesafe.play:play-java-ws_2.11:$play_version" + compile "com.squareup.retrofit2:converter-jackson:$retrofit_version" + compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + compile "com.fasterxml.jackson.datatype:jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}:$jackson_version" + {{/usePlayWS}} + + testCompile "junit:junit:$junit_version" +} diff --git a/libraries/retrofit2/build.sbt.mustache b/libraries/retrofit2/build.sbt.mustache new file mode 100644 index 00000000000..66635daa973 --- /dev/null +++ b/libraries/retrofit2/build.sbt.mustache @@ -0,0 +1,52 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "com.squareup.retrofit2" % "retrofit" % "2.3.0" % "compile", + "com.squareup.retrofit2" % "converter-scalars" % "2.3.0" % "compile", + {{^usePlayWS}} + "com.squareup.retrofit2" % "converter-gson" % "2.3.0" % "compile", + {{/usePlayWS}} + {{#usePlayWS}} + {{#play24}} + "com.typesafe.play" % "play-java-ws_2.11" % "2.4.11" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.6.6" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.6.6" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.6.6" % "compile", + {{/play24}} + {{#play25}} + "com.typesafe.play" % "play-java-ws_2.11" % "2.5.15" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.7.8" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.7.8" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.7.8" % "compile", + {{/play25}} + "com.squareup.retrofit2" % "converter-jackson" % "2.3.0" % "compile", + {{/usePlayWS}} + {{#useRxJava}} + "com.squareup.retrofit2" % "adapter-rxjava" % "2.3.0" % "compile", + "io.reactivex" % "rxjava" % "1.3.0" % "compile", + {{/useRxJava}} + {{#useRxJava2}} + "com.squareup.retrofit2" % "adapter-rxjava2" % "2.3.0" % "compile", + "io.reactivex.rxjava2" % "rxjava" % "2.1.1" % "compile", + {{/useRxJava2}} + "io.swagger" % "swagger-annotations" % "1.5.17" % "compile", + "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", + {{#joda}} + "joda-time" % "joda-time" % "2.9.9" % "compile", + {{/joda}} + {{#threetenbp}} + "org.threeten" % "threetenbp" % "1.3.5" % "compile", + {{/threetenbp}} + "io.gsonfire" % "gson-fire" % "1.8.0" % "compile", + "junit" % "junit" % "4.12" % "test", + "com.novocode" % "junit-interface" % "0.11" % "test" + ) + ) diff --git a/libraries/retrofit2/formParams.mustache b/libraries/retrofit2/formParams.mustache new file mode 100644 index 00000000000..b3f54cc4ddb --- /dev/null +++ b/libraries/retrofit2/formParams.mustache @@ -0,0 +1 @@ +{{#isFormParam}}{{#notFile}}{{#isMultipart}}@retrofit2.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit2.http.Field{{/isMultipart}}("{{baseName}}") {{{dataType}}} {{paramName}}{{/notFile}}{{#isFile}}{{#isMultipart}}@retrofit2.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit2.http.Field{{/isMultipart}} MultipartBody.Part {{paramName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file diff --git a/libraries/retrofit2/formParams.mustache.save b/libraries/retrofit2/formParams.mustache.save new file mode 100644 index 00000000000..84c4704432a --- /dev/null +++ b/libraries/retrofit2/formParams.mustache.save @@ -0,0 +1 @@ +{{#isFormParam}}{{#notFile}}{{#isMultipart}}retrofit.http@retrofit2.http.Part{{/isMultipart}}{{^isMultipart}}@Field{{/isMultipart}}("{{baseName}}") {{{dataType}}} {{paramName}}{{/notFile}}{{#isFile}}{{#isMultipart}}@Part{{/isMultipart}}{{^isMultipart}}@Field{{/isMultipart}} okhttp3.MultipartBody.Part {{paramName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file diff --git a/libraries/retrofit2/headerParams.mustache b/libraries/retrofit2/headerParams.mustache new file mode 100644 index 00000000000..c7748f3bf27 --- /dev/null +++ b/libraries/retrofit2/headerParams.mustache @@ -0,0 +1 @@ +{{#isHeaderParam}}@retrofit2.http.Header("{{baseName}}") {{{dataType}}} {{paramName}}{{/isHeaderParam}} \ No newline at end of file diff --git a/libraries/retrofit2/pathParams.mustache b/libraries/retrofit2/pathParams.mustache new file mode 100644 index 00000000000..8fe7c380c41 --- /dev/null +++ b/libraries/retrofit2/pathParams.mustache @@ -0,0 +1 @@ +{{#isPathParam}}@retrofit2.http.Path("{{baseName}}") {{{dataType}}} {{paramName}}{{/isPathParam}} \ No newline at end of file diff --git a/libraries/retrofit2/play-common/auth/ApiKeyAuth.mustache b/libraries/retrofit2/play-common/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..5652db326b5 --- /dev/null +++ b/libraries/retrofit2/play-common/auth/ApiKeyAuth.mustache @@ -0,0 +1,67 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; + +import java.util.Map; +import java.util.List; + +/** + * Holds ApiKey auth info + */ +{{>generatedAnnotation}} +public class ApiKeyAuth implements Authentication { + private final String location; + private final String paramName; + + private String apiKey; + private String apiKeyPrefix; + + public ApiKeyAuth(String location, String paramName) { + this.location = location; + this.paramName = paramName; + } + + public String getLocation() { + return location; + } + + public String getParamName() { + return paramName; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + public String getApiKeyPrefix() { + return apiKeyPrefix; + } + + public void setApiKeyPrefix(String apiKeyPrefix) { + this.apiKeyPrefix = apiKeyPrefix; + } + + @Override + public void applyToParams(List queryParams, Map headerParams) { + if (apiKey == null) { + return; + } + String value; + if (apiKeyPrefix != null) { + value = apiKeyPrefix + " " + apiKey; + } else { + value = apiKey; + } + if ("query".equals(location)) { + queryParams.add(new Pair(paramName, value)); + } else if ("header".equals(location)) { + headerParams.put(paramName, value); + } + } +} diff --git a/libraries/retrofit2/play24/ApiClient.mustache b/libraries/retrofit2/play24/ApiClient.mustache new file mode 100644 index 00000000000..5c871c62073 --- /dev/null +++ b/libraries/retrofit2/play24/ApiClient.mustache @@ -0,0 +1,136 @@ +package {{invokerPackage}}; + +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.*; + +import retrofit2.Retrofit; +import retrofit2.converter.scalars.ScalarsConverterFactory; +import retrofit2.converter.jackson.JacksonConverterFactory; + +import play.libs.Json; +import play.libs.ws.WSClient; + +import {{invokerPackage}}.Play24CallAdapterFactory; +import {{invokerPackage}}.Play24CallFactory; + +import okhttp3.Interceptor; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.Authentication; + +/** + * API client + */ +public class ApiClient { + + /** Underlying HTTP-client */ + private WSClient wsClient; + + /** Supported auths */ + private Map authentications; + + /** API base path */ + private String basePath = "{{{basePath}}}"; + + public ApiClient(WSClient wsClient) { + this(); + this.wsClient = wsClient; + } + + public ApiClient() { + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap<>();{{#authMethods}}{{#isBasic}} + // authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + // authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + + } + + /** + * Creates a retrofit2 client for given API interface + */ + public S createService(Class serviceClass) { + if(!basePath.endsWith("/")) { + basePath = basePath + "/"; + } + + Map extraHeaders = new HashMap<>(); + List extraQueryParams = new ArrayList<>(); + + for (String authName : authentications.keySet()) { + Authentication auth = authentications.get(authName); + if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + + auth.applyToParams(extraQueryParams, extraHeaders); + } + + return new Retrofit.Builder() + .baseUrl(basePath) + .addConverterFactory(ScalarsConverterFactory.create()) + .addConverterFactory(JacksonConverterFactory.create(Json.mapper())) + .callFactory(new Play24CallFactory(wsClient, extraHeaders, extraQueryParams)) + .addCallAdapterFactory(new Play24CallAdapterFactory()) + .build() + .create(serviceClass); + } + + /** + * Helper method to set API base path + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Get authentications (key: authentication name, value: authentication). + */ + public Map getAuthentications() { + return authentications; + } + + /** + * Get authentication for the given name. + * + * @param authName The authentication name + * @return The authentication, null if not found + */ + public Authentication getAuthentication(String authName) { + return authentications.get(authName); + } + + /** + * Helper method to set API key value for the first API key authentication. + */ + public ApiClient setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return this; + } + } + + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + */ + public ApiClient setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return this; + } + } + + throw new RuntimeException("No API key authentication configured!"); + } + + +} + + diff --git a/libraries/retrofit2/play24/Play24CallAdapterFactory.mustache b/libraries/retrofit2/play24/Play24CallAdapterFactory.mustache new file mode 100644 index 00000000000..be7cac4a0d5 --- /dev/null +++ b/libraries/retrofit2/play24/Play24CallAdapterFactory.mustache @@ -0,0 +1,100 @@ +package {{invokerPackage}}; + +import play.libs.F; +import retrofit2.*; + +import java.lang.annotation.Annotation; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.WildcardType; + +/** + * Creates {@link CallAdapter} instances that convert {@link Call} into {@link play.libs.F.Promise} + */ +public class Play24CallAdapterFactory extends CallAdapter.Factory { + + @Override + public CallAdapter get(Type returnType, Annotation[] annotations, Retrofit retrofit) { + if (!(returnType instanceof ParameterizedType)) { + return null; + } + + ParameterizedType type = (ParameterizedType) returnType; + if (type.getRawType() != F.Promise.class) { + return null; + } + + return createAdapter((ParameterizedType) returnType); + } + + private CallAdapter> createAdapter(ParameterizedType returnType) { + Type[] types = returnType.getActualTypeArguments(); + if (types.length != 1) { + throw new IllegalStateException("Must be exactly one type parameter"); + } + + Type resultType = types[0]; + Class rawTypeParam = getRawType(resultType); + + boolean includeResponse = false; + if (rawTypeParam == Response.class) { + if (!(resultType instanceof ParameterizedType)) { + throw new IllegalStateException("Response must be parameterized" + + " as Response"); + } + resultType = ((ParameterizedType) resultType).getActualTypeArguments()[0]; + includeResponse = true; + } + + return new ValueAdapter(resultType, includeResponse); + } + + /** + * Adapter that coverts values returned by API interface into CompletionStage + */ + private static final class ValueAdapter implements CallAdapter> { + + private final Type responseType; + private final boolean includeResponse; + + ValueAdapter(Type responseType, boolean includeResponse) { + this.responseType = responseType; + this.includeResponse = includeResponse; + } + + @Override + public Type responseType() { + return responseType; + } + + @Override + public F.Promise adapt(final Call call) { + final F.RedeemablePromise promise = F.RedeemablePromise.empty(); + + call.enqueue(new Callback() { + + @Override + public void onResponse(Call call, Response response) { + if (response.isSuccessful()) { + if (includeResponse) { + promise.success((R) response); + } else { + promise.success(response.body()); + } + } else { + promise.failure(new HttpException(response)); + } + } + + @Override + public void onFailure(Call call, Throwable t) { + promise.failure(t); + } + + }); + + return promise; + } + } + +} diff --git a/libraries/retrofit2/play24/Play24CallFactory.mustache b/libraries/retrofit2/play24/Play24CallFactory.mustache new file mode 100644 index 00000000000..5572ac47619 --- /dev/null +++ b/libraries/retrofit2/play24/Play24CallFactory.mustache @@ -0,0 +1,219 @@ +package {{invokerPackage}}; + +import okhttp3.*; +import okio.Buffer; +import okio.BufferedSource; +import play.libs.F; +import play.libs.ws.WSClient; +import play.libs.ws.WSRequest; +import play.libs.ws.WSResponse; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * Creates {@link Call} instances that invoke underlying {@link WSClient} + */ +public class Play24CallFactory implements okhttp3.Call.Factory { + + /** PlayWS http client */ + private final WSClient wsClient; + + /** Extra headers to add to request */ + private Map extraHeaders = new HashMap<>(); + + /** Extra query parameters to add to request */ + private List extraQueryParams = new ArrayList<>(); + + public Play24CallFactory(WSClient wsClient) { + this.wsClient = wsClient; + } + + public Play24CallFactory(WSClient wsClient, Map extraHeaders, + List extraQueryParams) { + this.wsClient = wsClient; + + this.extraHeaders.putAll(extraHeaders); + this.extraQueryParams.addAll(extraQueryParams); + } + + @Override + public Call newCall(Request request) { + // add extra headers + Request.Builder rb = request.newBuilder(); + for (Map.Entry header : this.extraHeaders.entrySet()) { + rb.addHeader(header.getKey(), header.getValue()); + } + + // add extra query params + if (!this.extraQueryParams.isEmpty()) { + String newQuery = request.url().uri().getQuery(); + for (Pair queryParam : this.extraQueryParams) { + String param = String.format("%s=%s", queryParam.getName(), queryParam.getValue()); + if (newQuery == null) { + newQuery = param; + } else { + newQuery += "&" + param; + } + } + + URI newUri; + try { + newUri = new URI(request.url().uri().getScheme(), request.url().uri().getAuthority(), + request.url().uri().getPath(), newQuery, request.url().uri().getFragment()); + rb.url(newUri.toURL()); + } catch (MalformedURLException | URISyntaxException e) { + throw new RuntimeException("Error while updating an url", e); + } + } + + return new PlayWSCall(wsClient, rb.build()); + } + + /** + * Call implementation that delegates to Play WS Client + */ + static class PlayWSCall implements Call { + + private final WSClient wsClient; + private WSRequest wsRequest; + + private final Request request; + + public PlayWSCall(WSClient wsClient, Request request) { + this.wsClient = wsClient; + this.request = request; + } + + @Override + public Request request() { + return request; + } + + @Override + public void enqueue(final okhttp3.Callback responseCallback) { + final Call call = this; + final F.Promise promise = executeAsync(); + + promise.onRedeem(new F.Callback() { + + @Override + public void invoke(WSResponse wsResponse) throws Throwable { + responseCallback.onResponse(call, PlayWSCall.this.toWSResponse(wsResponse)); + } + + }); + + promise.onFailure(new F.Callback() { + + @Override + public void invoke(Throwable throwable) throws Throwable { + if (throwable instanceof IOException) { + responseCallback.onFailure(call, (IOException) throwable); + } else { + responseCallback.onFailure(call, new IOException(throwable)); + } + } + + }); + + } + + F.Promise executeAsync() { + try { + wsRequest = wsClient.url(request.url().uri().toString()); + addHeaders(wsRequest); + if (request.body() != null) { + addBody(wsRequest); + } + + return wsRequest.execute(request.method()); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + private void addHeaders(WSRequest wsRequest) { + for(Map.Entry> entry : request.headers().toMultimap().entrySet()) { + List values = entry.getValue(); + for (String value : values) { + wsRequest.setHeader(entry.getKey(), value); + } + } + } + + private void addBody(WSRequest wsRequest) throws IOException { + Buffer buffer = new Buffer(); + request.body().writeTo(buffer); + wsRequest.setBody(buffer.inputStream()); + wsRequest.setContentType(request.body().contentType().toString()); + } + + private Response toWSResponse(final WSResponse r) { + final Response.Builder builder = new Response.Builder(); + builder.request(request) + .code(r.getStatus()) + .body(new ResponseBody() { + + @Override + public MediaType contentType() { + return Optional.ofNullable(r.getHeader("Content-Type")) + .map(MediaType::parse) + .orElse(null); + } + + @Override + public long contentLength() { + return r.asByteArray().length; + } + + @Override + public BufferedSource source() { + return new Buffer().write(r.asByteArray()); + } + + }); + + for (Map.Entry> entry : r.getAllHeaders().entrySet()) { + for (String value : entry.getValue()) { + builder.addHeader(entry.getKey(), value); + } + } + + builder.protocol(Protocol.HTTP_1_1); + return builder.build(); + } + + @Override + public Response execute() throws IOException { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public void cancel() { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public PlayWSCall clone() { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public boolean isExecuted() { + return false; + } + + @Override + public boolean isCanceled() { + return false; + } + } +} diff --git a/libraries/retrofit2/play24/api.mustache b/libraries/retrofit2/play24/api.mustache new file mode 100644 index 00000000000..6538ed53d2f --- /dev/null +++ b/libraries/retrofit2/play24/api.mustache @@ -0,0 +1,57 @@ +package {{package}}; + +import {{invokerPackage}}.CollectionFormats.*; + +{{#useRxJava}}import rx.Observable;{{/useRxJava}} +{{#useRxJava2}}import io.reactivex.Observable;{{/useRxJava2}} +{{#doNotUseRx}}import retrofit2.Call;{{/doNotUseRx}} +import retrofit2.http.*; + +import okhttp3.RequestBody; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +import play.libs.F; +import retrofit2.Response; + +{{#operations}} +public interface {{classname}} { + {{#operation}} + /** + * {{summary}} + * {{notes}} +{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} +{{/allParams}} + * @return Call<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + */ + {{#formParams}} + {{#-first}} + {{#isMultipart}}@retrofit2.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit2.http.FormUrlEncoded{{/isMultipart}} + {{/-first}} + {{/formParams}} + {{^formParams}} + {{#prioritizedContentTypes}} + {{#-first}} + @Headers({ + "Content-Type:{{{mediaType}}}" + }) + {{/-first}} + {{/prioritizedContentTypes}} + {{/formParams}} + @{{httpMethod}}("{{{path}}}") + F.Promise> {{operationId}}({{^allParams}});{{/allParams}} + {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{#hasMore}}, {{/hasMore}}{{^hasMore}} + );{{/hasMore}}{{/allParams}} + + {{/operation}} +} +{{/operations}} diff --git a/libraries/retrofit2/play25/ApiClient.mustache b/libraries/retrofit2/play25/ApiClient.mustache new file mode 100644 index 00000000000..163afd670c1 --- /dev/null +++ b/libraries/retrofit2/play25/ApiClient.mustache @@ -0,0 +1,136 @@ +package {{invokerPackage}}; + +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.*; + +import retrofit2.Retrofit; +import retrofit2.converter.scalars.ScalarsConverterFactory; +import retrofit2.converter.jackson.JacksonConverterFactory; + +import play.libs.Json; +import play.libs.ws.WSClient; + +import {{invokerPackage}}.Play25CallAdapterFactory; +import {{invokerPackage}}.Play25CallFactory; + +import okhttp3.Interceptor; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.Authentication; + +/** + * API client + */ +public class ApiClient { + + /** Underlying HTTP-client */ + private WSClient wsClient; + + /** Supported auths */ + private Map authentications; + + /** API base path */ + private String basePath = "{{{basePath}}}"; + + public ApiClient(WSClient wsClient) { + this(); + this.wsClient = wsClient; + } + + public ApiClient() { + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap<>();{{#authMethods}}{{#isBasic}} + // authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + // authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + + } + + /** + * Creates a retrofit2 client for given API interface + */ + public S createService(Class serviceClass) { + if(!basePath.endsWith("/")) { + basePath = basePath + "/"; + } + + Map extraHeaders = new HashMap<>(); + List extraQueryParams = new ArrayList<>(); + + for (String authName : authentications.keySet()) { + Authentication auth = authentications.get(authName); + if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + + auth.applyToParams(extraQueryParams, extraHeaders); + } + + return new Retrofit.Builder() + .baseUrl(basePath) + .addConverterFactory(ScalarsConverterFactory.create()) + .addConverterFactory(JacksonConverterFactory.create(Json.mapper())) + .callFactory(new Play25CallFactory(wsClient, extraHeaders, extraQueryParams)) + .addCallAdapterFactory(new Play25CallAdapterFactory()) + .build() + .create(serviceClass); + } + + /** + * Helper method to set API base path + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Get authentications (key: authentication name, value: authentication). + */ + public Map getAuthentications() { + return authentications; + } + + /** + * Get authentication for the given name. + * + * @param authName The authentication name + * @return The authentication, null if not found + */ + public Authentication getAuthentication(String authName) { + return authentications.get(authName); + } + + /** + * Helper method to set API key value for the first API key authentication. + */ + public ApiClient setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return this; + } + } + + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + */ + public ApiClient setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return this; + } + } + + throw new RuntimeException("No API key authentication configured!"); + } + + +} + + diff --git a/libraries/retrofit2/play25/Play25CallAdapterFactory.mustache b/libraries/retrofit2/play25/Play25CallAdapterFactory.mustache new file mode 100644 index 00000000000..088c10b160a --- /dev/null +++ b/libraries/retrofit2/play25/Play25CallAdapterFactory.mustache @@ -0,0 +1,117 @@ +package {{invokerPackage}}; + +import java.util.concurrent.CompletionStage; +import retrofit2.*; + +import java.lang.annotation.Annotation; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.WildcardType; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.function.Function; + +/** + * Creates {@link CallAdapter} instances that convert {@link Call} into {@link java.util.concurrent.CompletionStage} + */ +public class Play25CallAdapterFactory extends CallAdapter.Factory { + + private Function exceptionConverter = Function.identity(); + + public Play25CallAdapterFactory() { + } + + public Play25CallAdapterFactory( + Function exceptionConverter) { + this.exceptionConverter = exceptionConverter; + } + + @Override + public CallAdapter get(Type returnType, Annotation[] annotations, Retrofit retrofit) { + if (!(returnType instanceof ParameterizedType)) { + return null; + } + + ParameterizedType type = (ParameterizedType) returnType; + if (type.getRawType() != CompletionStage.class) { + return null; + } + + return createAdapter((ParameterizedType) returnType); + } + + private CallAdapter> createAdapter(ParameterizedType returnType) { + // Get CompletionStage type argument + Type[] types = returnType.getActualTypeArguments(); + if (types.length != 1) { + throw new IllegalStateException("Must be exactly one type parameter"); + } + + Type resultType = types[0]; + Class rawTypeParam = getRawType(resultType); + + boolean includeResponse = false; + if (rawTypeParam == Response.class) { + if (!(resultType instanceof ParameterizedType)) { + throw new IllegalStateException("Response must be parameterized" + + " as Response"); + } + resultType = ((ParameterizedType) resultType).getActualTypeArguments()[0]; + includeResponse = true; + } + + return new ValueAdapter(resultType, includeResponse, exceptionConverter); + } + + /** + * Adapter that coverts values returned by API interface into CompletionStage + */ + private static final class ValueAdapter implements CallAdapter> { + + private final Type responseType; + private final boolean includeResponse; + private Function exceptionConverter; + + ValueAdapter(Type responseType, boolean includeResponse, + Function exceptionConverter) { + this.responseType = responseType; + this.includeResponse = includeResponse; + this.exceptionConverter = exceptionConverter; + } + + @Override + public Type responseType() { + return responseType; + } + + @Override + public CompletionStage adapt(final Call call) { + final CompletableFuture promise = new CompletableFuture(); + + call.enqueue(new Callback() { + + @Override + public void onResponse(Call call, Response response) { + if (response.isSuccessful()) { + if (includeResponse) { + promise.complete((R) response); + } else { + promise.complete(response.body()); + } + } else { + promise.completeExceptionally(exceptionConverter.apply(new HttpException(response))); + } + } + + @Override + public void onFailure(Call call, Throwable t) { + promise.completeExceptionally(t); + } + + }); + + return promise; + } + } +} + diff --git a/libraries/retrofit2/play25/Play25CallFactory.mustache b/libraries/retrofit2/play25/Play25CallFactory.mustache new file mode 100644 index 00000000000..93df7a2718d --- /dev/null +++ b/libraries/retrofit2/play25/Play25CallFactory.mustache @@ -0,0 +1,228 @@ +package {{invokerPackage}}; + +import okhttp3.*; +import okio.Buffer; +import okio.BufferedSource; +import play.libs.ws.WSClient; +import play.libs.ws.WSRequest; +import play.libs.ws.WSResponse; +import play.libs.ws.WSRequestFilter; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.CompletionStage; + +/** + * Creates {@link Call} instances that invoke underlying {@link WSClient} + */ +public class Play25CallFactory implements okhttp3.Call.Factory { + + /** PlayWS http client */ + private final WSClient wsClient; + + /** Extra headers to add to request */ + private Map extraHeaders = new HashMap<>(); + + /** Extra query parameters to add to request */ + private List extraQueryParams = new ArrayList<>(); + + /** Filters (interceptors) */ + private List filters = new ArrayList<>(); + + public Play25CallFactory(WSClient wsClient) { + this.wsClient = wsClient; + } + + public Play25CallFactory(WSClient wsClient, List filters) { + this.wsClient = wsClient; + this.filters.addAll(filters); + } + + public Play25CallFactory(WSClient wsClient, Map extraHeaders, + List extraQueryParams) { + this.wsClient = wsClient; + + this.extraHeaders.putAll(extraHeaders); + this.extraQueryParams.addAll(extraQueryParams); + } + + @Override + public Call newCall(Request request) { + // add extra headers + Request.Builder rb = request.newBuilder(); + for (Map.Entry header : this.extraHeaders.entrySet()) { + rb.addHeader(header.getKey(), header.getValue()); + } + + // add extra query params + if (!this.extraQueryParams.isEmpty()) { + String newQuery = request.url().uri().getQuery(); + for (Pair queryParam : this.extraQueryParams) { + String param = String.format("%s=%s", queryParam.getName(), queryParam.getValue()); + if (newQuery == null) { + newQuery = param; + } else { + newQuery += "&" + param; + } + } + + URI newUri; + try { + newUri = new URI(request.url().uri().getScheme(), request.url().uri().getAuthority(), + request.url().uri().getPath(), newQuery, request.url().uri().getFragment()); + rb.url(newUri.toURL()); + } catch (MalformedURLException | URISyntaxException e) { + throw new RuntimeException("Error while updating an url", e); + } + } + + return new PlayWSCall(wsClient, this.filters, rb.build()); + } + + /** + * Call implementation that delegates to Play WS Client + */ + static class PlayWSCall implements Call { + + private final WSClient wsClient; + private WSRequest wsRequest; + private List filters; + + private final Request request; + + public PlayWSCall(WSClient wsClient, List filters, Request request) { + this.wsClient = wsClient; + this.request = request; + this.filters = filters; + } + + @Override + public Request request() { + return request; + } + + @Override + public void enqueue(final okhttp3.Callback responseCallback) { + final Call call = this; + final CompletionStage promise = executeAsync(); + + promise.whenCompleteAsync((v, t) -> { + if (t != null) { + if (t instanceof IOException) { + responseCallback.onFailure(call, (IOException) t); + } else { + responseCallback.onFailure(call, new IOException(t)); + } + } else { + try { + responseCallback.onResponse(call, PlayWSCall.this.toWSResponse(v)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }, play.libs.concurrent.HttpExecution.defaultContext()); + } + + CompletionStage executeAsync() { + try { + wsRequest = wsClient.url(request.url().uri().toString()); + addHeaders(wsRequest); + if (request.body() != null) { + addBody(wsRequest); + } + filters.stream().forEach(f -> wsRequest.withRequestFilter(f)); + + return wsRequest.execute(request.method()); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + private void addHeaders(WSRequest wsRequest) { + for(Map.Entry> entry : request.headers().toMultimap().entrySet()) { + List values = entry.getValue(); + for (String value : values) { + wsRequest.setHeader(entry.getKey(), value); + } + } + } + + private void addBody(WSRequest wsRequest) throws IOException { + Buffer buffer = new Buffer(); + request.body().writeTo(buffer); + wsRequest.setBody(buffer.inputStream()); + + MediaType mediaType = request.body().contentType(); + if (mediaType != null) { + wsRequest.setContentType(mediaType.toString()); + } + } + + private Response toWSResponse(final WSResponse r) { + final Response.Builder builder = new Response.Builder(); + builder.request(request) + .code(r.getStatus()) + .body(new ResponseBody() { + + @Override + public MediaType contentType() { + return Optional.ofNullable(r.getHeader("Content-Type")) + .map(MediaType::parse) + .orElse(null); + } + + @Override + public long contentLength() { + return r.asByteArray().length; + } + + @Override + public BufferedSource source() { + return new Buffer().write(r.asByteArray()); + } + + }); + + for (Map.Entry> entry : r.getAllHeaders().entrySet()) { + for (String value : entry.getValue()) { + builder.addHeader(entry.getKey(), value); + } + } + + builder.protocol(Protocol.HTTP_1_1); + return builder.build(); + } + + @Override + public Response execute() throws IOException { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public void cancel() { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public PlayWSCall clone() { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public boolean isExecuted() { + return false; + } + + @Override + public boolean isCanceled() { + return false; + } + } +} diff --git a/libraries/retrofit2/play25/api.mustache b/libraries/retrofit2/play25/api.mustache new file mode 100644 index 00000000000..51b1812b49e --- /dev/null +++ b/libraries/retrofit2/play25/api.mustache @@ -0,0 +1,57 @@ +package {{package}}; + +import {{invokerPackage}}.CollectionFormats.*; + +{{#useRxJava}}import rx.Observable;{{/useRxJava}} +{{#useRxJava2}}import io.reactivex.Observable;{{/useRxJava2}} +{{#doNotUseRx}}import retrofit2.Call;{{/doNotUseRx}} +import retrofit2.http.*; + +import okhttp3.RequestBody; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +import java.util.concurrent.*; +import retrofit2.Response; + +{{#operations}} +public interface {{classname}} { + {{#operation}} + /** + * {{summary}} + * {{notes}} +{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} +{{/allParams}} + * @return Call<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + */ + {{#formParams}} + {{#-first}} + {{#isMultipart}}@retrofit2.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit2.http.FormUrlEncoded{{/isMultipart}} + {{/-first}} + {{/formParams}} + {{^formParams}} + {{#prioritizedContentTypes}} + {{#-first}} + @Headers({ + "Content-Type:{{{mediaType}}}" + }) + {{/-first}} + {{/prioritizedContentTypes}} + {{/formParams}} + @{{httpMethod}}("{{{path}}}") + CompletionStage> {{operationId}}({{^allParams}});{{/allParams}} + {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{#hasMore}}, {{/hasMore}}{{^hasMore}} + );{{/hasMore}}{{/allParams}} + + {{/operation}} +} +{{/operations}} diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache new file mode 100644 index 00000000000..3adfab68fe7 --- /dev/null +++ b/libraries/retrofit2/pom.mustache @@ -0,0 +1,361 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{artifactUrl}} + {{artifactDescription}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-core-version} + + + com.squareup.retrofit2 + converter-gson + ${retrofit-version} + + + com.squareup.retrofit2 + retrofit + ${retrofit-version} + + + com.squareup.retrofit2 + converter-scalars + ${retrofit-version} + + + org.apache.oltu.oauth2 + org.apache.oltu.oauth2.client + ${oltu-version} + + + org.apache.oltu.oauth2 + common + + + + + io.gsonfire + gson-fire + ${gson-fire-version} + + {{#joda}} + + joda-time + joda-time + ${jodatime-version} + + {{/joda}} + {{#threetenbp}} + + org.threeten + threetenbp + ${threetenbp-version} + + {{/threetenbp}} + {{#useRxJava}} + + io.reactivex + rxjava + ${rxjava-version} + + + com.squareup.retrofit2 + adapter-rxjava + ${retrofit-version} + + {{/useRxJava}} + {{#useRxJava2}} + + io.reactivex.rxjava2 + rxjava + ${rxjava-version} + + + com.squareup.retrofit2 + adapter-rxjava2 + ${retrofit-version} + + {{/useRxJava2}} + + {{#usePlayWS}} + + + com.squareup.retrofit2 + converter-jackson + ${retrofit-version} + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-version} + + + com.fasterxml.jackson.datatype + jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}} + ${jackson-version} + + {{#withXml}} + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson-version} + + + {{/withXml}} + + com.typesafe.play + play-java-ws_2.11 + ${play-version} + + {{/usePlayWS}} + + {{#parcelableModel}} + + + com.google.android + android + 4.1.1.4 + provided + + {{/parcelableModel}} + + + + junit + junit + ${junit-version} + test + + + + UTF-8 + {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}} + ${java.version} + ${java.version} + 1.8.0 + 1.5.18 + {{#usePlayWS}} + {{#play24}} + 2.6.6 + 2.4.11 + {{/play24}} + {{#play25}} + 2.7.8 + 2.5.15 + {{/play25}} + {{/usePlayWS}} + 2.3.0 + {{#useRxJava}} + 1.3.0 + {{/useRxJava}} + {{#useRxJava2}} + 2.1.1 + {{/useRxJava2}} + {{#joda}} + 2.9.9 + {{/joda}} + {{#threetenbp}} + 1.3.5 + {{/threetenbp}} + 1.0.1 + 4.12 + + diff --git a/libraries/retrofit2/queryParams.mustache b/libraries/retrofit2/queryParams.mustache new file mode 100644 index 00000000000..abb87510ecf --- /dev/null +++ b/libraries/retrofit2/queryParams.mustache @@ -0,0 +1 @@ +{{#isQueryParam}}@retrofit2.http.Query("{{baseName}}") {{#collectionFormat}}{{#isCollectionFormatMulti}}{{{dataType}}}{{/isCollectionFormatMulti}}{{^isCollectionFormatMulti}}{{{collectionFormat.toUpperCase}}}Params{{/isCollectionFormatMulti}}{{/collectionFormat}}{{^collectionFormat}}{{{dataType}}}{{/collectionFormat}} {{paramName}}{{/isQueryParam}} \ No newline at end of file diff --git a/libraries/vertx/ApiClient.mustache b/libraries/vertx/ApiClient.mustache new file mode 100644 index 00000000000..1de56ec9ca9 --- /dev/null +++ b/libraries/vertx/ApiClient.mustache @@ -0,0 +1,600 @@ +package {{invokerPackage}}; + +import {{invokerPackage}}.auth.Authentication; +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.OAuth; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import io.vertx.core.*; +import io.vertx.core.buffer.Buffer; +import io.vertx.core.file.AsyncFile; +import io.vertx.core.file.FileSystem; +import io.vertx.core.file.OpenOptions; +import io.vertx.core.http.HttpHeaders; +import io.vertx.core.http.HttpMethod; +import io.vertx.core.json.Json; +import io.vertx.core.json.JsonObject; +import io.vertx.ext.web.client.HttpRequest; +import io.vertx.ext.web.client.HttpResponse; +import io.vertx.ext.web.client.WebClient; +import io.vertx.ext.web.client.WebClientOptions; + +import java.text.DateFormat; +import java.util.*; +import java.util.function.Consumer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static java.util.stream.Collectors.toMap; + +{{>generatedAnnotation}} +public class ApiClient { + + private static final Pattern CONTENT_DISPOSITION_PATTERN = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?"); + private static final OpenOptions FILE_DOWNLOAD_OPTIONS = new OpenOptions().setCreate(true).setTruncateExisting(true); + + private final Vertx vertx; + private final JsonObject config; + private final String identifier; + + private MultiMap defaultHeaders = MultiMap.caseInsensitiveMultiMap(); + private Map authentications; + private String basePath = "{{{basePath}}}"; + private DateFormat dateFormat; + private ObjectMapper objectMapper; + private String downloadsDir = ""; + + public ApiClient(Vertx vertx, JsonObject config) { + Objects.requireNonNull(vertx, "Vertx must not be null"); + Objects.requireNonNull(config, "Config must not be null"); + + this.vertx = vertx; + + // Use RFC3339 format for date and datetime. + // See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14 + this.dateFormat = new RFC3339DateFormat(); + + // Use UTC as the default time zone. + this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + + // Build object mapper + this.objectMapper = new ObjectMapper(); + this.objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + this.objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + this.objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + this.objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + this.objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + this.objectMapper.registerModule(new JavaTimeModule()); + this.objectMapper.setDateFormat(dateFormat); + + // Setup authentications (key: authentication name, value: authentication). + this.authentications = new HashMap<>();{{#authMethods}}{{#isBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + this.authentications = Collections.unmodifiableMap(authentications); + + // Configurations + this.basePath = config.getString("basePath", this.basePath); + this.downloadsDir = config.getString("downloadsDir", this.downloadsDir); + this.config = config; + this.identifier = UUID.randomUUID().toString(); + } + + public Vertx getVertx() { + return vertx; + } + + public ObjectMapper getObjectMapper() { + return objectMapper; + } + + public ApiClient setObjectMapper(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + return this; + } + + public synchronized WebClient getWebClient() { + String webClientIdentifier = "web-client-" + identifier; + WebClient webClient = Vertx.currentContext().get(webClientIdentifier); + if (webClient == null) { + webClient = buildWebClient(vertx, config); + Vertx.currentContext().put(webClientIdentifier, webClient); + } + return webClient; + } + + public String getBasePath() { + return basePath; + } + + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + public String getDownloadsDir() { + return downloadsDir; + } + + public ApiClient setDownloadsDir(String downloadsDir) { + this.downloadsDir = downloadsDir; + return this; + } + + public MultiMap getDefaultHeaders() { + return defaultHeaders; + } + + public ApiClient addDefaultHeader(String key, String value) { + defaultHeaders.add(key, value); + return this; + } + + /** + * Get authentications (key: authentication name, value: authentication). + * + * @return Map of authentication object + */ + public Map getAuthentications() { + return authentications; + } + + /** + * Get authentication for the given name. + * + * @param authName The authentication name + * @return The authentication, null if not found + */ + public Authentication getAuthentication(String authName) { + return authentications.get(authName); + } + + /** + * Helper method to set username for the first HTTP basic authentication. + * + * @param username Username + */ + public ApiClient setUsername(String username) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setUsername(username); + return this; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set password for the first HTTP basic authentication. + * + * @param password Password + */ + public ApiClient setPassword(String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setPassword(password); + return this; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set API key value for the first API key authentication. + * + * @param apiKey API key + */ + public ApiClient setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return this; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + * + * @param apiKeyPrefix API key prefix + */ + public ApiClient setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return this; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set access token for the first OAuth2 authentication. + * + * @param accessToken Access token + */ + public ApiClient setAccessToken(String accessToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setAccessToken(accessToken); + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Format the given Date object into string. + * + * @param date Date + * @return Date in string format + */ + public String formatDate(Date date) { + return dateFormat.format(date); + } + + /** + * Format the given parameter object into string. + * + * @param param Object + * @return Object in string format + */ + public String parameterToString(Object param) { + if (param == null) { + return ""; + } else if (param instanceof Date) { + return formatDate((Date) param); + } else if (param instanceof Collection) { + StringBuilder b = new StringBuilder(); + for (Object o : (Collection) param) { + if (b.length() > 0) { + b.append(','); + } + b.append(String.valueOf(o)); + } + return b.toString(); + } else { + return String.valueOf(param); + } + } + + /* + * Format to {@code Pair} objects. + * @param collectionFormat Collection format + * @param name Name + * @param value Value + * @return List of pairs + */ + public List parameterToPairs(String collectionFormat, String name, Object value) { + List params = new ArrayList(); + + // preconditions + if (name == null || name.isEmpty() || value == null) return params; + + Collection valueCollection; + if (value instanceof Collection) { + valueCollection = (Collection) value; + } else { + params.add(new Pair(name, parameterToString(value))); + return params; + } + + if (valueCollection.isEmpty()) { + return params; + } + + // get the collection format (default: csv) + String format = (collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat); + + // create the params based on the collection format + if ("multi".equals(format)) { + for (Object item : valueCollection) { + params.add(new Pair(name, parameterToString(item))); + } + return params; + } + + String delimiter = ","; + if ("csv".equals(format)) { + delimiter = ","; + } else if ("ssv".equals(format)) { + delimiter = " "; + } else if ("tsv".equals(format)) { + delimiter = "\t"; + } else if ("pipes".equals(format)) { + delimiter = "|"; + } + + StringBuilder sb = new StringBuilder(); + for (Object item : valueCollection) { + sb.append(delimiter); + sb.append(parameterToString(item)); + } + + params.add(new Pair(name, sb.substring(1))); + + return params; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * application/vnd.company+json + * + * @param mime MIME + * @return True if the MIME type is JSON + */ + private boolean isJsonMime(String mime) { + String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$"; + return mime != null && (mime.matches(jsonMime) || mime.equalsIgnoreCase("application/json-patch+json")); + } + + /** + * Select the Accept header's value from the given accepts array: + * if JSON exists in the given array, use it; + * otherwise use all of them (joining into a string) + * + * @param accepts The accepts array to select from + * @return The Accept header to use. If the given array is empty, + * null will be returned (not to set the Accept header explicitly). + */ + protected String selectHeaderAccept(String[] accepts) { + if (accepts.length == 0) { + return null; + } + for (String accept : accepts) { + if (isJsonMime(accept)) { + return accept; + } + } + return StringUtil.join(accepts, ","); + } + + /** + * Select the Content-Type header's value from the given array: + * if JSON exists in the given array, use it; + * otherwise use the first one of the array. + * + * @param contentTypes The Content-Type array to select from + * @return The Content-Type header to use. If the given array is empty, + * JSON will be used. + */ + protected String selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0) { + return "application/json"; + } + for (String contentType : contentTypes) { + if (isJsonMime(contentType)) { + return contentType; + } + } + return contentTypes[0]; + } + + public void sendBody(HttpRequest request, + Handler>> responseHandler, + Object body) { + if (body instanceof byte[]) { + Buffer buffer = Buffer.buffer((byte[]) body); + request.sendBuffer(buffer, responseHandler); + } else if (body instanceof AsyncFile) { + AsyncFile file = (AsyncFile) body; + request.sendStream(file, responseHandler); + } else { + request.sendJson(body, responseHandler); + } + } + + /** + * Invoke API by sending HTTP request with the given options. + * + * @param Type + * @param path The sub-path of the HTTP URL + * @param method The request method, one of "GET", "POST", "PUT", "HEAD" and "DELETE" + * @param queryParams The query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param formParams The form parameters + * @param accepts The request's Accept headers + * @param contentTypes The request's Content-Type headers + * @param authNames The authentications to apply + * @param returnType The return type into which to deserialize the response + * @param resultHandler The asynchronous response handler + */ + public void invokeAPI(String path, String method, List queryParams, Object body, MultiMap headerParams, + Map formParams, String[] accepts, String[] contentTypes, String[] authNames, + TypeReference returnType, Handler> resultHandler) { + + updateParamsForAuth(authNames, queryParams, headerParams); + + if (accepts != null) { + headerParams.add(HttpHeaders.ACCEPT, selectHeaderAccept(accepts)); + } + + if (contentTypes != null) { + headerParams.add(HttpHeaders.CONTENT_TYPE, selectHeaderContentType(contentTypes)); + } + + HttpMethod httpMethod = HttpMethod.valueOf(method); + HttpRequest request = getWebClient().requestAbs(httpMethod, basePath + path); + + if (httpMethod == HttpMethod.PATCH) { + request.putHeader("X-HTTP-Method-Override", "PATCH"); + } + + queryParams.forEach(entry -> { + if (entry.getValue() != null) { + request.addQueryParam(entry.getName(), entry.getValue()); + } + }); + + headerParams.forEach(entry -> { + if (entry.getValue() != null) { + request.putHeader(entry.getKey(), entry.getValue()); + } + }); + + defaultHeaders.forEach(entry -> { + if (entry.getValue() != null) { + request.putHeader(entry.getKey(), entry.getValue()); + } + }); + + Handler>> responseHandler = buildResponseHandler(returnType, resultHandler); + if (body != null) { + sendBody(request, responseHandler, body); + } else if (formParams != null && !formParams.isEmpty()) { + Map formMap = formParams.entrySet().stream().collect(toMap(Map.Entry::getKey, entry -> parameterToString(entry.getValue()))); + MultiMap form = MultiMap.caseInsensitiveMultiMap().addAll(formMap); + request.sendForm(form, responseHandler); + } else { + request.send(responseHandler); + } + } + + /** + * Sanitize filename by removing path. + * e.g. ../../sun.gif becomes sun.gif + * + * @param filename The filename to be sanitized + * @return The sanitized filename + */ + protected String sanitizeFilename(String filename) { + return filename.replaceAll(".*[/\\\\]", ""); + } + + /** + * Create a filename from the given headers. + * When the headers have no "Content-Disposition" information, a random UUID name is generated. + * + * @param headers The HTTP response headers + * @return The filename + */ + protected String generateFilename(MultiMap headers) { + String filename = UUID.randomUUID().toString(); + String contentDisposition = headers.get("Content-Disposition"); + if (contentDisposition != null && !contentDisposition.isEmpty()) { + Matcher matcher = CONTENT_DISPOSITION_PATTERN.matcher(contentDisposition); + if (matcher.find()) { + filename = sanitizeFilename(matcher.group(1)); + } + } + return filename; + } + + /** + * File Download handling. + * + * @param response The HTTP response + * @param handler The response handler + */ + protected void handleFileDownload(HttpResponse response, Handler> handler) { + FileSystem fs = getVertx().fileSystem(); + + String filename = generateFilename(response.headers()); + Consumer fileHandler = directory -> { + fs.open(directory + filename, FILE_DOWNLOAD_OPTIONS, asyncFileResult -> { + if (asyncFileResult.succeeded()) { + AsyncFile asyncFile = asyncFileResult.result(); + asyncFile.write(response.bodyAsBuffer()); + //noinspection unchecked + handler.handle(Future.succeededFuture((T) asyncFile)); + } else { + handler.handle(ApiException.fail(asyncFileResult.cause())); + } + }); + }; + + String dir = getDownloadsDir(); + if (dir != null && !dir.isEmpty()) { + fs.mkdirs(dir, mkdirResult -> { + String sanitizedFolder = dir.endsWith("/") ? dir : dir + "/"; + fileHandler.accept(sanitizedFolder); + }); + } else { + fileHandler.accept(""); + } + } + + /** + * Build a response handler for the HttpResponse. + * + * @param returnType The return type + * @param handler The response handler + * @return The HTTP response handler + */ + protected Handler>> buildResponseHandler(TypeReference returnType, + Handler> handler) { + return response -> { + AsyncResult result; + if (response.succeeded()) { + HttpResponse httpResponse = response.result(); + if (httpResponse.statusCode() / 100 == 2) { + if (httpResponse.statusCode() == 204 || returnType == null) { + result = Future.succeededFuture(null); + } else { + T resultContent; + if ("byte[]".equals(returnType.getType().toString())) { + resultContent = (T) httpResponse.body().getBytes(); + } else if (AsyncFile.class.equals(returnType.getType())) { + handleFileDownload(httpResponse, handler); + return; + } else { + resultContent = Json.decodeValue(httpResponse.body(), returnType); + } + result = Future.succeededFuture(resultContent); + } + } else { + result = ApiException.fail(httpResponse.statusMessage(), httpResponse.statusCode(), httpResponse.headers(), httpResponse.bodyAsString()); + } + } else if (response.cause() instanceof ApiException) { + result = Future.failedFuture(response.cause()); + } else { + result = ApiException.fail(500, response.cause() != null ? response.cause().getMessage() : null); + } + handler.handle(result); + }; + } + + /** + * Build the WebClient used to make HTTP requests. + * + * @param vertx Vertx + * @return WebClient + */ + protected WebClient buildWebClient(Vertx vertx, JsonObject config) { + + if (!config.containsKey("userAgent")) { + config.put("userAgent", "{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}Swagger-Codegen/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + } + + return WebClient.create(vertx, new WebClientOptions(config)); + } + + + /** + * Update query and header parameters based on authentication settings. + * + * @param authNames The authentications to apply + */ + protected void updateParamsForAuth(String[] authNames, List queryParams, MultiMap headerParams) { + for (String authName : authNames) { + Authentication auth = authentications.get(authName); + if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + auth.applyToParams(queryParams, headerParams); + } + } +} \ No newline at end of file diff --git a/libraries/vertx/Configuration.mustache b/libraries/vertx/Configuration.mustache new file mode 100644 index 00000000000..17710ae1600 --- /dev/null +++ b/libraries/vertx/Configuration.mustache @@ -0,0 +1,42 @@ +package {{invokerPackage}}; + +import io.vertx.core.Vertx; +import io.vertx.core.json.JsonObject; + +import java.util.Objects; + +public class Configuration { + + private static ApiClient defaultApiClient = null; + + /** + * Setup the default API client. + * Will be used by API instances when a client is not provided. + * + * @return Default API client + */ + public synchronized static ApiClient setupDefaultApiClient(Vertx vertx, JsonObject config) { + defaultApiClient = new ApiClient(vertx, config); + return defaultApiClient; + } + + /** + * Get the default API client, which would be used when creating API + * instances without providing an API client. + * + * @return Default API client + */ + public synchronized static ApiClient getDefaultApiClient() { + return defaultApiClient; + } + + /** + * Set the default API client, which would be used when creating API + * instances without providing an API client. + * + * @param apiClient API client + */ + public synchronized static void setDefaultApiClient(ApiClient apiClient) { + defaultApiClient = apiClient; + } +} diff --git a/libraries/vertx/api.mustache b/libraries/vertx/api.mustache new file mode 100644 index 00000000000..dcf9df4cc70 --- /dev/null +++ b/libraries/vertx/api.mustache @@ -0,0 +1,19 @@ +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} +import io.vertx.core.AsyncResult; +import io.vertx.core.Handler; +import io.vertx.core.json.JsonObject; + +import java.util.*; + +public interface {{classname}} { + + {{#operations}} + {{#operation}} + void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}Handler> handler); + + {{/operation}} + {{/operations}} +} diff --git a/libraries/vertx/apiException.mustache b/libraries/vertx/apiException.mustache new file mode 100644 index 00000000000..6e9bbdbb88d --- /dev/null +++ b/libraries/vertx/apiException.mustache @@ -0,0 +1,110 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import io.vertx.core.AsyncResult; +import io.vertx.core.Future; +import io.vertx.core.MultiMap; + +{{>generatedAnnotation}} +public class ApiException extends{{#useRuntimeException}} RuntimeException {{/useRuntimeException}}{{^useRuntimeException}} Exception {{/useRuntimeException}}{ + private int code = 0; + private MultiMap responseHeaders = null; + private String responseBody = null; + + + public static AsyncResult fail(int failureCode, String message) { + return Future.failedFuture(new ApiException(failureCode, message)); + } + + public static AsyncResult fail(Throwable throwable) { + return Future.failedFuture(new ApiException(throwable)); + } + + public static AsyncResult fail(String message) { + return Future.failedFuture(new ApiException(message)); + } + + public static AsyncResult fail(String message, Throwable throwable, int code, MultiMap responseHeaders) { + return Future.failedFuture(new ApiException(message, throwable, code, responseHeaders, null)); + } + + public static AsyncResult fail(String message, Throwable throwable, int code, MultiMap responseHeaders, String responseBody) { + return Future.failedFuture(new ApiException(message, throwable, code, responseHeaders, responseBody)); + } + + public static AsyncResult fail(String message, int code, MultiMap responseHeaders, String responseBody) { + return Future.failedFuture(new ApiException(message, (Throwable) null, code, responseHeaders, responseBody)); + } + + public static AsyncResult fail(int code, MultiMap responseHeaders, String responseBody) { + return Future.failedFuture(new ApiException((String) null, (Throwable) null, code, responseHeaders, responseBody)); + } + + public ApiException() {} + + public ApiException(Throwable throwable) { + super(throwable); + } + + public ApiException(String message) { + super(message); + } + + public ApiException(String message, Throwable throwable, int code, MultiMap responseHeaders, String responseBody) { + super(message, throwable); + this.code = code; + this.responseHeaders = responseHeaders; + this.responseBody = responseBody; + } + + public ApiException(String message, int code, MultiMap responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(String message, Throwable throwable, int code, MultiMap responseHeaders) { + this(message, throwable, code, responseHeaders, null); + } + + public ApiException(int code, MultiMap responseHeaders, String responseBody) { + this((String) null, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(int code, String message) { + super(message); + this.code = code; + } + + public ApiException(int code, String message, MultiMap responseHeaders, String responseBody) { + this(code, message); + this.responseHeaders = responseHeaders; + this.responseBody = responseBody; + } + + /** + * Get the HTTP status code. + * + * @return HTTP status code + */ + public int getCode() { + return code; + } + + /** + * Get the HTTP response headers. + * + * @return A map of list of string + */ + public MultiMap getResponseHeaders() { + return responseHeaders; + } + + /** + * Get the HTTP response body. + * + * @return Response body in the form of string + */ + public String getResponseBody() { + return responseBody; + } +} diff --git a/libraries/vertx/apiImpl.mustache b/libraries/vertx/apiImpl.mustache new file mode 100644 index 00000000000..f4b5a723922 --- /dev/null +++ b/libraries/vertx/apiImpl.mustache @@ -0,0 +1,91 @@ +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} + +import io.vertx.core.AsyncResult; +import io.vertx.core.Handler; +import io.vertx.core.MultiMap; +import io.vertx.core.json.JsonObject; + +import com.fasterxml.jackson.core.type.TypeReference; + +import java.util.*; + +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.Configuration; +import {{invokerPackage}}.Pair; + +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}}Impl implements {{classname}} { + + private ApiClient {{localVariablePrefix}}apiClient; + + public {{classname}}Impl() { + this(null); + } + + public {{classname}}Impl(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient != null ? apiClient : Configuration.getDefaultApiClient(); + } + + public ApiClient getApiClient() { + return {{localVariablePrefix}}apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + {{#operation}} + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @param resultHandler Asynchronous result handler + */ + public void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}Handler> resultHandler) { + Object {{localVariablePrefix}}localVarBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + resultHandler.handle(ApiException.fail(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}")); + return; + } + {{/required}}{{/allParams}} + // create path and map variables + String {{localVariablePrefix}}localVarPath = "{{{path}}}"{{#pathParams}}.replaceAll("\\{" + "{{baseName}}" + "\\}", {{{paramName}}}.toString()){{/pathParams}}; + + // query params + List {{localVariablePrefix}}localVarQueryParams = new ArrayList<>(); + {{#queryParams}} + {{localVariablePrefix}}localVarQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); + {{/queryParams}} + + // header params + MultiMap {{localVariablePrefix}}localVarHeaderParams = MultiMap.caseInsensitiveMultiMap(); + {{#headerParams}}if ({{paramName}} != null) + {{localVariablePrefix}}localVarHeaderParams.add("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}})); + {{/headerParams}} + + // form params + // TODO: sending files within multipart/form-data is not supported yet (because of vertx web-client) + Map {{localVariablePrefix}}localVarFormParams = new HashMap<>(); + {{#formParams}}if ({{paramName}} != null) {{localVariablePrefix}}localVarFormParams.put("{{baseName}}", {{paramName}}); + {{/formParams}} + + String[] {{localVariablePrefix}}localVarAccepts = { {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }; + String[] {{localVariablePrefix}}localVarContentTypes = { {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} }; + String[] {{localVariablePrefix}}localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + {{#returnType}} + TypeReference<{{{returnType}}}> {{localVariablePrefix}}localVarReturnType = new TypeReference<{{{returnType}}}>() {}; + {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccepts, {{localVariablePrefix}}localVarContentTypes, {{localVariablePrefix}}localVarAuthNames, {{localVariablePrefix}}localVarReturnType, resultHandler);{{/returnType}}{{^returnType}} + {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccepts, {{localVariablePrefix}}localVarContentTypes, {{localVariablePrefix}}localVarAuthNames, null, resultHandler);{{/returnType}} + } + {{/operation}} +} +{{/operations}} diff --git a/libraries/vertx/api_test.mustache b/libraries/vertx/api_test.mustache new file mode 100644 index 00000000000..753df13cd1d --- /dev/null +++ b/libraries/vertx/api_test.mustache @@ -0,0 +1,70 @@ +{{>licenseInfo}} +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} + +import {{invokerPackage}}.Configuration; + +import org.junit.Test; +import org.junit.Ignore; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.runner.RunWith; + +import io.vertx.core.AsyncResult; +import io.vertx.core.Handler; +import io.vertx.core.json.JsonObject; +import io.vertx.core.Vertx; +import io.vertx.ext.unit.junit.VertxUnitRunner; +import io.vertx.ext.unit.junit.RunTestOnContext; +import io.vertx.ext.unit.TestContext; +import io.vertx.ext.unit.Async; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +@RunWith(VertxUnitRunner.class) +@Ignore +public class {{classname}}Test { + + private {{classname}} api; + + @Rule + public RunTestOnContext rule = new RunTestOnContext(); + + @BeforeClass + public void setupApiClient() { + JsonObject config = new JsonObject(); + Vertx vertx = rule.vertx(); + Configuration.setupDefaultApiClient(vertx, config); + + api = new {{classname}}Impl(); + } + {{#operations}}{{#operation}} + /** + * {{summary}} + * {{notes}} + * + * @param context Vertx test context for doing assertions + */ + @Test + public void {{operationId}}Test(TestContext context) { + Async async = context.async(); + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + api.{{operationId}}({{#allParams}}{{paramName}}, {{/allParams}}result -> { + // TODO: test validations + async.complete(); + }); + } + {{/operation}}{{/operations}} +} \ No newline at end of file diff --git a/libraries/vertx/auth/ApiKeyAuth.mustache b/libraries/vertx/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..43b1866e460 --- /dev/null +++ b/libraries/vertx/auth/ApiKeyAuth.mustache @@ -0,0 +1,64 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import io.vertx.core.MultiMap; + +import java.util.List; + +{{>generatedAnnotation}} +public class ApiKeyAuth implements Authentication { + private final String location; + private final String paramName; + + private String apiKey; + private String apiKeyPrefix; + + public ApiKeyAuth(String location, String paramName) { + this.location = location; + this.paramName = paramName; + } + + public String getLocation() { + return location; + } + + public String getParamName() { + return paramName; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + public String getApiKeyPrefix() { + return apiKeyPrefix; + } + + public void setApiKeyPrefix(String apiKeyPrefix) { + this.apiKeyPrefix = apiKeyPrefix; + } + + @Override + public void applyToParams(List queryParams, MultiMap headerParams) { + if (apiKey == null) { + return; + } + String value; + if (apiKeyPrefix != null) { + value = apiKeyPrefix + " " + apiKey; + } else { + value = apiKey; + } + if ("query".equals(location)) { + queryParams.add(new Pair(paramName, value)); + } else if ("header".equals(location)) { + headerParams.add(paramName, value); + } + } +} diff --git a/libraries/vertx/auth/Authentication.mustache b/libraries/vertx/auth/Authentication.mustache new file mode 100644 index 00000000000..5dccb93f2ac --- /dev/null +++ b/libraries/vertx/auth/Authentication.mustache @@ -0,0 +1,18 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import io.vertx.core.MultiMap; + +import java.util.List; + +public interface Authentication { + /** + * Apply authentication settings to header and query params. + * + * @param queryParams List of query parameters + * @param headerParams Map of header parameters + */ + void applyToParams(List queryParams, MultiMap headerParams); +} diff --git a/libraries/vertx/auth/HttpBasicAuth.mustache b/libraries/vertx/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..43862b508b6 --- /dev/null +++ b/libraries/vertx/auth/HttpBasicAuth.mustache @@ -0,0 +1,40 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import io.vertx.core.MultiMap; +import java.util.Base64; +import java.nio.charset.StandardCharsets; +import java.util.List; + +{{>generatedAnnotation}} +public class HttpBasicAuth implements Authentication { + private String username; + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public void applyToParams(List queryParams, MultiMap headerParams) { + if (username == null && password == null) { + return; + } + String str = (username == null ? "" : username) + ":" + (password == null ? "" : password); + headerParams.add("Authorization", "Basic " + Base64.getEncoder().encodeToString(str.getBytes(StandardCharsets.UTF_8))); + } +} diff --git a/libraries/vertx/auth/OAuth.mustache b/libraries/vertx/auth/OAuth.mustache new file mode 100644 index 00000000000..f3c5b34ee11 --- /dev/null +++ b/libraries/vertx/auth/OAuth.mustache @@ -0,0 +1,28 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import io.vertx.core.MultiMap; + +import java.util.List; + +{{>generatedAnnotation}} +public class OAuth implements Authentication { + private String accessToken; + + public String getAccessToken() { + return accessToken; + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + @Override + public void applyToParams(List queryParams, MultiMap headerParams) { + if (accessToken != null) { + headerParams.add("Authorization", "Bearer " + accessToken); + } + } +} diff --git a/libraries/vertx/auth/OAuthFlow.mustache b/libraries/vertx/auth/OAuthFlow.mustache new file mode 100644 index 00000000000..002e9572f33 --- /dev/null +++ b/libraries/vertx/auth/OAuthFlow.mustache @@ -0,0 +1,7 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +public enum OAuthFlow { + accessCode, implicit, password, application +} diff --git a/libraries/vertx/build.gradle.mustache b/libraries/vertx/build.gradle.mustache new file mode 100644 index 00000000000..e1c956d5f72 --- /dev/null +++ b/libraries/vertx/build.gradle.mustache @@ -0,0 +1,53 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +repositories { + jcenter() +} + +apply plugin: 'java' +apply plugin: 'maven' + +sourceCompatibility = JavaVersion.VERSION_1_8 +targetCompatibility = JavaVersion.VERSION_1_8 + +install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } +} + +task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath +} + +ext { + swagger_annotations_version = "1.5.17" + jackson_version = "{{^threetenbp}}2.8.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" + vertx_version = "3.4.2" + junit_version = "4.12" +} + +dependencies { + compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "io.vertx:vertx-web-client:$vertx_version" + compile "io.vertx:vertx-rx-java:$vertx_version" + compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + {{#joda}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + {{/joda}} + {{#java8}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{/java8}} + {{#threetenbp}} + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_version" + {{/threetenbp}} + testCompile "junit:junit:$junit_version" + testCompile "io.vertx:vertx-unit:$vertx_version" +} diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache new file mode 100644 index 00000000000..d524edeaa94 --- /dev/null +++ b/libraries/vertx/pom.mustache @@ -0,0 +1,279 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{artifactUrl}} + {{artifactDescription}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.6 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.0.0 + + + add_sources + generate-sources + + add-source + + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-core-version} + + + + + io.vertx + vertx-rx-java + ${vertx-version} + + + io.vertx + vertx-web-client + ${vertx-version} + + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-version} + + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + {{/joda}} + {{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{/java8}} + {{#threetenbp}} + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${jackson-version} + + {{/threetenbp}} + + + + junit + junit + ${junit-version} + test + + + io.vertx + vertx-unit + ${vertx-version} + test + + + + + UTF-8 + 3.4.2 + 1.5.18 + {{^threetenbp}}2.8.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} + 4.12 + + diff --git a/libraries/vertx/rxApiImpl.mustache b/libraries/vertx/rxApiImpl.mustache new file mode 100644 index 00000000000..09ca96895d6 --- /dev/null +++ b/libraries/vertx/rxApiImpl.mustache @@ -0,0 +1,58 @@ +package {{package}}.rxjava; + +{{#imports}}import {{import}}; +{{/imports}} + +import java.util.*; + +import rx.Single; +import io.vertx.core.AsyncResult; +import io.vertx.core.Handler; + +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}} { + + private final {{package}}.{{classname}} delegate; + + public {{classname}}({{package}}.{{classname}} delegate) { + this.delegate = delegate; + } + + public {{package}}.{{classname}} getDelegate() { + return delegate; + } + + {{#operation}} + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @param resultHandler Asynchronous result handler + */ + public void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}Handler> resultHandler) { + delegate.{{operationId}}({{#allParams}}{{paramName}}, {{/allParams}}resultHandler); + } + + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @return Asynchronous result handler (RxJava Single) + */ + public Single<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> rx{{operationIdCamelCase}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) { + return Single.create(new io.vertx.rx.java.SingleOnSubscribeAdapter<>(fut -> { + delegate.{{operationId}}({{#allParams}}{{paramName}}, {{/allParams}}fut); + })); + } + {{/operation}} + + public static {{classname}} newInstance({{package}}.{{classname}} arg) { + return arg != null ? new {{classname}}(arg) : null; + } +} +{{/operations}} diff --git a/licenseInfo.mustache b/licenseInfo.mustache new file mode 100644 index 00000000000..94c36dda3af --- /dev/null +++ b/licenseInfo.mustache @@ -0,0 +1,11 @@ +/* + * {{{appName}}} + * {{{appDescription}}} + * + * {{#version}}OpenAPI spec version: {{{version}}}{{/version}} + * {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}} + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ diff --git a/manifest.mustache b/manifest.mustache new file mode 100644 index 00000000000..f44bd07d0a0 --- /dev/null +++ b/manifest.mustache @@ -0,0 +1,3 @@ + + + diff --git a/model.mustache b/model.mustache new file mode 100644 index 00000000000..a42a1359e4d --- /dev/null +++ b/model.mustache @@ -0,0 +1,39 @@ +{{>licenseInfo}} + +package {{package}}; + +{{^supportJava6}} +import java.util.Objects; +import java.util.Arrays; +{{/supportJava6}} +{{#supportJava6}} +import org.apache.commons.lang3.ObjectUtils; +{{/supportJava6}} +{{#imports}} +import {{import}}; +{{/imports}} +{{#serializableModel}} +import java.io.Serializable; +{{/serializableModel}} +{{#jackson}} +{{#withXml}} +import com.fasterxml.jackson.dataformat.xml.annotation.*; +{{/withXml}} +{{/jackson}} +{{#withXml}} +import javax.xml.bind.annotation.*; +{{/withXml}} +{{#parcelableModel}} +import android.os.Parcelable; +import android.os.Parcel; +{{/parcelableModel}} +{{#useBeanValidation}} +import javax.validation.constraints.*; +import javax.validation.Valid; +{{/useBeanValidation}} + +{{#models}} +{{#model}} +{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{>pojo}}{{/isEnum}} +{{/model}} +{{/models}} diff --git a/modelEnum.mustache b/modelEnum.mustache new file mode 100644 index 00000000000..209d310172b --- /dev/null +++ b/modelEnum.mustache @@ -0,0 +1,68 @@ +{{#jackson}} +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +{{/jackson}} +{{#gson}} +import java.io.IOException; +import com.google.gson.TypeAdapter; +import com.google.gson.annotations.JsonAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +{{/gson}} + +/** + * {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}} + */ +{{#gson}} +@JsonAdapter({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.Adapter.class) +{{/gson}} +public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} { + {{#allowableValues}}{{#enumVars}} + {{{name}}}({{{value}}}){{^-last}}, + {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}} + + private {{{dataType}}} value; + + {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}({{{dataType}}} value) { + this.value = value; + } + +{{#jackson}} + @JsonValue +{{/jackson}} + public {{{dataType}}} getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + +{{#jackson}} + @JsonCreator +{{/jackson}} + public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue(String text) { + for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + if (String.valueOf(b.value).equals(text)) { + return b; + } + } + return null; + } +{{#gson}} + + public static class Adapter extends TypeAdapter<{{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}> { + @Override + public void write(final JsonWriter jsonWriter, final {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} enumeration) throws IOException { + jsonWriter.value(enumeration.getValue()); + } + + @Override + public {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException { + {{{dataType}}} value = jsonReader.{{#isInteger}}nextInt(){{/isInteger}}{{^isInteger}}next{{{dataType}}}(){{/isInteger}}; + return {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue(String.valueOf(value)); + } + } +{{/gson}} +} diff --git a/modelInnerEnum.mustache b/modelInnerEnum.mustache new file mode 100644 index 00000000000..e7ffa65d130 --- /dev/null +++ b/modelInnerEnum.mustache @@ -0,0 +1,59 @@ + /** + * {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}} + */ +{{#gson}} + @JsonAdapter({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.Adapter.class) +{{/gson}} + public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} { + {{#allowableValues}} + {{#enumVars}} + {{{name}}}({{{value}}}){{^-last}}, + {{/-last}}{{#-last}};{{/-last}} + {{/enumVars}} + {{/allowableValues}} + + private {{{datatype}}} value; + + {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}({{{datatype}}} value) { + this.value = value; + } + +{{#jackson}} + @JsonValue +{{/jackson}} + public {{{datatype}}} getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + +{{#jackson}} + @JsonCreator +{{/jackson}} + public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue(String text) { + for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + if (String.valueOf(b.value).equals(text)) { + return b; + } + } + return null; + } +{{#gson}} + + public static class Adapter extends TypeAdapter<{{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}> { + @Override + public void write(final JsonWriter jsonWriter, final {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} enumeration) throws IOException { + jsonWriter.value(enumeration.getValue()); + } + + @Override + public {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException { + {{{datatype}}} value = jsonReader.{{#isInteger}}nextInt(){{/isInteger}}{{^isInteger}}next{{{datatype}}}(){{/isInteger}}; + return {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue(String.valueOf(value)); + } + } +{{/gson}} + } diff --git a/model_doc.mustache b/model_doc.mustache new file mode 100644 index 00000000000..658df8d5322 --- /dev/null +++ b/model_doc.mustache @@ -0,0 +1,3 @@ +{{#models}}{{#model}} +{{#isEnum}}{{>enum_outer_doc}}{{/isEnum}}{{^isEnum}}{{>pojo_doc}}{{/isEnum}} +{{/model}}{{/models}} diff --git a/pojo.mustache b/pojo.mustache new file mode 100644 index 00000000000..5bbeef075ba --- /dev/null +++ b/pojo.mustache @@ -0,0 +1,242 @@ +/** + * {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}} + */{{#description}} +@ApiModel(description = "{{{description}}}"){{/description}} +{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} +public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcelableModel}}implements Parcelable {{#serializableModel}}, Serializable {{/serializableModel}}{{/parcelableModel}}{{^parcelableModel}}{{#serializableModel}}implements Serializable {{/serializableModel}}{{/parcelableModel}}{ +{{#serializableModel}} + private static final long serialVersionUID = 1L; + +{{/serializableModel}} + {{#vars}} + {{#isEnum}} + {{^isContainer}} +{{>modelInnerEnum}} + {{/isContainer}} + {{/isEnum}} + {{#items.isEnum}} + {{#items}} + {{^isContainer}} +{{>modelInnerEnum}} + {{/isContainer}} + {{/items}} + {{/items.isEnum}} + {{#jackson}} + @JsonProperty("{{baseName}}") + {{#withXml}} + {{^isContainer}} + @JacksonXmlProperty({{#isXmlAttribute}}isAttribute = true, {{/isXmlAttribute}}{{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}localName = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isContainer}} + {{#isContainer}} + {{#isXmlWrapped}} + // items.xmlName={{items.xmlName}} + @JacksonXmlElementWrapper(useWrapping = {{isXmlWrapped}}, {{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}localName = "{{#items.xmlName}}{{items.xmlName}}{{/items.xmlName}}{{^items.xmlName}}{{items.baseName}}{{/items.xmlName}}") + {{/isXmlWrapped}} + {{/isContainer}} + {{/withXml}} + {{/jackson}} + {{#withXml}} + {{#isXmlAttribute}} + @XmlAttribute(name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlAttribute}} + {{^isXmlAttribute}} + {{^isContainer}} + @XmlElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isContainer}} + {{#isContainer}} + // Is a container wrapped={{isXmlWrapped}} + {{#items}} + // items.name={{name}} items.baseName={{baseName}} items.xmlName={{xmlName}} items.xmlNamespace={{xmlNamespace}} + // items.example={{example}} items.type={{datatype}} + @XmlElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/items}} + {{#isXmlWrapped}} + @XmlElementWrapper({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlWrapped}} + {{/isContainer}} + {{/isXmlAttribute}} + {{/withXml}} + {{#gson}} + @SerializedName("{{baseName}}") + {{/gson}} + {{#isContainer}} + private {{{datatypeWithEnum}}} {{name}}{{#required}} = {{{defaultValue}}}{{/required}}{{^required}} = null{{/required}}; + {{/isContainer}} + {{^isContainer}} + private {{{datatypeWithEnum}}} {{name}} = {{{defaultValue}}}; + {{/isContainer}} + + {{/vars}} + {{#gson}} + {{#discriminator}} + public {{classname}}() { + this.{{discriminator}} = this.getClass().getSimpleName(); + } + {{/discriminator}} + {{/gson}} + {{#vars}} + {{^isReadOnly}} + public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { + this.{{name}} = {{name}}; + return this; + } + {{#isListContainer}} + + public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.add({{name}}Item); + return this; + } + {{/isListContainer}} + {{#isMapContainer}} + + public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.put(key, {{name}}Item); + return this; + } + {{/isMapContainer}} + + {{/isReadOnly}} + /** + {{#description}} + * {{description}} + {{/description}} + {{^description}} + * Get {{name}} + {{/description}} + {{#minimum}} + * minimum: {{minimum}} + {{/minimum}} + {{#maximum}} + * maximum: {{maximum}} + {{/maximum}} + * @return {{name}} + **/ +{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} @ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") +{{#vendorExtensions.extraAnnotation}} + {{{vendorExtensions.extraAnnotation}}} +{{/vendorExtensions.extraAnnotation}} + public {{{datatypeWithEnum}}} {{#isBoolean}}is{{/isBoolean}}{{getter}}() { + return {{name}}; + } + {{^isReadOnly}} + + public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { + this.{{name}} = {{name}}; + } + {{/isReadOnly}} + + {{/vars}} + +{{^supportJava6}} + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + }{{#hasVars}} + {{classname}} {{classVarName}} = ({{classname}}) o; + return {{#vars}}{{#isByteArray}}Arrays{{/isByteArray}}{{#isBinary}}Arrays{{/isBinary}}{{^isByteArray}}{{^isBinary}}Objects{{/isBinary}}{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{#hasMore}} && + {{/hasMore}}{{/vars}}{{#parent}} && + super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} + return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}} + } + + @Override + public int hashCode() { + return Objects.hash({{#vars}}{{^isByteArray}}{{^isBinary}}{{name}}{{/isBinary}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{#isBinary}}Arrays.hashCode({{name}}){{/isBinary}}{{#hasMore}}, {{/hasMore}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); + } + +{{/supportJava6}} +{{#supportJava6}} + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + }{{#hasVars}} + {{classname}} {{classVarName}} = ({{classname}}) o; + return {{#vars}}ObjectUtils.equals(this.{{name}}, {{classVarName}}.{{name}}){{#hasMore}} && + {{/hasMore}}{{/vars}}{{#parent}} && + super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} + return true;{{/hasVars}} + } + + @Override + public int hashCode() { + return ObjectUtils.hashCodeMulti({{#vars}}{{name}}{{#hasMore}}, {{/hasMore}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); + } + +{{/supportJava6}} + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class {{classname}} {\n"); + {{#parent}}sb.append(" ").append(toIndentedString(super.toString())).append("\n");{{/parent}} + {{#vars}}sb.append(" {{name}}: ").append(toIndentedString({{name}})).append("\n"); + {{/vars}}sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + {{#parcelableModel}} + public void writeToParcel(Parcel out, int flags) { + {{#parent}} super.writeToParcel(out, flags); {{/parent}} {{#vars}} + out.writeValue({{name}}); + {{/vars}} + } + + public {{classname}}() { + super(); + } + + {{classname}}(Parcel in) { + {{#parent}} super(in); {{/parent}} + {{#vars}} + {{#isPrimitiveType}} + {{name}} = ({{{datatypeWithEnum}}})in.readValue(null); + {{/isPrimitiveType}} + {{^isPrimitiveType}} + {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader()); + {{/isPrimitiveType}} + {{/vars}} + } + + public int describeContents() { + return 0; + } + + public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() { + public {{classname}} createFromParcel(Parcel in) { + return new {{classname}}(in); + } + public {{classname}}[] newArray(int size) { + return new {{classname}}[size]; + } + }; + {{/parcelableModel}} +} diff --git a/pojo_doc.mustache b/pojo_doc.mustache new file mode 100644 index 00000000000..0e4c0749866 --- /dev/null +++ b/pojo_doc.mustache @@ -0,0 +1,15 @@ +# {{classname}} + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +{{#vars}}**{{name}}** | {{#isEnum}}[**{{datatypeWithEnum}}**](#{{datatypeWithEnum}}){{/isEnum}}{{^isEnum}}{{#isPrimitiveType}}**{{datatype}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{datatype}}**]({{complexType}}.md){{/isPrimitiveType}}{{/isEnum}} | {{description}} | {{^required}} [optional]{{/required}}{{#readOnly}} [readonly]{{/readOnly}} +{{/vars}} +{{#vars}}{{#isEnum}} + + +## Enum: {{datatypeWithEnum}} +Name | Value +---- | -----{{#allowableValues}}{{#enumVars}} +{{name}} | {{value}}{{/enumVars}}{{/allowableValues}} +{{/isEnum}}{{/vars}} diff --git a/pom.mustache b/pom.mustache new file mode 100644 index 00000000000..3de31865335 --- /dev/null +++ b/pom.mustache @@ -0,0 +1,336 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{artifactUrl}} + {{artifactDescription}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + {{#java8}} + + 1.8 + 1.8 + {{/java8}} + {{^java8}} + + 1.7 + 1.7 + {{/java8}} + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-annotations-version} + + + + + com.sun.jersey + jersey-client + ${jersey-version} + + + com.sun.jersey.contribs + jersey-multipart + ${jersey-version} + + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-version} + + + com.fasterxml.jackson.jaxrs + jackson-jaxrs-json-provider + ${jackson-version} + + {{#withXml}} + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson-version} + + + {{/withXml}} + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + {{/joda}} + {{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{/java8}} + {{#threetenbp}} + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${jackson-version} + + {{/threetenbp}} + {{^java8}} + + + com.brsanthu + migbase64 + 2.2 + + {{/java8}} + {{#supportJava6}} + + org.apache.commons + commons-lang3 + ${commons_lang3_version} + + + commons-io + commons-io + ${commons_io_version} + + {{/supportJava6}} + {{#useBeanValidation}} + + + javax.validation + validation-api + 1.1.0.Final + provided + + {{/useBeanValidation}} + {{#parcelableModel}} + + + com.google.android + android + 4.1.1.4 + provided + + {{/parcelableModel}} + + + junit + junit + ${junit-version} + test + + + + UTF-8 + 1.5.17 + 1.19.4 + {{#supportJava6}} + 2.5 + 3.6 + {{/supportJava6}} + {{^threetenbp}}2.7.5{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} + 1.0.0 + 4.12 + + diff --git a/settings.gradle.mustache b/settings.gradle.mustache new file mode 100644 index 00000000000..b8fd6c4c41f --- /dev/null +++ b/settings.gradle.mustache @@ -0,0 +1 @@ +rootProject.name = "{{artifactId}}" \ No newline at end of file diff --git a/travis.mustache b/travis.mustache new file mode 100644 index 00000000000..70cb81a67c2 --- /dev/null +++ b/travis.mustache @@ -0,0 +1,17 @@ +# +# Generated by: https://github.com/swagger-api/swagger-codegen.git +# +language: java +jdk: + - oraclejdk8 + - oraclejdk7 +before_install: + # ensure gradlew has proper permission + - chmod a+x ./gradlew +script: + # test using maven + - mvn test + # uncomment below to test using gradle + # - gradle test + # uncomment below to test using sbt + # - sbt test diff --git a/typeInfoAnnotation.mustache b/typeInfoAnnotation.mustache new file mode 100644 index 00000000000..2d7983d0101 --- /dev/null +++ b/typeInfoAnnotation.mustache @@ -0,0 +1,7 @@ +{{#jackson}} +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "{{discriminator}}", visible = true ) +@JsonSubTypes({ + {{#children}} + @JsonSubTypes.Type(value = {{classname}}.class, name = "{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}"), + {{/children}} +}){{/jackson}} diff --git a/xmlAnnotation.mustache b/xmlAnnotation.mustache new file mode 100644 index 00000000000..04566fa1167 --- /dev/null +++ b/xmlAnnotation.mustache @@ -0,0 +1,6 @@ +{{#withXml}} + +@XmlRootElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{classname}}{{/xmlName}}") +@XmlAccessorType(XmlAccessType.FIELD) +{{#jackson}} +@JacksonXmlRootElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}localName = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{classname}}{{/xmlName}}"){{/jackson}}{{/withXml}} \ No newline at end of file From 6989a40533c6d65a1c86e5c438791c1ff4ff5b42 Mon Sep 17 00:00:00 2001 From: wing328 Date: Sun, 1 Apr 2018 01:45:34 +0800 Subject: [PATCH 002/370] Merge branch 'master' into oas3_support2 --- pojo.mustache | 67 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 15 deletions(-) diff --git a/pojo.mustache b/pojo.mustache index 5bbeef075ba..03b0f666d3e 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -67,6 +67,19 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela {{/isContainer}} {{/vars}} + {{#parcelableModel}} + public {{classname}}() { + {{#parent}} + super(); + {{/parent}} + {{#gson}} + {{#discriminator}} + this.{{discriminator}} = this.getClass().getSimpleName(); + {{/discriminator}} + {{/gson}} + } + {{/parcelableModel}} + {{^parcelableModel}} {{#gson}} {{#discriminator}} public {{classname}}() { @@ -74,6 +87,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela } {{/discriminator}} {{/gson}} + {{/parcelableModel}} {{#vars}} {{^isReadOnly}} public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { @@ -203,27 +217,41 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela return o.toString().replace("\n", "\n "); } - {{#parcelableModel}} +{{#parcelableModel}} + public void writeToParcel(Parcel out, int flags) { - {{#parent}} super.writeToParcel(out, flags); {{/parent}} {{#vars}} +{{#model}} +{{#isArrayModel}} + out.writeList(this); +{{/isArrayModel}} +{{^isArrayModel}} +{{#parent}} + super.writeToParcel(out, flags); +{{/parent}} +{{#vars}} out.writeValue({{name}}); - {{/vars}} - } - - public {{classname}}() { - super(); +{{/vars}} +{{/isArrayModel}} +{{/model}} } {{classname}}(Parcel in) { - {{#parent}} super(in); {{/parent}} - {{#vars}} - {{#isPrimitiveType}} +{{#isArrayModel}} + in.readTypedList(this, {{arrayModelType}}.CREATOR); +{{/isArrayModel}} +{{^isArrayModel}} +{{#parent}} + super(in); +{{/parent}} +{{#vars}} +{{#isPrimitiveType}} {{name}} = ({{{datatypeWithEnum}}})in.readValue(null); - {{/isPrimitiveType}} - {{^isPrimitiveType}} +{{/isPrimitiveType}} +{{^isPrimitiveType}} {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader()); - {{/isPrimitiveType}} - {{/vars}} +{{/isPrimitiveType}} +{{/vars}} +{{/isArrayModel}} } public int describeContents() { @@ -232,11 +260,20 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() { public {{classname}} createFromParcel(Parcel in) { +{{#model}} +{{#isArrayModel}} + {{classname}} result = new {{classname}}(); + result.addAll(in.readArrayList({{arrayModelType}}.class.getClassLoader())); + return result; +{{/isArrayModel}} +{{^isArrayModel}} return new {{classname}}(in); +{{/isArrayModel}} +{{/model}} } public {{classname}}[] newArray(int size) { return new {{classname}}[size]; } }; - {{/parcelableModel}} +{{/parcelableModel}} } From 66f695d27ef6d72dffa26dcedd39b37dbf13cc41 Mon Sep 17 00:00:00 2001 From: wing328 Date: Sat, 7 Apr 2018 22:01:31 +0800 Subject: [PATCH 003/370] Merge branch 'master' into oas3_support2 --- build.gradle.mustache | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle.mustache b/build.gradle.mustache index cbc39ce3aca..af0d3d55d85 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -122,13 +122,13 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" {{#joda}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version", + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} {{#java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version", + compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_version", + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_version" {{/threetenbp}} {{^java8}} compile "com.brsanthu:migbase64:2.2" From c8e9047c19925f167bc0d313fdcb82029287f1f3 Mon Sep 17 00:00:00 2001 From: Jeremie Bresson Date: Sat, 14 Apr 2018 16:36:30 +0200 Subject: [PATCH 004/370] Rename projects from swagger-codegen master branch --- ApiClient.mustache | 771 +++++++++++ BeanValidationException.mustache | 27 + Configuration.mustache | 28 + CustomInstantDeserializer.mustache | 232 ++++ JSON.mustache | 521 +++++++ Pair.mustache | 41 + README.mustache | 167 +++ RFC3339DateFormat.mustache | 21 + StringUtil.mustache | 44 + api.mustache | 117 ++ apiException.mustache | 80 ++ api_doc.mustache | 82 ++ api_test.mustache | 45 + auth/ApiKeyAuth.mustache | 64 + auth/Authentication.mustache | 18 + auth/HttpBasicAuth.mustache | 60 + auth/OAuth.mustache | 28 + auth/OAuthFlow.mustache | 7 + beanValidation.mustache | 16 + beanValidationCore.mustache | 20 + beanValidationQueryParams.mustache | 1 + build.gradle.mustache | 137 ++ build.sbt.mustache | 0 enum_outer_doc.mustache | 7 + generatedAnnotation.mustache | 1 + git_push.sh.mustache | 52 + gitignore.mustache | 21 + gradle-wrapper.jar | Bin 0 -> 53639 bytes gradle-wrapper.properties.mustache | 6 + gradle.properties.mustache | 2 + gradlew.bat.mustache | 90 ++ gradlew.mustache | 160 +++ libraries/feign/ApiClient.mustache | 361 +++++ libraries/feign/EncodingUtils.mustache | 86 ++ libraries/feign/ParamExpander.mustache | 22 + libraries/feign/README.mustache | 43 + libraries/feign/api.mustache | 105 ++ libraries/feign/api_test.mustache | 70 + libraries/feign/auth/ApiKeyAuth.mustache | 41 + libraries/feign/auth/HttpBasicAuth.mustache | 41 + libraries/feign/auth/OAuth.mustache | 197 +++ libraries/feign/build.gradle.mustache | 135 ++ libraries/feign/build.sbt.mustache | 26 + libraries/feign/pom.mustache | 308 +++++ .../google-api-client/ApiClient.mustache | 109 ++ libraries/google-api-client/api.mustache | 189 +++ libraries/google-api-client/api_test.mustache | 45 + .../google-api-client/build.gradle.mustache | 142 ++ .../google-api-client/build.sbt.mustache | 33 + libraries/google-api-client/pom.mustache | 299 ++++ libraries/jersey2/ApiClient.mustache | 799 +++++++++++ libraries/jersey2/ApiResponse.mustache | 48 + libraries/jersey2/JSON.mustache | 62 + libraries/jersey2/api.mustache | 143 ++ libraries/jersey2/build.gradle.mustache | 146 ++ libraries/jersey2/build.sbt.mustache | 38 + libraries/jersey2/pom.mustache | 330 +++++ libraries/okhttp-gson/ApiCallback.mustache | 51 + libraries/okhttp-gson/ApiClient.mustache | 1227 +++++++++++++++++ libraries/okhttp-gson/ApiResponse.mustache | 48 + .../GzipRequestInterceptor.mustache | 70 + .../okhttp-gson/ProgressRequestBody.mustache | 66 + .../okhttp-gson/ProgressResponseBody.mustache | 65 + libraries/okhttp-gson/api.mustache | 268 ++++ .../okhttp-gson/auth/HttpBasicAuth.mustache | 43 + libraries/okhttp-gson/build.gradle.mustache | 115 ++ libraries/okhttp-gson/build.sbt.mustache | 26 + libraries/okhttp-gson/pom.mustache | 287 ++++ libraries/rest-assured/ApiClient.mustache | 59 + .../rest-assured/GsonObjectMapper.mustache | 30 + libraries/rest-assured/README.mustache | 43 + .../ResponseSpecBuilders.mustache | 31 + libraries/rest-assured/api.mustache | 243 ++++ libraries/rest-assured/api_doc.mustache | 62 + libraries/rest-assured/api_test.mustache | 65 + libraries/rest-assured/build.gradle.mustache | 124 ++ libraries/rest-assured/build.sbt.mustache | 26 + libraries/rest-assured/pom.mustache | 262 ++++ libraries/resteasy/ApiClient.mustache | 693 ++++++++++ libraries/resteasy/JSON.mustache | 48 + libraries/resteasy/api.mustache | 109 ++ libraries/resteasy/build.gradle.mustache | 147 ++ libraries/resteasy/build.sbt.mustache | 34 + libraries/resteasy/pom.mustache | 263 ++++ libraries/resttemplate/ApiClient.mustache | 678 +++++++++ libraries/resttemplate/api.mustache | 107 ++ libraries/resttemplate/api_test.mustache | 44 + .../resttemplate/auth/ApiKeyAuth.mustache | 60 + .../resttemplate/auth/Authentication.mustache | 13 + .../resttemplate/auth/HttpBasicAuth.mustache | 39 + libraries/resttemplate/auth/OAuth.mustache | 24 + .../resttemplate/auth/OAuthFlow.mustache | 5 + libraries/resttemplate/build.gradle.mustache | 140 ++ libraries/resttemplate/pom.mustache | 301 ++++ libraries/retrofit/ApiClient.mustache | 418 ++++++ libraries/retrofit/CollectionFormats.mustache | 95 ++ libraries/retrofit/README.mustache | 43 + libraries/retrofit/api.mustache | 62 + libraries/retrofit/api_test.mustache | 44 + libraries/retrofit/auth/ApiKeyAuth.mustache | 68 + .../retrofit/auth/HttpBasicAuth.mustache | 49 + libraries/retrofit/auth/OAuth.mustache | 185 +++ .../retrofit/auth/OAuthOkHttpClient.mustache | 69 + libraries/retrofit/bodyParams.mustache | 1 + libraries/retrofit/build.gradle.mustache | 118 ++ libraries/retrofit/build.sbt.mustache | 20 + libraries/retrofit/formParams.mustache | 1 + libraries/retrofit/headerParams.mustache | 1 + libraries/retrofit/pathParams.mustache | 1 + libraries/retrofit/pom.mustache | 254 ++++ libraries/retrofit/queryParams.mustache | 1 + libraries/retrofit2/ApiClient.mustache | 420 ++++++ .../retrofit2/CollectionFormats.mustache | 95 ++ libraries/retrofit2/JSON.mustache | 446 ++++++ libraries/retrofit2/README.mustache | 39 + libraries/retrofit2/api.mustache | 77 ++ libraries/retrofit2/api_test.mustache | 46 + libraries/retrofit2/auth/ApiKeyAuth.mustache | 68 + .../retrofit2/auth/HttpBasicAuth.mustache | 50 + libraries/retrofit2/auth/OAuth.mustache | 185 +++ .../retrofit2/auth/OAuthOkHttpClient.mustache | 72 + libraries/retrofit2/bodyParams.mustache | 1 + libraries/retrofit2/build.gradle.mustache | 164 +++ libraries/retrofit2/build.sbt.mustache | 52 + libraries/retrofit2/formParams.mustache | 1 + libraries/retrofit2/formParams.mustache.save | 1 + libraries/retrofit2/headerParams.mustache | 1 + libraries/retrofit2/pathParams.mustache | 1 + .../play-common/auth/ApiKeyAuth.mustache | 67 + libraries/retrofit2/play24/ApiClient.mustache | 136 ++ .../play24/Play24CallAdapterFactory.mustache | 100 ++ .../play24/Play24CallFactory.mustache | 219 +++ libraries/retrofit2/play24/api.mustache | 57 + libraries/retrofit2/play25/ApiClient.mustache | 136 ++ .../play25/Play25CallAdapterFactory.mustache | 117 ++ .../play25/Play25CallFactory.mustache | 228 +++ libraries/retrofit2/play25/api.mustache | 57 + libraries/retrofit2/pom.mustache | 361 +++++ libraries/retrofit2/queryParams.mustache | 1 + libraries/vertx/ApiClient.mustache | 600 ++++++++ libraries/vertx/Configuration.mustache | 42 + libraries/vertx/api.mustache | 19 + libraries/vertx/apiException.mustache | 110 ++ libraries/vertx/apiImpl.mustache | 91 ++ libraries/vertx/api_test.mustache | 70 + libraries/vertx/auth/ApiKeyAuth.mustache | 64 + libraries/vertx/auth/Authentication.mustache | 18 + libraries/vertx/auth/HttpBasicAuth.mustache | 40 + libraries/vertx/auth/OAuth.mustache | 28 + libraries/vertx/auth/OAuthFlow.mustache | 7 + libraries/vertx/build.gradle.mustache | 53 + libraries/vertx/pom.mustache | 279 ++++ libraries/vertx/rxApiImpl.mustache | 58 + licenseInfo.mustache | 11 + manifest.mustache | 3 + model.mustache | 39 + modelEnum.mustache | 68 + modelInnerEnum.mustache | 59 + model_doc.mustache | 3 + pojo.mustache | 279 ++++ pojo_doc.mustache | 15 + pom.mustache | 336 +++++ settings.gradle.mustache | 1 + travis.mustache | 17 + typeInfoAnnotation.mustache | 7 + xmlAnnotation.mustache | 6 + 166 files changed, 19551 insertions(+) create mode 100644 ApiClient.mustache create mode 100644 BeanValidationException.mustache create mode 100644 Configuration.mustache create mode 100644 CustomInstantDeserializer.mustache create mode 100644 JSON.mustache create mode 100644 Pair.mustache create mode 100644 README.mustache create mode 100644 RFC3339DateFormat.mustache create mode 100644 StringUtil.mustache create mode 100644 api.mustache create mode 100644 apiException.mustache create mode 100644 api_doc.mustache create mode 100644 api_test.mustache create mode 100644 auth/ApiKeyAuth.mustache create mode 100644 auth/Authentication.mustache create mode 100644 auth/HttpBasicAuth.mustache create mode 100644 auth/OAuth.mustache create mode 100644 auth/OAuthFlow.mustache create mode 100644 beanValidation.mustache create mode 100644 beanValidationCore.mustache create mode 100644 beanValidationQueryParams.mustache create mode 100644 build.gradle.mustache create mode 100644 build.sbt.mustache create mode 100644 enum_outer_doc.mustache create mode 100644 generatedAnnotation.mustache create mode 100755 git_push.sh.mustache create mode 100644 gitignore.mustache create mode 100644 gradle-wrapper.jar create mode 100644 gradle-wrapper.properties.mustache create mode 100644 gradle.properties.mustache create mode 100644 gradlew.bat.mustache create mode 100755 gradlew.mustache create mode 100644 libraries/feign/ApiClient.mustache create mode 100644 libraries/feign/EncodingUtils.mustache create mode 100644 libraries/feign/ParamExpander.mustache create mode 100644 libraries/feign/README.mustache create mode 100644 libraries/feign/api.mustache create mode 100644 libraries/feign/api_test.mustache create mode 100644 libraries/feign/auth/ApiKeyAuth.mustache create mode 100644 libraries/feign/auth/HttpBasicAuth.mustache create mode 100644 libraries/feign/auth/OAuth.mustache create mode 100644 libraries/feign/build.gradle.mustache create mode 100644 libraries/feign/build.sbt.mustache create mode 100644 libraries/feign/pom.mustache create mode 100644 libraries/google-api-client/ApiClient.mustache create mode 100644 libraries/google-api-client/api.mustache create mode 100644 libraries/google-api-client/api_test.mustache create mode 100644 libraries/google-api-client/build.gradle.mustache create mode 100644 libraries/google-api-client/build.sbt.mustache create mode 100644 libraries/google-api-client/pom.mustache create mode 100644 libraries/jersey2/ApiClient.mustache create mode 100644 libraries/jersey2/ApiResponse.mustache create mode 100644 libraries/jersey2/JSON.mustache create mode 100644 libraries/jersey2/api.mustache create mode 100644 libraries/jersey2/build.gradle.mustache create mode 100644 libraries/jersey2/build.sbt.mustache create mode 100644 libraries/jersey2/pom.mustache create mode 100644 libraries/okhttp-gson/ApiCallback.mustache create mode 100644 libraries/okhttp-gson/ApiClient.mustache create mode 100644 libraries/okhttp-gson/ApiResponse.mustache create mode 100644 libraries/okhttp-gson/GzipRequestInterceptor.mustache create mode 100644 libraries/okhttp-gson/ProgressRequestBody.mustache create mode 100644 libraries/okhttp-gson/ProgressResponseBody.mustache create mode 100644 libraries/okhttp-gson/api.mustache create mode 100644 libraries/okhttp-gson/auth/HttpBasicAuth.mustache create mode 100644 libraries/okhttp-gson/build.gradle.mustache create mode 100644 libraries/okhttp-gson/build.sbt.mustache create mode 100644 libraries/okhttp-gson/pom.mustache create mode 100644 libraries/rest-assured/ApiClient.mustache create mode 100644 libraries/rest-assured/GsonObjectMapper.mustache create mode 100644 libraries/rest-assured/README.mustache create mode 100644 libraries/rest-assured/ResponseSpecBuilders.mustache create mode 100644 libraries/rest-assured/api.mustache create mode 100644 libraries/rest-assured/api_doc.mustache create mode 100644 libraries/rest-assured/api_test.mustache create mode 100644 libraries/rest-assured/build.gradle.mustache create mode 100644 libraries/rest-assured/build.sbt.mustache create mode 100644 libraries/rest-assured/pom.mustache create mode 100644 libraries/resteasy/ApiClient.mustache create mode 100644 libraries/resteasy/JSON.mustache create mode 100644 libraries/resteasy/api.mustache create mode 100644 libraries/resteasy/build.gradle.mustache create mode 100644 libraries/resteasy/build.sbt.mustache create mode 100644 libraries/resteasy/pom.mustache create mode 100644 libraries/resttemplate/ApiClient.mustache create mode 100644 libraries/resttemplate/api.mustache create mode 100644 libraries/resttemplate/api_test.mustache create mode 100644 libraries/resttemplate/auth/ApiKeyAuth.mustache create mode 100644 libraries/resttemplate/auth/Authentication.mustache create mode 100644 libraries/resttemplate/auth/HttpBasicAuth.mustache create mode 100644 libraries/resttemplate/auth/OAuth.mustache create mode 100644 libraries/resttemplate/auth/OAuthFlow.mustache create mode 100644 libraries/resttemplate/build.gradle.mustache create mode 100644 libraries/resttemplate/pom.mustache create mode 100644 libraries/retrofit/ApiClient.mustache create mode 100644 libraries/retrofit/CollectionFormats.mustache create mode 100644 libraries/retrofit/README.mustache create mode 100644 libraries/retrofit/api.mustache create mode 100644 libraries/retrofit/api_test.mustache create mode 100644 libraries/retrofit/auth/ApiKeyAuth.mustache create mode 100644 libraries/retrofit/auth/HttpBasicAuth.mustache create mode 100644 libraries/retrofit/auth/OAuth.mustache create mode 100644 libraries/retrofit/auth/OAuthOkHttpClient.mustache create mode 100644 libraries/retrofit/bodyParams.mustache create mode 100644 libraries/retrofit/build.gradle.mustache create mode 100644 libraries/retrofit/build.sbt.mustache create mode 100644 libraries/retrofit/formParams.mustache create mode 100644 libraries/retrofit/headerParams.mustache create mode 100644 libraries/retrofit/pathParams.mustache create mode 100644 libraries/retrofit/pom.mustache create mode 100644 libraries/retrofit/queryParams.mustache create mode 100644 libraries/retrofit2/ApiClient.mustache create mode 100644 libraries/retrofit2/CollectionFormats.mustache create mode 100644 libraries/retrofit2/JSON.mustache create mode 100644 libraries/retrofit2/README.mustache create mode 100644 libraries/retrofit2/api.mustache create mode 100644 libraries/retrofit2/api_test.mustache create mode 100644 libraries/retrofit2/auth/ApiKeyAuth.mustache create mode 100644 libraries/retrofit2/auth/HttpBasicAuth.mustache create mode 100644 libraries/retrofit2/auth/OAuth.mustache create mode 100644 libraries/retrofit2/auth/OAuthOkHttpClient.mustache create mode 100644 libraries/retrofit2/bodyParams.mustache create mode 100644 libraries/retrofit2/build.gradle.mustache create mode 100644 libraries/retrofit2/build.sbt.mustache create mode 100644 libraries/retrofit2/formParams.mustache create mode 100644 libraries/retrofit2/formParams.mustache.save create mode 100644 libraries/retrofit2/headerParams.mustache create mode 100644 libraries/retrofit2/pathParams.mustache create mode 100644 libraries/retrofit2/play-common/auth/ApiKeyAuth.mustache create mode 100644 libraries/retrofit2/play24/ApiClient.mustache create mode 100644 libraries/retrofit2/play24/Play24CallAdapterFactory.mustache create mode 100644 libraries/retrofit2/play24/Play24CallFactory.mustache create mode 100644 libraries/retrofit2/play24/api.mustache create mode 100644 libraries/retrofit2/play25/ApiClient.mustache create mode 100644 libraries/retrofit2/play25/Play25CallAdapterFactory.mustache create mode 100644 libraries/retrofit2/play25/Play25CallFactory.mustache create mode 100644 libraries/retrofit2/play25/api.mustache create mode 100644 libraries/retrofit2/pom.mustache create mode 100644 libraries/retrofit2/queryParams.mustache create mode 100644 libraries/vertx/ApiClient.mustache create mode 100644 libraries/vertx/Configuration.mustache create mode 100644 libraries/vertx/api.mustache create mode 100644 libraries/vertx/apiException.mustache create mode 100644 libraries/vertx/apiImpl.mustache create mode 100644 libraries/vertx/api_test.mustache create mode 100644 libraries/vertx/auth/ApiKeyAuth.mustache create mode 100644 libraries/vertx/auth/Authentication.mustache create mode 100644 libraries/vertx/auth/HttpBasicAuth.mustache create mode 100644 libraries/vertx/auth/OAuth.mustache create mode 100644 libraries/vertx/auth/OAuthFlow.mustache create mode 100644 libraries/vertx/build.gradle.mustache create mode 100644 libraries/vertx/pom.mustache create mode 100644 libraries/vertx/rxApiImpl.mustache create mode 100644 licenseInfo.mustache create mode 100644 manifest.mustache create mode 100644 model.mustache create mode 100644 modelEnum.mustache create mode 100644 modelInnerEnum.mustache create mode 100644 model_doc.mustache create mode 100644 pojo.mustache create mode 100644 pojo_doc.mustache create mode 100644 pom.mustache create mode 100644 settings.gradle.mustache create mode 100644 travis.mustache create mode 100644 typeInfoAnnotation.mustache create mode 100644 xmlAnnotation.mustache diff --git a/ApiClient.mustache b/ApiClient.mustache new file mode 100644 index 00000000000..f99ea1dade7 --- /dev/null +++ b/ApiClient.mustache @@ -0,0 +1,771 @@ +{{>licenseInfo}} +package {{invokerPackage}}; + +{{#threetenbp}} +import org.threeten.bp.*; + +{{/threetenbp}} +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.*; +{{#joda}} +import com.fasterxml.jackson.datatype.joda.JodaModule; +{{/joda}} +{{#java8}} +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{/java8}} +{{#threetenbp}} +import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; +{{/threetenbp}} +import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; + +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.GenericType; +import com.sun.jersey.api.client.config.DefaultClientConfig; +import com.sun.jersey.api.client.filter.GZIPContentEncodingFilter; +import com.sun.jersey.api.client.filter.LoggingFilter; +import com.sun.jersey.api.client.WebResource.Builder; + +import com.sun.jersey.multipart.FormDataMultiPart; +import com.sun.jersey.multipart.file.FileDataBodyPart; + +import javax.ws.rs.core.Response.Status.Family; +import javax.ws.rs.core.MediaType; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Map.Entry; +import java.util.HashMap; +import java.util.List; +import java.util.ArrayList; +import java.util.Date; +import java.util.TimeZone; + +import java.net.URLEncoder; + +import java.io.File; +import java.io.UnsupportedEncodingException; + +import java.text.DateFormat; + +import {{invokerPackage}}.auth.Authentication; +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.OAuth; + +{{>generatedAnnotation}} +public class ApiClient { + private Map defaultHeaderMap = new HashMap(); + private String basePath = "{{{basePath}}}"; + private boolean debugging = false; + private int connectionTimeout = 0; + + private Client httpClient; + private ObjectMapper objectMapper; + + private Map authentications; + + private int statusCode; + private Map> responseHeaders; + + private DateFormat dateFormat; + + public ApiClient() { + objectMapper = new ObjectMapper(); + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + {{#joda}} + objectMapper.registerModule(new JodaModule()); + {{/joda}} + {{#java8}} + objectMapper.registerModule(new JavaTimeModule()); + {{/java8}} + {{#threetenbp}} + ThreeTenModule module = new ThreeTenModule(); + module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); + module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); + module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); + objectMapper.registerModule(module); + {{/threetenbp}} + objectMapper.setDateFormat(ApiClient.buildDefaultDateFormat()); + + dateFormat = ApiClient.buildDefaultDateFormat(); + + // Set default User-Agent. + setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}Swagger-Codegen/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap();{{#authMethods}}{{#isBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + + rebuildHttpClient(); + } + + public static DateFormat buildDefaultDateFormat() { + return new RFC3339DateFormat(); + } + + /** + * Build the Client used to make HTTP requests with the latest settings, + * i.e. objectMapper and debugging. + * TODO: better to use the Builder Pattern? + * @return API client + */ + public ApiClient rebuildHttpClient() { + // Add the JSON serialization support to Jersey + JacksonJsonProvider jsonProvider = new JacksonJsonProvider(objectMapper); + DefaultClientConfig conf = new DefaultClientConfig(); + conf.getSingletons().add(jsonProvider); + Client client = Client.create(conf); + client.addFilter(new GZIPContentEncodingFilter({{#useGzipFeature}}true{{/useGzipFeature}}{{^useGzipFeature}}false{{/useGzipFeature}})); + if (debugging) { + client.addFilter(new LoggingFilter()); + } + this.httpClient = client; + return this; + } + + /** + * Returns the current object mapper used for JSON serialization/deserialization. + *

+ * Note: If you make changes to the object mapper, remember to set it back via + * setObjectMapper in order to trigger HTTP client rebuilding. + *

+ * @return Object mapper + */ + public ObjectMapper getObjectMapper() { + return objectMapper; + } + + public ApiClient setObjectMapper(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + // Need to rebuild the Client as it depends on object mapper. + rebuildHttpClient(); + return this; + } + + public Client getHttpClient() { + return httpClient; + } + + public ApiClient setHttpClient(Client httpClient) { + this.httpClient = httpClient; + return this; + } + + public String getBasePath() { + return basePath; + } + + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Gets the status code of the previous request + * @return Status code + */ + public int getStatusCode() { + return statusCode; + } + + /** + * Gets the response headers of the previous request + * @return Response headers + */ + public Map> getResponseHeaders() { + return responseHeaders; + } + + /** + * Get authentications (key: authentication name, value: authentication). + * @return Map of authentication + */ + public Map getAuthentications() { + return authentications; + } + + /** + * Get authentication for the given name. + * + * @param authName The authentication name + * @return The authentication, null if not found + */ + public Authentication getAuthentication(String authName) { + return authentications.get(authName); + } + + /** + * Helper method to set username for the first HTTP basic authentication. + * @param username Username + */ + public void setUsername(String username) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setUsername(username); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set password for the first HTTP basic authentication. + * @param password Password + */ + public void setPassword(String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setPassword(password); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set API key value for the first API key authentication. + * @param apiKey API key + */ + public void setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + * @param apiKeyPrefix API key prefix + */ + public void setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set access token for the first OAuth2 authentication. + * @param accessToken Access token + */ + public void setAccessToken(String accessToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setAccessToken(accessToken); + return; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Set the User-Agent header's value (by adding to the default header map). + * @param userAgent User agent + * @return API client + */ + public ApiClient setUserAgent(String userAgent) { + addDefaultHeader("User-Agent", userAgent); + return this; + } + + /** + * Add a default header. + * + * @param key The header's key + * @param value The header's value + * @return API client + */ + public ApiClient addDefaultHeader(String key, String value) { + defaultHeaderMap.put(key, value); + return this; + } + + /** + * Check that whether debugging is enabled for this API client. + * @return True if debugging is on + */ + public boolean isDebugging() { + return debugging; + } + + /** + * Enable/disable debugging for this API client. + * + * @param debugging To enable (true) or disable (false) debugging + * @return API client + */ + public ApiClient setDebugging(boolean debugging) { + this.debugging = debugging; + // Need to rebuild the Client as it depends on the value of debugging. + rebuildHttpClient(); + return this; + } + + /** + * Connect timeout (in milliseconds). + * @return Connection timeout + */ + public int getConnectTimeout() { + return connectionTimeout; + } + + /** + * Set the connect timeout (in milliseconds). + * A value of 0 means no timeout, otherwise values must be between 1 and + * {@link Integer#MAX_VALUE}. + * @param connectionTimeout Connection timeout in milliseconds + * @return API client + */ + public ApiClient setConnectTimeout(int connectionTimeout) { + this.connectionTimeout = connectionTimeout; + httpClient.setConnectTimeout(connectionTimeout); + return this; + } + + /** + * Get the date format used to parse/format date parameters. + * @return Date format + */ + public DateFormat getDateFormat() { + return dateFormat; + } + + /** + * Set the date format used to parse/format date parameters. + * @param dateFormat Date format + * @return API client + */ + public ApiClient setDateFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + // Also set the date format for model (de)serialization with Date properties. + this.objectMapper.setDateFormat((DateFormat) dateFormat.clone()); + // Need to rebuild the Client as objectMapper changes. + rebuildHttpClient(); + return this; + } + + /** + * Parse the given string into Date object. + * @param str String + * @return Date + */ + public Date parseDate(String str) { + try { + return dateFormat.parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(e); + } + } + + /** + * Format the given Date object into string. + * @param date Date + * @return Date in string format + */ + public String formatDate(Date date) { + return dateFormat.format(date); + } + + /** + * Format the given parameter object into string. + * @param param Object + * @return Object in string format + */ + public String parameterToString(Object param) { + if (param == null) { + return ""; + } else if (param instanceof Date) { + return formatDate((Date) param); + } else if (param instanceof Collection) { + StringBuilder b = new StringBuilder(); + for(Object o : (Collection)param) { + if(b.length() > 0) { + b.append(','); + } + b.append(String.valueOf(o)); + } + return b.toString(); + } else { + return String.valueOf(param); + } + } + + /** + * Formats the specified query parameter to a list containing a single {@code Pair} object. + * + * Note that {@code value} must not be a collection. + * + * @param name The name of the parameter. + * @param value The value of the parameter. + * @return A list containing a single {@code Pair} object. + */ + public List parameterToPair(String name, Object value) { + List params = new ArrayList(); + + // preconditions + if (name == null || name.isEmpty() || value == null || value instanceof Collection) return params; + + params.add(new Pair(name, parameterToString(value))); + return params; + } + + /** + * Formats the specified collection query parameters to a list of {@code Pair} objects. + * + * Note that the values of each of the returned Pair objects are percent-encoded. + * + * @param collectionFormat The collection format of the parameter. + * @param name The name of the parameter. + * @param value The value of the parameter. + * @return A list of {@code Pair} objects. + */ + public List parameterToPairs(String collectionFormat, String name, Collection value) { + List params = new ArrayList(); + + // preconditions + if (name == null || name.isEmpty() || value == null) { + return params; + } + + // create the params based on the collection format + if ("multi".equals(collectionFormat)) { + for (Object item : value) { + params.add(new Pair(name, escapeString(parameterToString(item)))); + } + return params; + } + + // collectionFormat is assumed to be "csv" by default + String delimiter = ","; + + // escape all delimiters except commas, which are URI reserved + // characters + if ("ssv".equals(collectionFormat)) { + delimiter = escapeString(" "); + } else if ("tsv".equals(collectionFormat)) { + delimiter = escapeString("\t"); + } else if ("pipes".equals(collectionFormat)) { + delimiter = escapeString("|"); + } + + StringBuilder sb = new StringBuilder() ; + for (Object item : value) { + sb.append(delimiter); + sb.append(escapeString(parameterToString(item))); + } + + params.add(new Pair(name, sb.substring(delimiter.length()))); + + return params; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * application/vnd.company+json + * @param mime MIME + * @return True if MIME type is boolean + */ + public boolean isJsonMime(String mime) { + String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$"; + return mime != null && (mime.matches(jsonMime) || mime.equals("*/*")); + } + + /** + * Select the Accept header's value from the given accepts array: + * if JSON exists in the given array, use it; + * otherwise use all of them (joining into a string) + * + * @param accepts The accepts array to select from + * @return The Accept header to use. If the given array is empty, + * null will be returned (not to set the Accept header explicitly). + */ + public String selectHeaderAccept(String[] accepts) { + if (accepts.length == 0) { + return null; + } + for (String accept : accepts) { + if (isJsonMime(accept)) { + return accept; + } + } + return StringUtil.join(accepts, ","); + } + + /** + * Select the Content-Type header's value from the given array: + * if JSON exists in the given array, use it; + * otherwise use the first one of the array. + * + * @param contentTypes The Content-Type array to select from + * @return The Content-Type header to use. If the given array is empty, + * or matches "any", JSON will be used. + */ + public String selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0 || contentTypes[0].equals("*/*")) { + return "application/json"; + } + for (String contentType : contentTypes) { + if (isJsonMime(contentType)) { + return contentType; + } + } + return contentTypes[0]; + } + + /** + * Escape the given string to be used as URL query value. + * @param str String + * @return Escaped string + */ + public String escapeString(String str) { + try { + return URLEncoder.encode(str, "utf8").replaceAll("\\+", "%20"); + } catch (UnsupportedEncodingException e) { + return str; + } + } + + /** + * Serialize the given Java object into string according the given + * Content-Type (only JSON is supported for now). + * @param obj Object + * @param contentType Content type + * @param formParams Form parameters + * @return Object + * @throws ApiException API exception + */ + public Object serialize(Object obj, String contentType, Map formParams) throws ApiException { + if (contentType.startsWith("multipart/form-data")) { + FormDataMultiPart mp = new FormDataMultiPart(); + for (Entry param: formParams.entrySet()) { + if( param.getValue() instanceof List && !( ( List ) param.getValue() ).isEmpty() + && ( ( List ) param.getValue() ).get( 0 ) instanceof File ) { + @SuppressWarnings( "unchecked" ) + List files = ( List ) param.getValue(); + for( File file : files ) { + mp.bodyPart( new FileDataBodyPart( param.getKey(), file, MediaType.APPLICATION_OCTET_STREAM_TYPE ) ); + } + } else if (param.getValue() instanceof File) { + File file = (File) param.getValue(); + mp.bodyPart(new FileDataBodyPart(param.getKey(), file, MediaType.APPLICATION_OCTET_STREAM_TYPE)); + } else { + mp.field(param.getKey(), parameterToString(param.getValue()), MediaType.MULTIPART_FORM_DATA_TYPE); + } + } + return mp; + } else if (contentType.startsWith("application/x-www-form-urlencoded")) { + return this.getXWWWFormUrlencodedParams(formParams); + } else { + // We let Jersey attempt to serialize the body + return obj; + } + } + + /** + * Build full URL by concatenating base path, the given sub path and query parameters. + * + * @param path The sub path + * @param queryParams The query parameters + * @param collectionQueryParams The collection query parameters + * @return The full URL + */ + private String buildUrl(String path, List queryParams, List collectionQueryParams) { + final StringBuilder url = new StringBuilder(); + url.append(basePath).append(path); + + if (queryParams != null && !queryParams.isEmpty()) { + // support (constant) query string in `path`, e.g. "/posts?draft=1" + String prefix = path.contains("?") ? "&" : "?"; + for (Pair param : queryParams) { + if (param.getValue() != null) { + if (prefix != null) { + url.append(prefix); + prefix = null; + } else { + url.append("&"); + } + String value = parameterToString(param.getValue()); + url.append(escapeString(param.getName())).append("=").append(escapeString(value)); + } + } + } + + if (collectionQueryParams != null && !collectionQueryParams.isEmpty()) { + String prefix = url.toString().contains("?") ? "&" : "?"; + for (Pair param : collectionQueryParams) { + if (param.getValue() != null) { + if (prefix != null) { + url.append(prefix); + prefix = null; + } else { + url.append("&"); + } + String value = parameterToString(param.getValue()); + // collection query parameter value already escaped as part of parameterToPairs + url.append(escapeString(param.getName())).append("=").append(value); + } + } + } + + return url.toString(); + } + + private ClientResponse getAPIResponse(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map formParams, String accept, String contentType, String[] authNames) throws ApiException { + if (body != null && !formParams.isEmpty()) { + throw new ApiException(500, "Cannot have body and form params"); + } + + updateParamsForAuth(authNames, queryParams, headerParams); + + final String url = buildUrl(path, queryParams, collectionQueryParams); + Builder builder; + if (accept == null) { + builder = httpClient.resource(url).getRequestBuilder(); + } else { + builder = httpClient.resource(url).accept(accept); + } + + for (Entry keyValue : headerParams.entrySet()) { + builder = builder.header(keyValue.getKey(), keyValue.getValue()); + } + for (Map.Entry keyValue : defaultHeaderMap.entrySet()) { + if (!headerParams.containsKey(keyValue.getKey())) { + builder = builder.header(keyValue.getKey(), keyValue.getValue()); + } + } + + ClientResponse response = null; + + if ("GET".equals(method)) { + response = (ClientResponse) builder.get(ClientResponse.class); + } else if ("POST".equals(method)) { + response = builder.type(contentType).post(ClientResponse.class, serialize(body, contentType, formParams)); + } else if ("PUT".equals(method)) { + response = builder.type(contentType).put(ClientResponse.class, serialize(body, contentType, formParams)); + } else if ("DELETE".equals(method)) { + response = builder.type(contentType).delete(ClientResponse.class, serialize(body, contentType, formParams)); + } else if ("PATCH".equals(method)) { + response = builder.type(contentType).header("X-HTTP-Method-Override", "PATCH").post(ClientResponse.class, serialize(body, contentType, formParams)); + } else if ("HEAD".equals(method)) { + response = builder.head(); + } else { + throw new ApiException(500, "unknown method type " + method); + } + return response; + } + + /** + * Invoke API by sending HTTP request with the given options. + * + * @param Type + * @param path The sub-path of the HTTP URL + * @param method The request method, one of "GET", "POST", "PUT", and "DELETE" + * @param queryParams The query parameters + * @param collectionQueryParams The collection query parameters + * @param body The request body object - if it is not binary, otherwise null + * @param headerParams The header parameters + * @param formParams The form parameters + * @param accept The request's Accept header + * @param contentType The request's Content-Type header + * @param authNames The authentications to apply + * @param returnType Return type + * @return The response body in type of string + * @throws ApiException API exception + */ + public T invokeAPI(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { + + ClientResponse response = getAPIResponse(path, method, queryParams, collectionQueryParams, body, headerParams, formParams, accept, contentType, authNames); + + statusCode = response.getStatusInfo().getStatusCode(); + responseHeaders = response.getHeaders(); + + if(response.getStatusInfo().getStatusCode() == ClientResponse.Status.NO_CONTENT.getStatusCode()) { + return null; + } else if (response.getStatusInfo().getFamily() == Family.SUCCESSFUL) { + if (returnType == null) + return null; + else + return response.getEntity(returnType); + } else { + String message = "error"; + String respBody = null; + if (response.hasEntity()) { + try { + respBody = response.getEntity(String.class); + message = respBody; + } catch (RuntimeException e) { + // e.printStackTrace(); + } + } + throw new ApiException( + response.getStatusInfo().getStatusCode(), + message, + response.getHeaders(), + respBody); + } + } + + /** + * Update query and header parameters based on authentication settings. + * + * @param authNames The authentications to apply + * @param queryParams Query parameters + * @param headerParams Header parameters + */ + private void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams) { + for (String authName : authNames) { + Authentication auth = authentications.get(authName); + if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + auth.applyToParams(queryParams, headerParams); + } + } + + /** + * Encode the given form parameters as request body. + * @param formParams Form parameters + * @return HTTP form encoded parameters + */ + private String getXWWWFormUrlencodedParams(Map formParams) { + StringBuilder formParamBuilder = new StringBuilder(); + + for (Entry param : formParams.entrySet()) { + String valueStr = parameterToString(param.getValue()); + try { + formParamBuilder.append(URLEncoder.encode(param.getKey(), "utf8")) + .append("=") + .append(URLEncoder.encode(valueStr, "utf8")); + formParamBuilder.append("&"); + } catch (UnsupportedEncodingException e) { + // move on to next + } + } + + String encodedFormParams = formParamBuilder.toString(); + if (encodedFormParams.endsWith("&")) { + encodedFormParams = encodedFormParams.substring(0, encodedFormParams.length() - 1); + } + + return encodedFormParams; + } +} diff --git a/BeanValidationException.mustache b/BeanValidationException.mustache new file mode 100644 index 00000000000..ab8ef30b69b --- /dev/null +++ b/BeanValidationException.mustache @@ -0,0 +1,27 @@ +package {{invokerPackage}}; + +import java.util.Set; + +import javax.validation.ConstraintViolation; +import javax.validation.ValidationException; + +public class BeanValidationException extends ValidationException { + /** + * + */ + private static final long serialVersionUID = -5294733947409491364L; + Set> violations; + + public BeanValidationException(Set> violations) { + this.violations = violations; + } + + public Set> getViolations() { + return violations; + } + + public void setViolations(Set> violations) { + this.violations = violations; + } + +} diff --git a/Configuration.mustache b/Configuration.mustache new file mode 100644 index 00000000000..cb425df3563 --- /dev/null +++ b/Configuration.mustache @@ -0,0 +1,28 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +{{>generatedAnnotation}} +public class Configuration { + private static ApiClient defaultApiClient = new ApiClient(); + + /** + * Get the default API client, which would be used when creating API + * instances without providing an API client. + * + * @return Default API client + */ + public static ApiClient getDefaultApiClient() { + return defaultApiClient; + } + + /** + * Set the default API client, which would be used when creating API + * instances without providing an API client. + * + * @param apiClient API client + */ + public static void setDefaultApiClient(ApiClient apiClient) { + defaultApiClient = apiClient; + } +} diff --git a/CustomInstantDeserializer.mustache b/CustomInstantDeserializer.mustache new file mode 100644 index 00000000000..dbf4d30e117 --- /dev/null +++ b/CustomInstantDeserializer.mustache @@ -0,0 +1,232 @@ +package {{invokerPackage}}; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonTokenId; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.datatype.threetenbp.DateTimeUtils; +import com.fasterxml.jackson.datatype.threetenbp.DecimalUtils; +import com.fasterxml.jackson.datatype.threetenbp.deser.ThreeTenDateTimeDeserializerBase; +import com.fasterxml.jackson.datatype.threetenbp.function.BiFunction; +import com.fasterxml.jackson.datatype.threetenbp.function.Function; +import org.threeten.bp.DateTimeException; +import org.threeten.bp.Instant; +import org.threeten.bp.OffsetDateTime; +import org.threeten.bp.ZoneId; +import org.threeten.bp.ZonedDateTime; +import org.threeten.bp.format.DateTimeFormatter; +import org.threeten.bp.temporal.Temporal; +import org.threeten.bp.temporal.TemporalAccessor; + +import java.io.IOException; +import java.math.BigDecimal; + +/** + * Deserializer for ThreeTen temporal {@link Instant}s, {@link OffsetDateTime}, and {@link ZonedDateTime}s. + * Adapted from the jackson threetenbp InstantDeserializer to add support for deserializing rfc822 format. + * + * @author Nick Williams + */ +public class CustomInstantDeserializer + extends ThreeTenDateTimeDeserializerBase { + private static final long serialVersionUID = 1L; + + public static final CustomInstantDeserializer INSTANT = new CustomInstantDeserializer( + Instant.class, DateTimeFormatter.ISO_INSTANT, + new Function() { + @Override + public Instant apply(TemporalAccessor temporalAccessor) { + return Instant.from(temporalAccessor); + } + }, + new Function() { + @Override + public Instant apply(FromIntegerArguments a) { + return Instant.ofEpochMilli(a.value); + } + }, + new Function() { + @Override + public Instant apply(FromDecimalArguments a) { + return Instant.ofEpochSecond(a.integer, a.fraction); + } + }, + null + ); + + public static final CustomInstantDeserializer OFFSET_DATE_TIME = new CustomInstantDeserializer( + OffsetDateTime.class, DateTimeFormatter.ISO_OFFSET_DATE_TIME, + new Function() { + @Override + public OffsetDateTime apply(TemporalAccessor temporalAccessor) { + return OffsetDateTime.from(temporalAccessor); + } + }, + new Function() { + @Override + public OffsetDateTime apply(FromIntegerArguments a) { + return OffsetDateTime.ofInstant(Instant.ofEpochMilli(a.value), a.zoneId); + } + }, + new Function() { + @Override + public OffsetDateTime apply(FromDecimalArguments a) { + return OffsetDateTime.ofInstant(Instant.ofEpochSecond(a.integer, a.fraction), a.zoneId); + } + }, + new BiFunction() { + @Override + public OffsetDateTime apply(OffsetDateTime d, ZoneId z) { + return d.withOffsetSameInstant(z.getRules().getOffset(d.toLocalDateTime())); + } + } + ); + + public static final CustomInstantDeserializer ZONED_DATE_TIME = new CustomInstantDeserializer( + ZonedDateTime.class, DateTimeFormatter.ISO_ZONED_DATE_TIME, + new Function() { + @Override + public ZonedDateTime apply(TemporalAccessor temporalAccessor) { + return ZonedDateTime.from(temporalAccessor); + } + }, + new Function() { + @Override + public ZonedDateTime apply(FromIntegerArguments a) { + return ZonedDateTime.ofInstant(Instant.ofEpochMilli(a.value), a.zoneId); + } + }, + new Function() { + @Override + public ZonedDateTime apply(FromDecimalArguments a) { + return ZonedDateTime.ofInstant(Instant.ofEpochSecond(a.integer, a.fraction), a.zoneId); + } + }, + new BiFunction() { + @Override + public ZonedDateTime apply(ZonedDateTime zonedDateTime, ZoneId zoneId) { + return zonedDateTime.withZoneSameInstant(zoneId); + } + } + ); + + protected final Function fromMilliseconds; + + protected final Function fromNanoseconds; + + protected final Function parsedToValue; + + protected final BiFunction adjust; + + protected CustomInstantDeserializer(Class supportedType, + DateTimeFormatter parser, + Function parsedToValue, + Function fromMilliseconds, + Function fromNanoseconds, + BiFunction adjust) { + super(supportedType, parser); + this.parsedToValue = parsedToValue; + this.fromMilliseconds = fromMilliseconds; + this.fromNanoseconds = fromNanoseconds; + this.adjust = adjust == null ? new BiFunction() { + @Override + public T apply(T t, ZoneId zoneId) { + return t; + } + } : adjust; + } + + @SuppressWarnings("unchecked") + protected CustomInstantDeserializer(CustomInstantDeserializer base, DateTimeFormatter f) { + super((Class) base.handledType(), f); + parsedToValue = base.parsedToValue; + fromMilliseconds = base.fromMilliseconds; + fromNanoseconds = base.fromNanoseconds; + adjust = base.adjust; + } + + @Override + protected JsonDeserializer withDateFormat(DateTimeFormatter dtf) { + if (dtf == _formatter) { + return this; + } + return new CustomInstantDeserializer(this, dtf); + } + + @Override + public T deserialize(JsonParser parser, DeserializationContext context) throws IOException { + //NOTE: Timestamps contain no timezone info, and are always in configured TZ. Only + //string values have to be adjusted to the configured TZ. + switch (parser.getCurrentTokenId()) { + case JsonTokenId.ID_NUMBER_FLOAT: { + BigDecimal value = parser.getDecimalValue(); + long seconds = value.longValue(); + int nanoseconds = DecimalUtils.extractNanosecondDecimal(value, seconds); + return fromNanoseconds.apply(new FromDecimalArguments( + seconds, nanoseconds, getZone(context))); + } + + case JsonTokenId.ID_NUMBER_INT: { + long timestamp = parser.getLongValue(); + if (context.isEnabled(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS)) { + return this.fromNanoseconds.apply(new FromDecimalArguments( + timestamp, 0, this.getZone(context) + )); + } + return this.fromMilliseconds.apply(new FromIntegerArguments( + timestamp, this.getZone(context) + )); + } + + case JsonTokenId.ID_STRING: { + String string = parser.getText().trim(); + if (string.length() == 0) { + return null; + } + if (string.endsWith("+0000")) { + string = string.substring(0, string.length() - 5) + "Z"; + } + T value; + try { + TemporalAccessor acc = _formatter.parse(string); + value = parsedToValue.apply(acc); + if (context.isEnabled(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)) { + return adjust.apply(value, this.getZone(context)); + } + } catch (DateTimeException e) { + throw _peelDTE(e); + } + return value; + } + } + throw context.mappingException("Expected type float, integer, or string."); + } + + private ZoneId getZone(DeserializationContext context) { + // Instants are always in UTC, so don't waste compute cycles + return (_valueClass == Instant.class) ? null : DateTimeUtils.timeZoneToZoneId(context.getTimeZone()); + } + + private static class FromIntegerArguments { + public final long value; + public final ZoneId zoneId; + + private FromIntegerArguments(long value, ZoneId zoneId) { + this.value = value; + this.zoneId = zoneId; + } + } + + private static class FromDecimalArguments { + public final long integer; + public final int fraction; + public final ZoneId zoneId; + + private FromDecimalArguments(long integer, int fraction, ZoneId zoneId) { + this.integer = integer; + this.fraction = fraction; + this.zoneId = zoneId; + } + } +} diff --git a/JSON.mustache b/JSON.mustache new file mode 100644 index 00000000000..63814a361fc --- /dev/null +++ b/JSON.mustache @@ -0,0 +1,521 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonParseException; +import com.google.gson.TypeAdapter; +import com.google.gson.internal.bind.util.ISO8601Utils; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import com.google.gson.JsonElement; +import io.gsonfire.GsonFireBuilder; +import io.gsonfire.TypeSelector; +{{#joda}} +import org.joda.time.DateTime; +import org.joda.time.LocalDate; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.DateTimeFormatterBuilder; +import org.joda.time.format.ISODateTimeFormat; +{{/joda}} +{{#threetenbp}} +import org.threeten.bp.LocalDate; +import org.threeten.bp.OffsetDateTime; +import org.threeten.bp.format.DateTimeFormatter; +{{/threetenbp}} + +import {{modelPackage}}.*; +import okio.ByteString; + +import java.io.IOException; +import java.io.StringReader; +import java.lang.reflect.Type; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.ParsePosition; +{{#java8}} +import java.time.LocalDate; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +{{/java8}} +import java.util.Date; +import java.util.Map; +import java.util.HashMap; + +public class JSON { + private Gson gson; + private boolean isLenientOnJson = false; + private DateTypeAdapter dateTypeAdapter = new DateTypeAdapter(); + private SqlDateTypeAdapter sqlDateTypeAdapter = new SqlDateTypeAdapter(); + {{#joda}} + private DateTimeTypeAdapter dateTimeTypeAdapter = new DateTimeTypeAdapter(); + private LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter(); + {{/joda}} + {{#jsr310}} + private OffsetDateTimeTypeAdapter offsetDateTimeTypeAdapter = new OffsetDateTimeTypeAdapter(); + private LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter(); + {{/jsr310}} + private ByteArrayAdapter byteArrayAdapter = new ByteArrayAdapter(); + + public static GsonBuilder createGson() { + GsonFireBuilder fireBuilder = new GsonFireBuilder() + {{#parent}} + .registerTypeSelector({{classname}}.class, new TypeSelector() { + @Override + public Class getClassForElement(JsonElement readElement) { + Map classByDiscriminatorValue = new HashMap(); + {{#children}} + classByDiscriminatorValue.put("{{name}}".toUpperCase(), {{classname}}.class); + {{/children}} + classByDiscriminatorValue.put("{{classname}}".toUpperCase(), {{classname}}.class); + return getClassByDiscriminator( + classByDiscriminatorValue, + getDiscriminatorValue(readElement, "{{discriminator}}")); + } + }) + {{/parent}} + ; + return fireBuilder.createGsonBuilder(); + } + + private static String getDiscriminatorValue(JsonElement readElement, String discriminatorField) { + JsonElement element = readElement.getAsJsonObject().get(discriminatorField); + if(null == element) { + throw new IllegalArgumentException("missing discriminator field: <" + discriminatorField + ">"); + } + return element.getAsString(); + } + + private static Class getClassByDiscriminator(Map classByDiscriminatorValue, String discriminatorValue) { + Class clazz = (Class) classByDiscriminatorValue.get(discriminatorValue.toUpperCase()); + if(null == clazz) { + throw new IllegalArgumentException("cannot determine model class of name: <" + discriminatorValue + ">"); + } + return clazz; + } + + public JSON() { + gson = createGson() + .registerTypeAdapter(Date.class, dateTypeAdapter) + .registerTypeAdapter(java.sql.Date.class, sqlDateTypeAdapter) + {{#joda}} + .registerTypeAdapter(DateTime.class, dateTimeTypeAdapter) + .registerTypeAdapter(LocalDate.class, localDateTypeAdapter) + {{/joda}} + {{#jsr310}} + .registerTypeAdapter(OffsetDateTime.class, offsetDateTimeTypeAdapter) + .registerTypeAdapter(LocalDate.class, localDateTypeAdapter) + {{/jsr310}} + .registerTypeAdapter(byte[].class, byteArrayAdapter) + .create(); + } + + /** + * Get Gson. + * + * @return Gson + */ + public Gson getGson() { + return gson; + } + + /** + * Set Gson. + * + * @param gson Gson + * @return JSON + */ + public JSON setGson(Gson gson) { + this.gson = gson; + return this; + } + + public JSON setLenientOnJson(boolean lenientOnJson) { + isLenientOnJson = lenientOnJson; + return this; + } + + /** + * Serialize the given Java object into JSON string. + * + * @param obj Object + * @return String representation of the JSON + */ + public String serialize(Object obj) { + return gson.toJson(obj); + } + + /** + * Deserialize the given JSON string to Java object. + * + * @param Type + * @param body The JSON string + * @param returnType The type to deserialize into + * @return The deserialized Java object + */ + @SuppressWarnings("unchecked") + public T deserialize(String body, Type returnType) { + try { + if (isLenientOnJson) { + JsonReader jsonReader = new JsonReader(new StringReader(body)); + // see https://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/stream/JsonReader.html#setLenient(boolean) + jsonReader.setLenient(true); + return gson.fromJson(jsonReader, returnType); + } else { + return gson.fromJson(body, returnType); + } + } catch (JsonParseException e) { + // Fallback processing when failed to parse JSON form response body: + // return the response body string directly for the String return type; + if (returnType.equals(String.class)) + return (T) body; + else throw (e); + } + } + + /** + * Gson TypeAdapter for Byte Array type + */ + public class ByteArrayAdapter extends TypeAdapter { + + @Override + public void write(JsonWriter out, byte[] value) throws IOException { + if (value == null) { + out.nullValue(); + } else { + out.value(ByteString.of(value).base64()); + } + } + + @Override + public byte[] read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String bytesAsBase64 = in.nextString(); + ByteString byteString = ByteString.decodeBase64(bytesAsBase64); + return byteString.toByteArray(); + } + } + } + + {{#joda}} + /** + * Gson TypeAdapter for Joda DateTime type + */ + public static class DateTimeTypeAdapter extends TypeAdapter { + + private DateTimeFormatter formatter; + + public DateTimeTypeAdapter() { + this(new DateTimeFormatterBuilder() + .append(ISODateTimeFormat.dateTime().getPrinter(), ISODateTimeFormat.dateOptionalTimeParser().getParser()) + .toFormatter()); + } + + public DateTimeTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } + + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } + + @Override + public void write(JsonWriter out, DateTime date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.print(date)); + } + } + + @Override + public DateTime read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + return formatter.parseDateTime(date); + } + } + } + + /** + * Gson TypeAdapter for Joda LocalDate type + */ + public class LocalDateTypeAdapter extends TypeAdapter { + + private DateTimeFormatter formatter; + + public LocalDateTypeAdapter() { + this(ISODateTimeFormat.date()); + } + + public LocalDateTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } + + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } + + @Override + public void write(JsonWriter out, LocalDate date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.print(date)); + } + } + + @Override + public LocalDate read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + return formatter.parseLocalDate(date); + } + } + } + + public JSON setDateTimeFormat(DateTimeFormatter dateFormat) { + dateTimeTypeAdapter.setFormat(dateFormat); + return this; + } + + public JSON setLocalDateFormat(DateTimeFormatter dateFormat) { + localDateTypeAdapter.setFormat(dateFormat); + return this; + } + + {{/joda}} + {{#jsr310}} + /** + * Gson TypeAdapter for JSR310 OffsetDateTime type + */ + public static class OffsetDateTimeTypeAdapter extends TypeAdapter { + + private DateTimeFormatter formatter; + + public OffsetDateTimeTypeAdapter() { + this(DateTimeFormatter.ISO_OFFSET_DATE_TIME); + } + + public OffsetDateTimeTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } + + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } + + @Override + public void write(JsonWriter out, OffsetDateTime date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.format(date)); + } + } + + @Override + public OffsetDateTime read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + if (date.endsWith("+0000")) { + date = date.substring(0, date.length()-5) + "Z"; + } + return OffsetDateTime.parse(date, formatter); + } + } + } + + /** + * Gson TypeAdapter for JSR310 LocalDate type + */ + public class LocalDateTypeAdapter extends TypeAdapter { + + private DateTimeFormatter formatter; + + public LocalDateTypeAdapter() { + this(DateTimeFormatter.ISO_LOCAL_DATE); + } + + public LocalDateTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } + + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } + + @Override + public void write(JsonWriter out, LocalDate date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.format(date)); + } + } + + @Override + public LocalDate read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + return LocalDate.parse(date, formatter); + } + } + } + + public JSON setOffsetDateTimeFormat(DateTimeFormatter dateFormat) { + offsetDateTimeTypeAdapter.setFormat(dateFormat); + return this; + } + + public JSON setLocalDateFormat(DateTimeFormatter dateFormat) { + localDateTypeAdapter.setFormat(dateFormat); + return this; + } + + {{/jsr310}} + /** + * Gson TypeAdapter for java.sql.Date type + * If the dateFormat is null, a simple "yyyy-MM-dd" format will be used + * (more efficient than SimpleDateFormat). + */ + public static class SqlDateTypeAdapter extends TypeAdapter { + + private DateFormat dateFormat; + + public SqlDateTypeAdapter() { + } + + public SqlDateTypeAdapter(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + public void setFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + @Override + public void write(JsonWriter out, java.sql.Date date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + String value; + if (dateFormat != null) { + value = dateFormat.format(date); + } else { + value = date.toString(); + } + out.value(value); + } + } + + @Override + public java.sql.Date read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + try { + if (dateFormat != null) { + return new java.sql.Date(dateFormat.parse(date).getTime()); + } + return new java.sql.Date(ISO8601Utils.parse(date, new ParsePosition(0)).getTime()); + } catch (ParseException e) { + throw new JsonParseException(e); + } + } + } + } + + /** + * Gson TypeAdapter for java.util.Date type + * If the dateFormat is null, ISO8601Utils will be used. + */ + public static class DateTypeAdapter extends TypeAdapter { + + private DateFormat dateFormat; + + public DateTypeAdapter() { + } + + public DateTypeAdapter(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + public void setFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + @Override + public void write(JsonWriter out, Date date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + String value; + if (dateFormat != null) { + value = dateFormat.format(date); + } else { + value = ISO8601Utils.format(date, true); + } + out.value(value); + } + } + + @Override + public Date read(JsonReader in) throws IOException { + try { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + try { + if (dateFormat != null) { + return dateFormat.parse(date); + } + return ISO8601Utils.parse(date, new ParsePosition(0)); + } catch (ParseException e) { + throw new JsonParseException(e); + } + } + } catch (IllegalArgumentException e) { + throw new JsonParseException(e); + } + } + } + + public JSON setDateFormat(DateFormat dateFormat) { + dateTypeAdapter.setFormat(dateFormat); + return this; + } + + public JSON setSqlDateFormat(DateFormat dateFormat) { + sqlDateTypeAdapter.setFormat(dateFormat); + return this; + } + +} diff --git a/Pair.mustache b/Pair.mustache new file mode 100644 index 00000000000..c08f145a482 --- /dev/null +++ b/Pair.mustache @@ -0,0 +1,41 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +{{>generatedAnnotation}} +public class Pair { + private String name = ""; + private String value = ""; + + public Pair (String name, String value) { + setName(name); + setValue(value); + } + + private void setName(String name) { + if (!isValidString(name)) return; + + this.name = name; + } + + private void setValue(String value) { + if (!isValidString(value)) return; + + this.value = value; + } + + public String getName() { + return this.name; + } + + public String getValue() { + return this.value; + } + + private boolean isValidString(String arg) { + if (arg == null) return false; + if (arg.trim().isEmpty()) return false; + + return true; + } +} diff --git a/README.mustache b/README.mustache new file mode 100644 index 00000000000..6ec3efff471 --- /dev/null +++ b/README.mustache @@ -0,0 +1,167 @@ +# {{artifactId}} + +{{appName}} +- API version: {{appVersion}} +{{^hideGenerationTimestamp}} + - Build date: {{generatedDate}} +{{/hideGenerationTimestamp}} + +{{#appDescription}}{{{appDescription}}}{{/appDescription}} + +{{#infoUrl}} + For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) +{{/infoUrl}} + +*Automatically generated by the [Swagger Codegen](https://github.com/swagger-api/swagger-codegen)* + + +## Requirements + +Building the API client library requires: +1. Java 1.7+ +2. Maven/Gradle + +## Installation + +To install the API client library to your local Maven repository, simply execute: + +```shell +mvn clean install +``` + +To deploy it to a remote Maven repository instead, configure the settings of the repository and execute: + +```shell +mvn clean deploy +``` + +Refer to the [OSSRH Guide](http://central.sonatype.org/pages/ossrh-guide.html) for more information. + +### Maven users + +Add this dependency to your project's POM: + +```xml + + {{{groupId}}} + {{{artifactId}}} + {{{artifactVersion}}} + compile + +``` + +### Gradle users + +Add this dependency to your project's build file: + +```groovy +compile "{{{groupId}}}:{{{artifactId}}}:{{{artifactVersion}}}" +``` + +### Others + +At first generate the JAR by executing: + +```shell +mvn clean package +``` + +Then manually install the following JARs: + +* `target/{{{artifactId}}}-{{{artifactVersion}}}.jar` +* `target/lib/*.jar` + +## Getting Started + +Please follow the [installation](#installation) instruction and execute the following Java code: + +```java +{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}} +import {{{invokerPackage}}}.*; +import {{{invokerPackage}}}.auth.*; +import {{{modelPackage}}}.*; +import {{{package}}}.{{{classname}}}; + +import java.io.File; +import java.util.*; + +public class {{{classname}}}Example { + + public static void main(String[] args) { + {{#hasAuthMethods}}ApiClient defaultClient = Configuration.getDefaultApiClient(); + {{#authMethods}}{{#isBasic}} + // Configure HTTP basic authorization: {{{name}}} + HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setUsername("YOUR USERNAME"); + {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasic}}{{#isApiKey}} + // Configure API key authorization: {{{name}}} + ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setApiKey("YOUR API KEY"); + // Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null) + //{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} + // Configure OAuth2 access token for authorization: {{{name}}} + OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}} + {{/authMethods}} + {{/hasAuthMethods}} + + {{{classname}}} apiInstance = new {{{classname}}}(); + {{#allParams}} + {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} + {{/allParams}} + try { + {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + System.out.println(result);{{/returnType}} + } catch (ApiException e) { + System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); + e.printStackTrace(); + } + } +} +{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} +``` + +## Documentation for API Endpoints + +All URIs are relative to *{{basePath}}* + +Class | Method | HTTP request | Description +------------ | ------------- | ------------- | ------------- +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} + +## Documentation for Models + +{{#models}}{{#model}} - [{{classname}}]({{modelDocPath}}{{classname}}.md) +{{/model}}{{/models}} + +## Documentation for Authorization + +{{^authMethods}}All endpoints do not require authorization. +{{/authMethods}}Authentication schemes defined for the API: +{{#authMethods}}### {{name}} + +{{#isApiKey}}- **Type**: API key +- **API key parameter name**: {{keyParamName}} +- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}} +{{/isApiKey}} +{{#isBasic}}- **Type**: HTTP basic authentication +{{/isBasic}} +{{#isOAuth}}- **Type**: OAuth +- **Flow**: {{flow}} +- **Authorization URL**: {{authorizationUrl}} +- **Scopes**: {{^scopes}}N/A{{/scopes}} +{{#scopes}} - {{scope}}: {{description}} +{{/scopes}} +{{/isOAuth}} + +{{/authMethods}} + +## Recommendation + +It's recommended to create an instance of `ApiClient` per thread in a multithreaded environment to avoid any potential issues. + +## Author + +{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} +{{/hasMore}}{{/apis}}{{/apiInfo}} diff --git a/RFC3339DateFormat.mustache b/RFC3339DateFormat.mustache new file mode 100644 index 00000000000..16fd2a495a7 --- /dev/null +++ b/RFC3339DateFormat.mustache @@ -0,0 +1,21 @@ +{{>licenseInfo}} +package {{invokerPackage}}; + +import com.fasterxml.jackson.databind.util.ISO8601DateFormat; +import com.fasterxml.jackson.databind.util.ISO8601Utils; + +import java.text.FieldPosition; +import java.util.Date; + + +public class RFC3339DateFormat extends ISO8601DateFormat { + + // Same as ISO8601DateFormat but serializing milliseconds. + @Override + public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { + String value = ISO8601Utils.format(date, true); + toAppendTo.append(value); + return toAppendTo; + } + +} \ No newline at end of file diff --git a/StringUtil.mustache b/StringUtil.mustache new file mode 100644 index 00000000000..7b72a7bab45 --- /dev/null +++ b/StringUtil.mustache @@ -0,0 +1,44 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +{{>generatedAnnotation}} +public class StringUtil { + /** + * Check if the given array contains the given value (with case-insensitive comparison). + * + * @param array The array + * @param value The value to search + * @return true if the array contains the value + */ + public static boolean containsIgnoreCase(String[] array, String value) { + for (String str : array) { + if (value == null && str == null) return true; + if (value != null && value.equalsIgnoreCase(str)) return true; + } + return false; + } + + /** + * Join an array of strings with the given separator. + *

+ * Note: This might be replaced by utility method from commons-lang or guava someday + * if one of those libraries is added as dependency. + *

+ * + * @param array The array of strings + * @param separator The separator + * @return the resulting string + */ + public static String join(String[] array, String separator) { + int len = array.length; + if (len == 0) return ""; + + StringBuilder out = new StringBuilder(); + out.append(array[0]); + for (int i = 1; i < len; i++) { + out.append(separator).append(array[i]); + } + return out.toString(); + } +} diff --git a/api.mustache b/api.mustache new file mode 100644 index 00000000000..542ccbba287 --- /dev/null +++ b/api.mustache @@ -0,0 +1,117 @@ +{{>licenseInfo}} +package {{package}}; + +import com.sun.jersey.api.client.GenericType; + +import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.Configuration; +import {{modelPackage}}.*; +import {{invokerPackage}}.Pair; + +{{#imports}}import {{import}}; +{{/imports}} + + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}} { + private ApiClient {{localVariablePrefix}}apiClient; + + public {{classname}}() { + this(Configuration.getDefaultApiClient()); + } + + public {{classname}}(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + public ApiClient getApiClient() { + return {{localVariablePrefix}}apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + {{#operation}} + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} + {{#returnType}} + * @return {{returnType}} + {{/returnType}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + Object {{localVariablePrefix}}localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + } + {{/required}}{{/allParams}} + // create path and map variables + String {{localVariablePrefix}}localVarPath = "{{{path}}}"{{#pathParams}} + .replaceAll("\\{" + "{{baseName}}" + "\\}", {{localVariablePrefix}}apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; + + // query params + {{javaUtilPrefix}}List {{localVariablePrefix}}localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}List {{localVariablePrefix}}localVarCollectionQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarFormParams = new {{javaUtilPrefix}}HashMap(); + + {{#queryParams}} + {{localVariablePrefix}}{{#collectionFormat}}localVarCollectionQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPairs("{{{collectionFormat}}}", {{/collectionFormat}}{{^collectionFormat}}localVarQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPair({{/collectionFormat}}"{{baseName}}", {{paramName}})); + {{/queryParams}} + + {{#headerParams}}if ({{paramName}} != null) + {{localVariablePrefix}}localVarHeaderParams.put("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}})); + {{/headerParams}} + + {{#formParams}}if ({{paramName}} != null) + {{localVariablePrefix}}localVarFormParams.put("{{baseName}}", {{paramName}}); + {{/formParams}} + + final String[] {{localVariablePrefix}}localVarAccepts = { + {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} + }; + final String {{localVariablePrefix}}localVarAccept = {{localVariablePrefix}}apiClient.selectHeaderAccept({{localVariablePrefix}}localVarAccepts); + + final String[] {{localVariablePrefix}}localVarContentTypes = { + {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} + }; + final String {{localVariablePrefix}}localVarContentType = {{localVariablePrefix}}apiClient.selectHeaderContentType({{localVariablePrefix}}localVarContentTypes); + + String[] {{localVariablePrefix}}localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + + {{#returnType}} + GenericType<{{{returnType}}}> {{localVariablePrefix}}localVarReturnType = new GenericType<{{{returnType}}}>() {}; + return {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarCollectionQueryParams, {{localVariablePrefix}}localVarPostBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccept, {{localVariablePrefix}}localVarContentType, {{localVariablePrefix}}localVarAuthNames, {{localVariablePrefix}}localVarReturnType); + {{/returnType}}{{^returnType}} + {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarCollectionQueryParams, {{localVariablePrefix}}localVarPostBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccept, {{localVariablePrefix}}localVarContentType, {{localVariablePrefix}}localVarAuthNames, null); + {{/returnType}} + } + {{/operation}} +} +{{/operations}} diff --git a/apiException.mustache b/apiException.mustache new file mode 100644 index 00000000000..5b450c9ba62 --- /dev/null +++ b/apiException.mustache @@ -0,0 +1,80 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import java.util.Map; +import java.util.List; + +{{>generatedAnnotation}} +public class ApiException extends{{#useRuntimeException}} RuntimeException {{/useRuntimeException}}{{^useRuntimeException}} Exception {{/useRuntimeException}}{ + private int code = 0; + private Map> responseHeaders = null; + private String responseBody = null; + + public ApiException() {} + + public ApiException(Throwable throwable) { + super(throwable); + } + + public ApiException(String message) { + super(message); + } + + public ApiException(String message, Throwable throwable, int code, Map> responseHeaders, String responseBody) { + super(message, throwable); + this.code = code; + this.responseHeaders = responseHeaders; + this.responseBody = responseBody; + } + + public ApiException(String message, int code, Map> responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(String message, Throwable throwable, int code, Map> responseHeaders) { + this(message, throwable, code, responseHeaders, null); + } + + public ApiException(int code, Map> responseHeaders, String responseBody) { + this((String) null, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(int code, String message) { + super(message); + this.code = code; + } + + public ApiException(int code, String message, Map> responseHeaders, String responseBody) { + this(code, message); + this.responseHeaders = responseHeaders; + this.responseBody = responseBody; + } + + /** + * Get the HTTP status code. + * + * @return HTTP status code + */ + public int getCode() { + return code; + } + + /** + * Get the HTTP response headers. + * + * @return A map of list of string + */ + public Map> getResponseHeaders() { + return responseHeaders; + } + + /** + * Get the HTTP response body. + * + * @return Response body in the form of string + */ + public String getResponseBody() { + return responseBody; + } +} diff --git a/api_doc.mustache b/api_doc.mustache new file mode 100644 index 00000000000..bbb5b66f840 --- /dev/null +++ b/api_doc.mustache @@ -0,0 +1,82 @@ +# {{classname}}{{#description}} +{{description}}{{/description}} + +All URIs are relative to *{{basePath}}* + +Method | HTTP request | Description +------------- | ------------- | ------------- +{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}} + +{{#operations}} +{{#operation}} + +# **{{operationId}}** +> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) + +{{summary}}{{#notes}} + +{{notes}}{{/notes}} + +### Example +```java +// Import classes:{{#hasAuthMethods}} +//import {{{invokerPackage}}}.ApiClient;{{/hasAuthMethods}} +//import {{{invokerPackage}}}.ApiException;{{#hasAuthMethods}} +//import {{{invokerPackage}}}.Configuration; +//import {{{invokerPackage}}}.auth.*;{{/hasAuthMethods}} +//import {{{package}}}.{{{classname}}}; + +{{#hasAuthMethods}} +ApiClient defaultClient = Configuration.getDefaultApiClient(); +{{#authMethods}}{{#isBasic}} +// Configure HTTP basic authorization: {{{name}}} +HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); +{{{name}}}.setUsername("YOUR USERNAME"); +{{{name}}}.setPassword("YOUR PASSWORD");{{/isBasic}}{{#isApiKey}} +// Configure API key authorization: {{{name}}} +ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); +{{{name}}}.setApiKey("YOUR API KEY"); +// Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null) +//{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} +// Configure OAuth2 access token for authorization: {{{name}}} +OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); +{{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}} +{{/authMethods}} +{{/hasAuthMethods}} + +{{{classname}}} apiInstance = new {{{classname}}}(); +{{#allParams}} +{{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} +{{/allParams}} +try { + {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + System.out.println(result);{{/returnType}} +} catch (ApiException e) { + System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); + e.printStackTrace(); +} +``` + +### Parameters +{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} +Name | Type | Description | Notes +------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} +{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} +{{/allParams}} + +### Return type + +{{#returnType}}{{#returnTypeIsPrimitive}}**{{returnType}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{returnType}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}null (empty response body){{/returnType}} + +### Authorization + +{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{name}}](../README.md#{{name}}){{^-last}}, {{/-last}}{{/authMethods}} + +### HTTP request headers + + - **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} + - **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} + +{{/operation}} +{{/operations}} diff --git a/api_test.mustache b/api_test.mustache new file mode 100644 index 00000000000..1d95ac2ed89 --- /dev/null +++ b/api_test.mustache @@ -0,0 +1,45 @@ +{{>licenseInfo}} + +package {{package}}; + +import {{invokerPackage}}.ApiException; +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Test; +import org.junit.Ignore; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +@Ignore +public class {{classname}}Test { + + private final {{classname}} api = new {{classname}}(); + + {{#operations}}{{#operation}} + /** + * {{summary}} + * + * {{notes}} + * + * @throws ApiException + * if the Api call fails + */ + @Test + public void {{operationId}}Test() throws ApiException { + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + + // TODO: test validations + } + {{/operation}}{{/operations}} +} diff --git a/auth/ApiKeyAuth.mustache b/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..5af060f1173 --- /dev/null +++ b/auth/ApiKeyAuth.mustache @@ -0,0 +1,64 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; + +import java.util.Map; +import java.util.List; + +{{>generatedAnnotation}} +public class ApiKeyAuth implements Authentication { + private final String location; + private final String paramName; + + private String apiKey; + private String apiKeyPrefix; + + public ApiKeyAuth(String location, String paramName) { + this.location = location; + this.paramName = paramName; + } + + public String getLocation() { + return location; + } + + public String getParamName() { + return paramName; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + public String getApiKeyPrefix() { + return apiKeyPrefix; + } + + public void setApiKeyPrefix(String apiKeyPrefix) { + this.apiKeyPrefix = apiKeyPrefix; + } + + @Override + public void applyToParams(List queryParams, Map headerParams) { + if (apiKey == null) { + return; + } + String value; + if (apiKeyPrefix != null) { + value = apiKeyPrefix + " " + apiKey; + } else { + value = apiKey; + } + if ("query".equals(location)) { + queryParams.add(new Pair(paramName, value)); + } else if ("header".equals(location)) { + headerParams.put(paramName, value); + } + } +} diff --git a/auth/Authentication.mustache b/auth/Authentication.mustache new file mode 100644 index 00000000000..26174fa3b59 --- /dev/null +++ b/auth/Authentication.mustache @@ -0,0 +1,18 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; + +import java.util.Map; +import java.util.List; + +public interface Authentication { + /** + * Apply authentication settings to header and query params. + * + * @param queryParams List of query parameters + * @param headerParams Map of header parameters + */ + void applyToParams(List queryParams, Map headerParams); +} diff --git a/auth/HttpBasicAuth.mustache b/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..015e042e171 --- /dev/null +++ b/auth/HttpBasicAuth.mustache @@ -0,0 +1,60 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; + +{{^java8}} +import com.migcomponents.migbase64.Base64; +{{/java8}} +{{#java8}} +import java.util.Base64; +import java.nio.charset.StandardCharsets; +{{/java8}} + +import java.util.Map; +import java.util.List; + +{{^java8}} +import java.io.UnsupportedEncodingException; +{{/java8}} + +{{>generatedAnnotation}} +public class HttpBasicAuth implements Authentication { + private String username; + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public void applyToParams(List queryParams, Map headerParams) { + if (username == null && password == null) { + return; + } + String str = (username == null ? "" : username) + ":" + (password == null ? "" : password); +{{^java8}} + try { + headerParams.put("Authorization", "Basic " + Base64.encodeToString(str.getBytes("UTF-8"), false)); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } +{{/java8}} +{{#java8}} + headerParams.put("Authorization", "Basic " + Base64.getEncoder().encodeToString(str.getBytes(StandardCharsets.UTF_8))); +{{/java8}} + } +} diff --git a/auth/OAuth.mustache b/auth/OAuth.mustache new file mode 100644 index 00000000000..ffc9923d1fe --- /dev/null +++ b/auth/OAuth.mustache @@ -0,0 +1,28 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; + +import java.util.Map; +import java.util.List; + +{{>generatedAnnotation}} +public class OAuth implements Authentication { + private String accessToken; + + public String getAccessToken() { + return accessToken; + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + @Override + public void applyToParams(List queryParams, Map headerParams) { + if (accessToken != null) { + headerParams.put("Authorization", "Bearer " + accessToken); + } + } +} diff --git a/auth/OAuthFlow.mustache b/auth/OAuthFlow.mustache new file mode 100644 index 00000000000..002e9572f33 --- /dev/null +++ b/auth/OAuthFlow.mustache @@ -0,0 +1,7 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +public enum OAuthFlow { + accessCode, implicit, password, application +} diff --git a/beanValidation.mustache b/beanValidation.mustache new file mode 100644 index 00000000000..7c347758d8d --- /dev/null +++ b/beanValidation.mustache @@ -0,0 +1,16 @@ +{{#required}} + @NotNull +{{/required}} +{{#isContainer}} +{{^isPrimitiveType}} +{{^isEnum}} + @Valid +{{/isEnum}} +{{/isPrimitiveType}} +{{/isContainer}} +{{#isNotContainer}} +{{^isPrimitiveType}} + @Valid +{{/isPrimitiveType}} +{{/isNotContainer}} +{{>beanValidationCore}} \ No newline at end of file diff --git a/beanValidationCore.mustache b/beanValidationCore.mustache new file mode 100644 index 00000000000..8bcdce3df16 --- /dev/null +++ b/beanValidationCore.mustache @@ -0,0 +1,20 @@ +{{#pattern}} @Pattern(regexp="{{{pattern}}}"){{/pattern}}{{! +minLength && maxLength set +}}{{#minLength}}{{#maxLength}} @Size(min={{minLength}},max={{maxLength}}){{/maxLength}}{{/minLength}}{{! +minLength set, maxLength not +}}{{#minLength}}{{^maxLength}} @Size(min={{minLength}}){{/maxLength}}{{/minLength}}{{! +minLength not set, maxLength set +}}{{^minLength}}{{#maxLength}} @Size(max={{maxLength}}){{/maxLength}}{{/minLength}}{{! +@Size: minItems && maxItems set +}}{{#minItems}}{{#maxItems}} @Size(min={{minItems}},max={{maxItems}}){{/maxItems}}{{/minItems}}{{! +@Size: minItems set, maxItems not +}}{{#minItems}}{{^maxItems}} @Size(min={{minItems}}){{/maxItems}}{{/minItems}}{{! +@Size: minItems not set && maxItems set +}}{{^minItems}}{{#maxItems}} @Size(max={{maxItems}}){{/maxItems}}{{/minItems}}{{! +check for integer or long / all others=decimal type with @Decimal* +isInteger set +}}{{#isInteger}}{{#minimum}} @Min({{minimum}}){{/minimum}}{{#maximum}} @Max({{maximum}}){{/maximum}}{{/isInteger}}{{! +isLong set +}}{{#isLong}}{{#minimum}} @Min({{minimum}}L){{/minimum}}{{#maximum}} @Max({{maximum}}L){{/maximum}}{{/isLong}}{{! +Not Integer, not Long => we have a decimal value! +}}{{^isInteger}}{{^isLong}}{{#minimum}} @DecimalMin("{{minimum}}"){{/minimum}}{{#maximum}} @DecimalMax("{{maximum}}"){{/maximum}}{{/isLong}}{{/isInteger}} \ No newline at end of file diff --git a/beanValidationQueryParams.mustache b/beanValidationQueryParams.mustache new file mode 100644 index 00000000000..f8eef8f94c7 --- /dev/null +++ b/beanValidationQueryParams.mustache @@ -0,0 +1 @@ +{{#required}} @NotNull{{/required}}{{>beanValidationCore}} \ No newline at end of file diff --git a/build.gradle.mustache b/build.gradle.mustache new file mode 100644 index 00000000000..af0d3d55d85 --- /dev/null +++ b/build.gradle.mustache @@ -0,0 +1,137 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + } + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + {{#java8}} + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + {{/java8}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + swagger_annotations_version = "1.5.17" + jackson_version = "{{^threetenbp}}2.8.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" + jersey_version = "1.19.4" + jodatime_version = "2.9.9" + junit_version = "4.12" +} + +dependencies { + compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "com.sun.jersey:jersey-client:$jersey_version" + compile "com.sun.jersey.contribs:jersey-multipart:$jersey_version" + compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + {{#joda}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + {{/joda}} + {{#java8}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{/java8}} + {{#threetenbp}} + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_version" + {{/threetenbp}} + {{^java8}} + compile "com.brsanthu:migbase64:2.2" + {{/java8}} + testCompile "junit:junit:$junit_version" +} diff --git a/build.sbt.mustache b/build.sbt.mustache new file mode 100644 index 00000000000..e69de29bb2d diff --git a/enum_outer_doc.mustache b/enum_outer_doc.mustache new file mode 100644 index 00000000000..20c512aaeae --- /dev/null +++ b/enum_outer_doc.mustache @@ -0,0 +1,7 @@ +# {{classname}} + +## Enum + +{{#allowableValues}}{{#enumVars}} +* `{{name}}` (value: `{{{value}}}`) +{{/enumVars}}{{/allowableValues}} diff --git a/generatedAnnotation.mustache b/generatedAnnotation.mustache new file mode 100644 index 00000000000..a47b6faa85b --- /dev/null +++ b/generatedAnnotation.mustache @@ -0,0 +1 @@ +{{^hideGenerationTimestamp}}@javax.annotation.Generated(value = "{{generatorClass}}", date = "{{generatedDate}}"){{/hideGenerationTimestamp}} \ No newline at end of file diff --git a/git_push.sh.mustache b/git_push.sh.mustache new file mode 100755 index 00000000000..a2d75234837 --- /dev/null +++ b/git_push.sh.mustache @@ -0,0 +1,52 @@ +#!/bin/sh +# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ +# +# Usage example: /bin/sh ./git_push.sh wing328 swagger-petstore-perl "minor update" + +git_user_id=$1 +git_repo_id=$2 +release_note=$3 + +if [ "$git_user_id" = "" ]; then + git_user_id="{{{gitUserId}}}" + echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id" +fi + +if [ "$git_repo_id" = "" ]; then + git_repo_id="{{{gitRepoId}}}" + echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id" +fi + +if [ "$release_note" = "" ]; then + release_note="{{{releaseNote}}}" + echo "[INFO] No command line input provided. Set \$release_note to $release_note" +fi + +# Initialize the local directory as a Git repository +git init + +# Adds the files in the local repository and stages them for commit. +git add . + +# Commits the tracked changes and prepares them to be pushed to a remote repository. +git commit -m "$release_note" + +# Sets the new remote +git_remote=`git remote` +if [ "$git_remote" = "" ]; then # git remote not defined + + if [ "$GIT_TOKEN" = "" ]; then + echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment." + git remote add origin https://github.com/${git_user_id}/${git_repo_id}.git + else + git remote add origin https://${git_user_id}:${GIT_TOKEN}@github.com/${git_user_id}/${git_repo_id}.git + fi + +fi + +git pull origin master + +# Pushes (Forces) the changes in the local repository up to the remote repository +echo "Git pushing to https://github.com/${git_user_id}/${git_repo_id}.git" +git push origin master 2>&1 | grep -v 'To https' + diff --git a/gitignore.mustache b/gitignore.mustache new file mode 100644 index 00000000000..a530464afa1 --- /dev/null +++ b/gitignore.mustache @@ -0,0 +1,21 @@ +*.class + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear + +# exclude jar for gradle wrapper +!gradle/wrapper/*.jar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +# build files +**/target +target +.gradle +build diff --git a/gradle-wrapper.jar b/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..2c6137b87896c8f70315ae454e00a969ef5f6019 GIT binary patch literal 53639 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 F{{tUq7iIte literal 0 HcmV?d00001 diff --git a/gradle-wrapper.properties.mustache b/gradle-wrapper.properties.mustache new file mode 100644 index 00000000000..b7a36473955 --- /dev/null +++ b/gradle-wrapper.properties.mustache @@ -0,0 +1,6 @@ +#Tue May 17 23:08:05 CST 2016 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.6-bin.zip diff --git a/gradle.properties.mustache b/gradle.properties.mustache new file mode 100644 index 00000000000..05644f0754a --- /dev/null +++ b/gradle.properties.mustache @@ -0,0 +1,2 @@ +# Uncomment to build for Android +#target = android \ No newline at end of file diff --git a/gradlew.bat.mustache b/gradlew.bat.mustache new file mode 100644 index 00000000000..5f192121eb4 --- /dev/null +++ b/gradlew.bat.mustache @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/gradlew.mustache b/gradlew.mustache new file mode 100755 index 00000000000..9d82f789151 --- /dev/null +++ b/gradlew.mustache @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/libraries/feign/ApiClient.mustache b/libraries/feign/ApiClient.mustache new file mode 100644 index 00000000000..fa1dea42e8a --- /dev/null +++ b/libraries/feign/ApiClient.mustache @@ -0,0 +1,361 @@ +package {{invokerPackage}}; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; +{{#threetenbp}} +import org.threeten.bp.*; +{{/threetenbp}} + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +{{#joda}} +import com.fasterxml.jackson.datatype.joda.JodaModule; +{{/joda}} +{{#java8}} +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{/java8}} +{{#threetenbp}} +import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; +{{/threetenbp}} + +import feign.Feign; +import feign.RequestInterceptor; +import feign.form.FormEncoder; +import feign.jackson.JacksonDecoder; +import feign.jackson.JacksonEncoder; +import feign.slf4j.Slf4jLogger; +import {{invokerPackage}}.auth.*; +import {{invokerPackage}}.auth.OAuth.AccessTokenListener; + +{{>generatedAnnotation}} +public class ApiClient { + public interface Api {} + + protected ObjectMapper objectMapper; + private String basePath = "{{{basePath}}}"; + private Map apiAuthorizations; + private Feign.Builder feignBuilder; + + public ApiClient() { + objectMapper = createObjectMapper(); + apiAuthorizations = new LinkedHashMap(); + feignBuilder = Feign.builder() + .encoder(new FormEncoder(new JacksonEncoder(objectMapper))) + .decoder(new JacksonDecoder(objectMapper)) + .logger(new Slf4jLogger()); + } + + public ApiClient(String[] authNames) { + this(); + for(String authName : authNames) { + {{#hasAuthMethods}} + RequestInterceptor auth; + {{#authMethods}}if ("{{name}}".equals(authName)) { + {{#isBasic}} + auth = new HttpBasicAuth(); + {{/isBasic}} + {{#isApiKey}} + auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"); + {{/isApiKey}} + {{#isOAuth}} + auth = new OAuth(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{#hasMore}}, {{/hasMore}}{{/scopes}}"); + {{/isOAuth}} + } else {{/authMethods}}{ + throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); + } + addAuthorization(authName, auth); + {{/hasAuthMethods}} + {{^hasAuthMethods}} + throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); + {{/hasAuthMethods}} + } + } + + /** + * Basic constructor for single auth name + * @param authName + */ + public ApiClient(String authName) { + this(new String[]{authName}); + } + + /** + * Helper constructor for single api key + * @param authName + * @param apiKey + */ + public ApiClient(String authName, String apiKey) { + this(authName); + this.setApiKey(apiKey); + } + + /** + * Helper constructor for single basic auth or password oauth2 + * @param authName + * @param username + * @param password + */ + public ApiClient(String authName, String username, String password) { + this(authName); + this.setCredentials(username, password); + } + + /** + * Helper constructor for single password oauth2 + * @param authName + * @param clientId + * @param secret + * @param username + * @param password + */ + public ApiClient(String authName, String clientId, String secret, String username, String password) { + this(authName); + this.getTokenEndPoint() + .setClientId(clientId) + .setClientSecret(secret) + .setUsername(username) + .setPassword(password); + } + + public String getBasePath() { + return basePath; + } + + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + public Map getApiAuthorizations() { + return apiAuthorizations; + } + + public void setApiAuthorizations(Map apiAuthorizations) { + this.apiAuthorizations = apiAuthorizations; + } + + public Feign.Builder getFeignBuilder() { + return feignBuilder; + } + + public ApiClient setFeignBuilder(Feign.Builder feignBuilder) { + this.feignBuilder = feignBuilder; + return this; + } + + private ObjectMapper createObjectMapper() { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + objectMapper.disable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE); + objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + objectMapper.setDateFormat(new RFC3339DateFormat()); + {{#joda}} + objectMapper.registerModule(new JodaModule()); + {{/joda}} + {{#java8}} + objectMapper.registerModule(new JavaTimeModule()); + {{/java8}} + {{#threetenbp}} + ThreeTenModule module = new ThreeTenModule(); + module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); + module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); + module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); + objectMapper.registerModule(module); + {{/threetenbp}} + return objectMapper; + } + + public ObjectMapper getObjectMapper(){ + return objectMapper; + } + + /** + * Creates a feign client for given API interface. + * + * Usage: + * ApiClient apiClient = new ApiClient(); + * apiClient.setBasePath("http://localhost:8080"); + * XYZApi api = apiClient.buildClient(XYZApi.class); + * XYZResponse response = api.someMethod(...); + * @param Type + * @param clientClass Client class + * @return The Client + */ + public T buildClient(Class clientClass) { + return feignBuilder.target(clientClass, basePath); + } + + /** + * Select the Accept header's value from the given accepts array: + * if JSON exists in the given array, use it; + * otherwise use all of them (joining into a string) + * + * @param accepts The accepts array to select from + * @return The Accept header to use. If the given array is empty, + * null will be returned (not to set the Accept header explicitly). + */ + public String selectHeaderAccept(String[] accepts) { + if (accepts.length == 0) return null; + if (StringUtil.containsIgnoreCase(accepts, "application/json")) return "application/json"; + return StringUtil.join(accepts, ","); + } + + /** + * Select the Content-Type header's value from the given array: + * if JSON exists in the given array, use it; + * otherwise use the first one of the array. + * + * @param contentTypes The Content-Type array to select from + * @return The Content-Type header to use. If the given array is empty, + * JSON will be used. + */ + public String selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0) return "application/json"; + if (StringUtil.containsIgnoreCase(contentTypes, "application/json")) return "application/json"; + return contentTypes[0]; + } + + /** + * Helper method to configure the first api key found + * @param apiKey API key + */ + public void setApiKey(String apiKey) { + for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof ApiKeyAuth) { + ApiKeyAuth keyAuth = (ApiKeyAuth) apiAuthorization; + keyAuth.setApiKey(apiKey); + return ; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to configure the username/password for basic auth or password OAuth + * @param username Username + * @param password Password + */ + public void setCredentials(String username, String password) { + for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof HttpBasicAuth) { + HttpBasicAuth basicAuth = (HttpBasicAuth) apiAuthorization; + basicAuth.setCredentials(username, password); + return; + } + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.getTokenRequestBuilder().setUsername(username).setPassword(password); + return; + } + } + throw new RuntimeException("No Basic authentication or OAuth configured!"); + } + + /** + * Helper method to configure the token endpoint of the first oauth found in the apiAuthorizations (there should be only one) + * @return Token request builder + */ + public TokenRequestBuilder getTokenEndPoint() { + for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + return oauth.getTokenRequestBuilder(); + } + } + return null; + } + + /** + * Helper method to configure authorization endpoint of the first oauth found in the apiAuthorizations (there should be only one) + * @return Authentication request builder + */ + public AuthenticationRequestBuilder getAuthorizationEndPoint() { + for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + return oauth.getAuthenticationRequestBuilder(); + } + } + return null; + } + + /** + * Helper method to pre-set the oauth access token of the first oauth found in the apiAuthorizations (there should be only one) + * @param accessToken Access Token + * @param expiresIn Validity period in seconds + */ + public void setAccessToken(String accessToken, Long expiresIn) { + for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.setAccessToken(accessToken, expiresIn); + return; + } + } + } + + /** + * Helper method to configure the oauth accessCode/implicit flow parameters + * @param clientId Client ID + * @param clientSecret Client secret + * @param redirectURI Redirect URI + */ + public void configureAuthorizationFlow(String clientId, String clientSecret, String redirectURI) { + for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.getTokenRequestBuilder() + .setClientId(clientId) + .setClientSecret(clientSecret) + .setRedirectURI(redirectURI); + oauth.getAuthenticationRequestBuilder() + .setClientId(clientId) + .setRedirectURI(redirectURI); + return; + } + } + } + + /** + * Configures a listener which is notified when a new access token is received. + * @param accessTokenListener Acesss token listener + */ + public void registerAccessTokenListener(AccessTokenListener accessTokenListener) { + for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.registerAccessTokenListener(accessTokenListener); + return; + } + } + } + + /** + * Gets request interceptor based on authentication name + * @param authName Authentiation name + * @return Request Interceptor + */ + public RequestInterceptor getAuthorization(String authName) { + return apiAuthorizations.get(authName); + } + + /** + * Adds an authorization to be used by the client + * @param authName Authentication name + * @param authorization Request interceptor + */ + public void addAuthorization(String authName, RequestInterceptor authorization) { + if (apiAuthorizations.containsKey(authName)) { + throw new RuntimeException("auth name \"" + authName + "\" already in api authorizations"); + } + apiAuthorizations.put(authName, authorization); + feignBuilder.requestInterceptor(authorization); + } + +} diff --git a/libraries/feign/EncodingUtils.mustache b/libraries/feign/EncodingUtils.mustache new file mode 100644 index 00000000000..6f43e1c3c2a --- /dev/null +++ b/libraries/feign/EncodingUtils.mustache @@ -0,0 +1,86 @@ +package {{invokerPackage}}; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** +* Utilities to support Swagger encoding formats in Feign. +*/ +public final class EncodingUtils { + + /** + * Private constructor. Do not construct this class. + */ + private EncodingUtils() {} + + /** + *

Encodes a collection of query parameters according to the Swagger + * collection format.

+ * + *

Of the various collection formats defined by Swagger ("csv", "tsv", + * etc), Feign only natively supports "multi". This utility generates the + * other format types so it will be properly processed by Feign.

+ * + *

Note, as part of reformatting, it URL encodes the parameters as + * well.

+ * @param parameters The collection object to be formatted. This object will + * not be changed. + * @param collectionFormat The Swagger collection format (eg, "csv", "tsv", + * "pipes"). See the + *
+ * Swagger Spec for more details. + * @return An object that will be correctly formatted by Feign. + */ + public static Object encodeCollection(Collection parameters, + String collectionFormat) { + if (parameters == null) { + return parameters; + } + List stringValues = new ArrayList<>(parameters.size()); + for (Object parameter : parameters) { + // ignore null values (same behavior as Feign) + if (parameter != null) { + stringValues.add(encode(parameter)); + } + } + // Feign natively handles single-element lists and the "multi" format. + if (stringValues.size() < 2 || "multi".equals(collectionFormat)) { + return stringValues; + } + // Otherwise return a formatted String + String[] stringArray = stringValues.toArray(new String[0]); + switch (collectionFormat) { + case "csv": + default: + return StringUtil.join(stringArray, ","); + case "ssv": + return StringUtil.join(stringArray, " "); + case "tsv": + return StringUtil.join(stringArray, "\t"); + case "pipes": + return StringUtil.join(stringArray, "|"); + } + } + + /** + * URL encode a single query parameter. + * @param parameter The query parameter to encode. This object will not be + * changed. + * @return The URL encoded string representation of the parameter. If the + * parameter is null, returns null. + */ + public static String encode(Object parameter) { + if (parameter == null) { + return null; + } + try { + return URLEncoder.encode(parameter.toString(), "UTF-8"); + } catch (UnsupportedEncodingException e) { + // Should never happen, UTF-8 is always supported + throw new RuntimeException(e); + } + } +} diff --git a/libraries/feign/ParamExpander.mustache b/libraries/feign/ParamExpander.mustache new file mode 100644 index 00000000000..2f5095d00f0 --- /dev/null +++ b/libraries/feign/ParamExpander.mustache @@ -0,0 +1,22 @@ +package {{invokerPackage}}; + +import feign.Param; + +import java.text.DateFormat; +import java.util.Date; + +/** + * Param Expander to convert {@link Date} to RFC3339 + */ +public class ParamExpander implements Param.Expander { + + private static final DateFormat dateformat = new RFC3339DateFormat(); + + @Override + public String expand(Object value) { + if (value instanceof Date) { + return dateformat.format(value); + } + return value.toString(); + } +} diff --git a/libraries/feign/README.mustache b/libraries/feign/README.mustache new file mode 100644 index 00000000000..56560172ee3 --- /dev/null +++ b/libraries/feign/README.mustache @@ -0,0 +1,43 @@ +# {{artifactId}} + +## Requirements + +Building the API client library requires [Maven](https://maven.apache.org/) to be installed. + +## Installation & Usage + +To install the API client library to your local Maven repository, simply execute: + +```shell +mvn install +``` + +To deploy it to a remote Maven repository instead, configure the settings of the repository and execute: + +```shell +mvn deploy +``` + +Refer to the [official documentation](https://maven.apache.org/plugins/maven-deploy-plugin/usage.html) for more information. + +After the client library is installed/deployed, you can use it in your Maven project by adding the following to your *pom.xml*: + +```xml + + {{groupId}} + {{artifactId}} + {{artifactVersion}} + compile + + +``` + +## Recommendation + +It's recommended to create an instance of `ApiClient` per thread in a multithreaded environment to avoid any potential issues. + +## Author + +{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} +{{/hasMore}}{{/apis}}{{/apiInfo}} + diff --git a/libraries/feign/api.mustache b/libraries/feign/api.mustache new file mode 100644 index 00000000000..03eb7dd40cb --- /dev/null +++ b/libraries/feign/api.mustache @@ -0,0 +1,105 @@ +package {{package}}; + +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.EncodingUtils; +{{#legacyDates}} +import {{invokerPackage}}.ParamExpander; +{{/legacyDates}} + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} +import feign.*; + +{{>generatedAnnotation}} +public interface {{classname}} extends ApiClient.Api { + +{{#operations}}{{#operation}} + /** + * {{summary}} + * {{notes}} +{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} +{{/allParams}} +{{#returnType}} + * @return {{returnType}} +{{/returnType}} +{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation +{{/externalDocs}} + */ + @RequestLine("{{httpMethod}} {{{path}}}{{#hasQueryParams}}?{{/hasQueryParams}}{{#queryParams}}{{baseName}}={{=<% %>=}}{<%paramName%>}<%={{ }}=%>{{#hasMore}}&{{/hasMore}}{{/queryParams}}") + @Headers({ +{{#vendorExtensions.x-contentType}} "Content-Type: {{vendorExtensions.x-contentType}}", +{{/vendorExtensions.x-contentType}} "Accept: {{vendorExtensions.x-accepts}}",{{#headerParams}} + "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{#hasMore}}, + {{/hasMore}}{{/headerParams}} + }) + {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{paramName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{#hasQueryParams}} + + /** + * {{summary}} + * {{notes}} + * Note, this is equivalent to the other {{operationId}} method, + * but with the query parameters collected into a single Map parameter. This + * is convenient for services with optional query parameters, especially when + * used with the {@link {{operationIdCamelCase}}QueryParams} class that allows for + * building up this map in a fluent style. + {{#allParams}} + {{^isQueryParam}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/isQueryParam}} + {{/allParams}} + * @param queryParams Map of query parameters as name-value pairs + *

The following elements may be specified in the query map:

+ *
    + {{#queryParams}} + *
  • {{paramName}} - {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}
  • + {{/queryParams}} + *
+ {{#returnType}} + * @return {{returnType}} + {{/returnType}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + @RequestLine("{{httpMethod}} {{{path}}}?{{#queryParams}}{{baseName}}={{=<% %>=}}{<%paramName%>}<%={{ }}=%>{{#hasMore}}&{{/hasMore}}{{/queryParams}}") + @Headers({ +{{#vendorExtensions.x-contentType}} "Content-Type: {{vendorExtensions.x-contentType}}", +{{/vendorExtensions.x-contentType}} "Accept: {{vendorExtensions.x-accepts}}",{{#headerParams}} + "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{#hasMore}}, + {{/hasMore}}{{/headerParams}} + }) + {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isQueryParam}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{paramName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}, {{/isQueryParam}}{{/allParams}}@QueryMap(encoded=true) Map queryParams); + + /** + * A convenience class for generating query parameters for the + * {{operationId}} method in a fluent style. + */ + public static class {{operationIdCamelCase}}QueryParams extends HashMap { + {{#queryParams}} + public {{operationIdCamelCase}}QueryParams {{paramName}}(final {{{dataType}}} value) { + {{#collectionFormat}} + put("{{baseName}}", EncodingUtils.encodeCollection(value, "{{collectionFormat}}")); + {{/collectionFormat}} + {{^collectionFormat}} + put("{{baseName}}", EncodingUtils.encode(value)); + {{/collectionFormat}} + return this; + } + {{/queryParams}} + } + {{/hasQueryParams}} + {{/operation}} +{{/operations}} +} diff --git a/libraries/feign/api_test.mustache b/libraries/feign/api_test.mustache new file mode 100644 index 00000000000..bcc14a987c6 --- /dev/null +++ b/libraries/feign/api_test.mustache @@ -0,0 +1,70 @@ +package {{package}}; + +import {{invokerPackage}}.ApiClient; +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Before; +import org.junit.Test; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +public class {{classname}}Test { + + private {{classname}} api; + + @Before + public void setup() { + api = new ApiClient().buildClient({{classname}}.class); + } + + {{#operations}}{{#operation}} + /** + * {{summary}} + * + * {{notes}} + */ + @Test + public void {{operationId}}Test() { + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + // {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + + // TODO: test validations + } + + {{#hasQueryParams}} + /** + * {{summary}} + * + * {{notes}} + * + * This tests the overload of the method that uses a Map for query parameters instead of + * listing them out individually. + */ + @Test + public void {{operationId}}TestQueryMap() { + {{#allParams}} + {{^isQueryParam}} + {{{dataType}}} {{paramName}} = null; + {{/isQueryParam}} + {{/allParams}} + {{classname}}.{{operationIdCamelCase}}QueryParams queryParams = new {{classname}}.{{operationIdCamelCase}}QueryParams() + {{#queryParams}} + .{{paramName}}(null){{^hasMore}};{{/hasMore}} + {{/queryParams}} + // {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{^isQueryParam}}{{paramName}}, {{/isQueryParam}}{{/allParams}}queryParams); + + // TODO: test validations + } + {{/hasQueryParams}} + {{/operation}}{{/operations}} +} diff --git a/libraries/feign/auth/ApiKeyAuth.mustache b/libraries/feign/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..9982cd7fc49 --- /dev/null +++ b/libraries/feign/auth/ApiKeyAuth.mustache @@ -0,0 +1,41 @@ +package {{invokerPackage}}.auth; + +import feign.RequestInterceptor; +import feign.RequestTemplate; + +public class ApiKeyAuth implements RequestInterceptor { + private final String location; + private final String paramName; + + private String apiKey; + + public ApiKeyAuth(String location, String paramName) { + this.location = location; + this.paramName = paramName; + } + + public String getLocation() { + return location; + } + + public String getParamName() { + return paramName; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + @Override + public void apply(RequestTemplate template) { + if ("query".equals(location)) { + template.query(paramName, apiKey); + } else if ("header".equals(location)) { + template.header(paramName, apiKey); + } + } +} diff --git a/libraries/feign/auth/HttpBasicAuth.mustache b/libraries/feign/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..2b1acb8ff74 --- /dev/null +++ b/libraries/feign/auth/HttpBasicAuth.mustache @@ -0,0 +1,41 @@ +package {{invokerPackage}}.auth; + +import feign.RequestInterceptor; +import feign.RequestTemplate; +import feign.auth.BasicAuthRequestInterceptor; + +/** + * An interceptor that adds the request header needed to use HTTP basic authentication. + */ +public class HttpBasicAuth implements RequestInterceptor { + + private String username; + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public void setCredentials(String username, String password) { + this.username = username; + this.password = password; + } + + @Override + public void apply(RequestTemplate template) { + RequestInterceptor requestInterceptor = new BasicAuthRequestInterceptor(username, password); + requestInterceptor.apply(template); + } +} diff --git a/libraries/feign/auth/OAuth.mustache b/libraries/feign/auth/OAuth.mustache new file mode 100644 index 00000000000..1df88d403a2 --- /dev/null +++ b/libraries/feign/auth/OAuth.mustache @@ -0,0 +1,197 @@ +package {{invokerPackage}}.auth; + +import java.io.IOException; +import java.util.Collection; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.oltu.oauth2.client.HttpClient; +import org.apache.oltu.oauth2.client.OAuthClient; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; +import org.apache.oltu.oauth2.client.response.OAuthClientResponse; +import org.apache.oltu.oauth2.client.response.OAuthClientResponseFactory; +import org.apache.oltu.oauth2.client.response.OAuthJSONAccessTokenResponse; +import org.apache.oltu.oauth2.common.exception.OAuthProblemException; +import org.apache.oltu.oauth2.common.exception.OAuthSystemException; +import org.apache.oltu.oauth2.common.message.types.GrantType; +import org.apache.oltu.oauth2.common.token.BasicOAuthToken; + +import feign.Client; +import feign.Request.Options; +import feign.RequestInterceptor; +import feign.RequestTemplate; +import feign.Response; +import feign.RetryableException; +import feign.Util; +import {{invokerPackage}}.StringUtil; + + +public class OAuth implements RequestInterceptor { + + static final int MILLIS_PER_SECOND = 1000; + + public interface AccessTokenListener { + void notify(BasicOAuthToken token); + } + + private volatile String accessToken; + private Long expirationTimeMillis; + private OAuthClient oauthClient; + private TokenRequestBuilder tokenRequestBuilder; + private AuthenticationRequestBuilder authenticationRequestBuilder; + private AccessTokenListener accessTokenListener; + + public OAuth(Client client, TokenRequestBuilder requestBuilder) { + this.oauthClient = new OAuthClient(new OAuthFeignClient(client)); + this.tokenRequestBuilder = requestBuilder; + } + + public OAuth(Client client, OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { + this(client, OAuthClientRequest.tokenLocation(tokenUrl).setScope(scopes)); + + switch(flow) { + case accessCode: + case implicit: + tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE); + break; + case password: + tokenRequestBuilder.setGrantType(GrantType.PASSWORD); + break; + case application: + tokenRequestBuilder.setGrantType(GrantType.CLIENT_CREDENTIALS); + break; + default: + break; + } + authenticationRequestBuilder = OAuthClientRequest.authorizationLocation(authorizationUrl); + } + + public OAuth(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { + this(new Client.Default(null, null), flow, authorizationUrl, tokenUrl, scopes); + } + + @Override + public void apply(RequestTemplate template) { + // If the request already have an authorization (eg. Basic auth), do nothing + if (template.headers().containsKey("Authorization")) { + return; + } + // If first time, get the token + if (expirationTimeMillis == null || System.currentTimeMillis() >= expirationTimeMillis) { + updateAccessToken(); + } + if (getAccessToken() != null) { + template.header("Authorization", "Bearer " + getAccessToken()); + } + } + + public synchronized void updateAccessToken() { + OAuthJSONAccessTokenResponse accessTokenResponse; + try { + accessTokenResponse = oauthClient.accessToken(tokenRequestBuilder.buildBodyMessage()); + } catch (Exception e) { + throw new RetryableException(e.getMessage(), e,null); + } + if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { + setAccessToken(accessTokenResponse.getAccessToken(), accessTokenResponse.getExpiresIn()); + if (accessTokenListener != null) { + accessTokenListener.notify((BasicOAuthToken) accessTokenResponse.getOAuthToken()); + } + } + } + + public synchronized void registerAccessTokenListener(AccessTokenListener accessTokenListener) { + this.accessTokenListener = accessTokenListener; + } + + public synchronized String getAccessToken() { + return accessToken; + } + + public synchronized void setAccessToken(String accessToken, Long expiresIn) { + this.accessToken = accessToken; + this.expirationTimeMillis = System.currentTimeMillis() + expiresIn * MILLIS_PER_SECOND; + } + + public TokenRequestBuilder getTokenRequestBuilder() { + return tokenRequestBuilder; + } + + public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) { + this.tokenRequestBuilder = tokenRequestBuilder; + } + + public AuthenticationRequestBuilder getAuthenticationRequestBuilder() { + return authenticationRequestBuilder; + } + + public void setAuthenticationRequestBuilder(AuthenticationRequestBuilder authenticationRequestBuilder) { + this.authenticationRequestBuilder = authenticationRequestBuilder; + } + + public OAuthClient getOauthClient() { + return oauthClient; + } + + public void setOauthClient(OAuthClient oauthClient) { + this.oauthClient = oauthClient; + } + + public void setOauthClient(Client client) { + this.oauthClient = new OAuthClient( new OAuthFeignClient(client)); + } + + public static class OAuthFeignClient implements HttpClient { + + private Client client; + + public OAuthFeignClient() { + this.client = new Client.Default(null, null); + } + + public OAuthFeignClient(Client client) { + this.client = client; + } + + public T execute(OAuthClientRequest request, Map headers, + String requestMethod, Class responseClass) + throws OAuthSystemException, OAuthProblemException { + + RequestTemplate req = new RequestTemplate() + .append(request.getLocationUri()) + .method(requestMethod) + .body(request.getBody()); + + for (Entry entry : headers.entrySet()) { + req.header(entry.getKey(), entry.getValue()); + } + Response feignResponse; + String body = ""; + try { + feignResponse = client.execute(req.request(), new Options()); + body = Util.toString(feignResponse.body().asReader()); + } catch (IOException e) { + throw new OAuthSystemException(e); + } + + String contentType = null; + Collection contentTypeHeader = feignResponse.headers().get("Content-Type"); + if(contentTypeHeader != null) { + contentType = StringUtil.join(contentTypeHeader.toArray(new String[0]), ";"); + } + + return OAuthClientResponseFactory.createCustomResponse( + body, + contentType, + feignResponse.status(), + responseClass + ); + } + + public void shutdown() { + // Nothing to do here + } + } +} diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache new file mode 100644 index 00000000000..0074c0e38a2 --- /dev/null +++ b/libraries/feign/build.gradle.mustache @@ -0,0 +1,135 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + } + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + sourceCompatibility = JavaVersion.VERSION_{{^java8}}1_7{{/java8}}{{#java8}}1_8{{/java8}} + targetCompatibility = JavaVersion.VERSION_{{^java8}}1_7{{/java8}}{{#java8}}1_8{{/java8}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + swagger_annotations_version = "1.5.9" + jackson_version = "2.8.7" + {{#threetenbp}} + threepane_version = "2.6.4" + {{/threetenbp}} + feign_version = "9.4.0" + feign_form_version = "2.1.0" + junit_version = "4.12" + oltu_version = "1.0.1" +} + +dependencies { + compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "io.github.openfeign:feign-core:$feign_version" + compile "io.github.openfeign:feign-jackson:$feign_version" + compile "io.github.openfeign:feign-slf4j:$feign_version" + compile "io.github.openfeign.form:feign-form:$feign_form_version" + compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + {{#joda}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + {{/joda}} + {{#java8}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{/java8}} + {{#threetenbp}} + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$threepane_version" + {{/threetenbp}} + compile "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version" + compile "com.brsanthu:migbase64:2.2" + testCompile "junit:junit:$junit_version" +} diff --git a/libraries/feign/build.sbt.mustache b/libraries/feign/build.sbt.mustache new file mode 100644 index 00000000000..d745ef7e86d --- /dev/null +++ b/libraries/feign/build.sbt.mustache @@ -0,0 +1,26 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "io.swagger" % "swagger-annotations" % "1.5.9" % "compile", + "io.github.openfeign" % "feign-core" % "9.4.0" % "compile", + "io.github.openfeign" % "feign-jackson" % "9.4.0" % "compile", + "io.github.openfeign" % "feign-slf4j" % "9.4.0" % "compile", + "io.github.openfeign.form" % "feign-form" % "2.1.0" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.8.7" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.7" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.7" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}" % "2.8.7" % "compile", + "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", + "com.brsanthu" % "migbase64" % "2.2" % "compile", + "junit" % "junit" % "4.12" % "test", + "com.novocode" % "junit-interface" % "0.10" % "test" + ) + ) diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache new file mode 100644 index 00000000000..ad255c13ea4 --- /dev/null +++ b/libraries/feign/pom.mustache @@ -0,0 +1,308 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{artifactUrl}} + {{artifactDescription}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-core-version} + + + + + io.github.openfeign + feign-core + ${feign-version} + + + io.github.openfeign + feign-jackson + ${feign-version} + + + io.github.openfeign + feign-slf4j + ${feign-version} + + + io.github.openfeign.form + feign-form + ${feign-form-version} + + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-version} + + {{#withXml}} + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson-version} + + + {{/withXml}} + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + {{/joda}} + {{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{/java8}} + {{#threetenbp}} + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${jackson-threetenbp-version} + + {{/threetenbp}} + + org.apache.oltu.oauth2 + org.apache.oltu.oauth2.client + ${oltu-version} + + + + + junit + junit + ${junit-version} + test + + + com.squareup.okhttp3 + mockwebserver + 3.6.0 + test + + + org.assertj + assertj-core + 1.7.1 + test + + + + UTF-8 + {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}} + ${java.version} + ${java.version} + 1.5.18 + 9.4.0 + 2.1.0 + 2.8.9 + {{#threetenbp}} + 2.6.4 + {{/threetenbp}} + 4.12 + 1.0.0 + 1.0.1 + + diff --git a/libraries/google-api-client/ApiClient.mustache b/libraries/google-api-client/ApiClient.mustache new file mode 100644 index 00000000000..fa6e7a601fe --- /dev/null +++ b/libraries/google-api-client/ApiClient.mustache @@ -0,0 +1,109 @@ +package {{invokerPackage}}; + +import {{apiPackage}}.*; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +{{#joda}} +import com.fasterxml.jackson.datatype.joda.JodaModule; +{{/joda}} +{{#java8}} +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{/java8}} +{{#threetenbp}} +import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; +{{/threetenbp}} +{{#threetenbp}} +import org.threeten.bp.*; +{{/threetenbp}} +import com.google.api.client.googleapis.util.Utils; +import com.google.api.client.http.AbstractHttpContent; +import com.google.api.client.http.HttpRequestFactory; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.HttpTransport; +import com.google.api.client.json.Json; + +import java.io.IOException; +import java.io.OutputStream; + +{{>generatedAnnotation}} +public class ApiClient { + private final String basePath; + private final HttpRequestFactory httpRequestFactory; + private final ObjectMapper objectMapper; + + private static final String defaultBasePath = "{{basePath}}"; + + // A reasonable default object mapper. Client can pass in a chosen ObjectMapper anyway, this is just for reasonable defaults. + private static ObjectMapper createDefaultObjectMapper() { + ObjectMapper objectMapper = new ObjectMapper() + .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) + .setDateFormat(new RFC3339DateFormat()); + {{#joda}} + objectMapper.registerModule(new JodaModule()); + {{/joda}} + {{#java8}} + objectMapper.registerModule(new JavaTimeModule()); + {{/java8}} + {{#threetenbp}} + ThreeTenModule module = new ThreeTenModule(); + module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); + module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); + module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); + objectMapper.registerModule(module); + {{/threetenbp}} + return objectMapper; + } + + public ApiClient() { + this(null, null, null, null); + } + + public ApiClient( + String basePath, + HttpTransport httpTransport, + HttpRequestInitializer initializer, + ObjectMapper objectMapper + ) { + this.basePath = basePath == null ? defaultBasePath : ( + basePath.endsWith("/") ? basePath.substring(0, basePath.length() - 1) : basePath + ); + this.httpRequestFactory = (httpTransport == null ? Utils.getDefaultTransport() : httpTransport).createRequestFactory(initializer); + this.objectMapper = (objectMapper == null ? createDefaultObjectMapper() : objectMapper); + } + + public HttpRequestFactory getHttpRequestFactory() { + return httpRequestFactory; + } + + public String getBasePath() { + return basePath; + } + + public ObjectMapper getObjectMapper() { + return objectMapper; + } + + public class JacksonJsonHttpContent extends AbstractHttpContent { + /* A POJO that can be serialized with a com.fasterxml Jackson ObjectMapper */ + private final Object data; + + public JacksonJsonHttpContent(Object data) { + super(Json.MEDIA_TYPE); + this.data = data; + } + + @Override + public void writeTo(OutputStream out) throws IOException { + objectMapper.writeValue(out, data); + } + } + + // Builder pattern to get API instances for this client. + {{#apiInfo}}{{#apis}} + public {{classname}} {{classVarName}}Api() { + return new {{classname}}(this); + } + {{/apis}}{{/apiInfo}} +} diff --git a/libraries/google-api-client/api.mustache b/libraries/google-api-client/api.mustache new file mode 100644 index 00000000000..46ecf3af355 --- /dev/null +++ b/libraries/google-api-client/api.mustache @@ -0,0 +1,189 @@ +package {{package}}; + +import {{invokerPackage}}.ApiClient; + +{{#imports}}import {{import}}; +{{/imports}} + +import com.fasterxml.jackson.core.type.TypeReference; +import com.google.api.client.http.GenericUrl; +import com.google.api.client.http.HttpContent; +import com.google.api.client.http.InputStreamContent; +import com.google.api.client.http.HttpMethods; +import com.google.api.client.http.HttpResponse; +import com.google.api.client.json.Json; + +import javax.ws.rs.core.UriBuilder; +import java.io.IOException; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.List; +import java.util.ArrayList; + +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}} { + private ApiClient {{localVariablePrefix}}apiClient; + + public {{classname}}() { + this(new ApiClient()); + } + + public {{classname}}(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + public ApiClient getApiClient() { + return {{localVariablePrefix}}apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + {{#operation}} + /**{{#summary}} + * {{summary}}{{/summary}}{{#notes}} + * {{notes}}{{/notes}}{{#responses}} + *

{{code}}{{#message}} - {{message}}{{/message}}{{/responses}}{{#allParams}} + * @param {{paramName}} {{description}}{{^description}}The {{paramName}} parameter{{/description}}{{/allParams}}{{#returnType}} + * @return {{returnType}}{{/returnType}} + * @throws IOException if an error occurs while attempting to invoke the API{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + + **/ + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws IOException { + {{#returnType}}HttpResponse response = {{/returnType}}{{operationId}}ForHttpResponse({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + TypeReference typeRef = new TypeReference<{{{returnType}}}>() {}; + return apiClient.getObjectMapper().readValue(response.getContent(), typeRef);{{/returnType}} + } + + /**{{#summary}} + * {{summary}}{{/summary}}{{#notes}} + * {{notes}}{{/notes}}{{#responses}} + *

{{code}}{{#message}} - {{message}}{{/message}}{{/responses}}{{#requiredParams}} + * @param {{paramName}} {{description}}{{^description}}The {{paramName}} parameter{{/description}}{{/requiredParams}} + * @param params Map of query params. A collection will be interpreted as passing in multiple instances of the same query param.{{#returnType}} + * @return {{returnType}}{{/returnType}} + * @throws IOException if an error occurs while attempting to invoke the API{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + + **/ + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#bodyParam}}{{^required}}{{{dataType}}} {{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}Map params) throws IOException { + {{#returnType}}HttpResponse response = {{/returnType}}{{operationId}}ForHttpResponse({{#bodyParam}}{{^required}}{{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}params);{{#returnType}} + TypeReference typeRef = new TypeReference<{{{returnType}}}>() {}; + return apiClient.getObjectMapper().readValue(response.getContent(), typeRef);{{/returnType}} + } + + public HttpResponse {{operationId}}ForHttpResponse({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws IOException { + {{#allParams}}{{#required}}// verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new IllegalArgumentException("Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + }{{/required}}{{/allParams}} + {{#hasPathParams}} + // create a map of path variables + final Map uriVariables = new HashMap();{{#pathParams}} + uriVariables.put("{{baseName}}", {{{paramName}}});{{/pathParams}} + {{/hasPathParams}} + UriBuilder uriBuilder = UriBuilder.fromUri(apiClient.getBasePath() + "{{{path}}}");{{#hasQueryParams}} + {{#queryParams}} + if ({{paramName}} != null) { + String key = "{{baseName}}"; + Object value = {{paramName}}; + if (value instanceof Collection) { + uriBuilder = uriBuilder.queryParam(key, ((Collection) value).toArray()); + } else if (value instanceof Object[]) { + uriBuilder = uriBuilder.queryParam(key, (Object[]) value); + } else { + uriBuilder = uriBuilder.queryParam(key, value); + } + }{{/queryParams}}{{/hasQueryParams}} + + String url = uriBuilder{{#hasPathParams}}.buildFromMap(uriVariables).toString();{{/hasPathParams}}{{^hasPathParams}}.build().toString();{{/hasPathParams}} + GenericUrl genericUrl = new GenericUrl(url); + + HttpContent content = {{#isBodyAllowed}}apiClient.new JacksonJsonHttpContent({{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}){{/isBodyAllowed}}{{^isBodyAllowed}}null{{/isBodyAllowed}}; + return apiClient.getHttpRequestFactory().buildRequest(HttpMethods.{{httpMethod}}, genericUrl, content).execute(); + }{{#bodyParam}} + + public HttpResponse {{operationId}}ForHttpResponse({{#allParams}}{{#isBodyParam}}java.io.InputStream {{paramName}}{{/isBodyParam}}{{^isBodyParam}}{{{dataType}}} {{paramName}}{{/isBodyParam}}{{#hasMore}}, {{/hasMore}}{{/allParams}}, String mediaType) throws IOException { + {{#allParams}}{{#required}}// verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new IllegalArgumentException("Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + }{{/required}}{{/allParams}} + {{#hasPathParams}} + // create a map of path variables + final Map uriVariables = new HashMap();{{#pathParams}} + uriVariables.put("{{baseName}}", {{{paramName}}});{{/pathParams}} + {{/hasPathParams}} + UriBuilder uriBuilder = UriBuilder.fromUri(apiClient.getBasePath() + "{{{path}}}");{{#hasQueryParams}} + {{#queryParams}} + if ({{paramName}} != null) { + String key = "{{baseName}}"; + Object value = {{paramName}}; + if (value instanceof Collection) { + uriBuilder = uriBuilder.queryParam(key, ((Collection) value).toArray()); + } else if (value instanceof Object[]) { + uriBuilder = uriBuilder.queryParam(key, (Object[]) value); + } else { + uriBuilder = uriBuilder.queryParam(key, value); + } + }{{/queryParams}}{{/hasQueryParams}} + + String url = uriBuilder{{#hasPathParams}}.buildFromMap(uriVariables).toString();{{/hasPathParams}}{{^hasPathParams}}.build().toString();{{/hasPathParams}} + GenericUrl genericUrl = new GenericUrl(url); + + HttpContent content = {{#bodyParam}}{{paramName}} == null ? + apiClient.new JacksonJsonHttpContent(null) : + new InputStreamContent(mediaType == null ? Json.MEDIA_TYPE : mediaType, {{paramName}}){{/bodyParam}}; + return apiClient.getHttpRequestFactory().buildRequest(HttpMethods.{{httpMethod}}, genericUrl, content).execute(); + }{{/bodyParam}} + + public HttpResponse {{operationId}}ForHttpResponse({{#bodyParam}}{{^required}}{{{dataType}}} {{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}Map params) throws IOException { + {{#allParams}}{{#required}}// verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new IllegalArgumentException("Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + }{{/required}}{{/allParams}} + {{#hasPathParams}} + // create a map of path variables + final Map uriVariables = new HashMap();{{#pathParams}} + uriVariables.put("{{baseName}}", {{{paramName}}});{{/pathParams}} + {{/hasPathParams}} + UriBuilder uriBuilder = UriBuilder.fromUri(apiClient.getBasePath() + "{{{path}}}"); + + // Copy the params argument if present, to allow passing in immutable maps + Map allParams = params == null ? new HashMap() : new HashMap(params);{{#queryParams}}{{#required}} + // Add the required query param '{{paramName}}' to the map of query params + allParams.put("{{paramName}}", {{paramName}});{{/required}}{{/queryParams}} + + for (Map.Entry entry: allParams.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + + if (key != null && value != null) { + if (value instanceof Collection) { + uriBuilder = uriBuilder.queryParam(key, ((Collection) value).toArray()); + } else if (value instanceof Object[]) { + uriBuilder = uriBuilder.queryParam(key, (Object[]) value); + } else { + uriBuilder = uriBuilder.queryParam(key, value); + } + } + } + + String url = uriBuilder{{#hasPathParams}}.buildFromMap(uriVariables).toString();{{/hasPathParams}}{{^hasPathParams}}.build().toString();{{/hasPathParams}} + GenericUrl genericUrl = new GenericUrl(url); + + HttpContent content = {{#isBodyAllowed}}apiClient.new JacksonJsonHttpContent({{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}){{/isBodyAllowed}}{{^isBodyAllowed}}null{{/isBodyAllowed}}; + return apiClient.getHttpRequestFactory().buildRequest(HttpMethods.{{httpMethod}}, genericUrl, content).execute(); + } + + + {{/operation}} +} +{{/operations}} diff --git a/libraries/google-api-client/api_test.mustache b/libraries/google-api-client/api_test.mustache new file mode 100644 index 00000000000..365106fbedf --- /dev/null +++ b/libraries/google-api-client/api_test.mustache @@ -0,0 +1,45 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Test; +import org.junit.Ignore; + +import java.io.IOException; +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +@Ignore +public class {{classname}}Test { + + private final {{classname}} api = new {{classname}}(); + + {{#operations}}{{#operation}} + /** + * {{summary}} + * + * {{notes}} + * + * @throws IOException + * if the Api call fails + */ + @Test + public void {{operationId}}Test() throws IOException { + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + + // TODO: test validations + } + {{/operation}}{{/operations}} +} diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache new file mode 100644 index 00000000000..e6197b08f7a --- /dev/null +++ b/libraries/google-api-client/build.gradle.mustache @@ -0,0 +1,142 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.5.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 23 + buildToolsVersion '23.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 22 + } + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + {{#java8}} + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + {{/java8}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + swagger_annotations_version = "1.5.17" + jackson_version = "2.8.9" + google_api_client_version = "1.23.0" + jersey_common_version = "2.25.1" + jodatime_version = "2.9.9" + junit_version = "4.12" + {{#threetenbp}} + jackson_threeten_version = "2.6.4" + {{/threetenbp}} +} + +dependencies { + compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "com.google.api-client:google-api-client:${google_api_client_version}" + compile "org.glassfish.jersey.core:jersey-common:${jersey_common_version}" + compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + {{#java8}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{/java8}} + {{#joda}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + compile "joda-time:joda-time:$jodatime_version" + {{/joda}} + {{#threetenbp}} + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threeten_version" + {{/threetenbp}} + {{#withXml}} + compile "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jackson_version" + {{/withXml}} + testCompile "junit:junit:$junit_version" +} diff --git a/libraries/google-api-client/build.sbt.mustache b/libraries/google-api-client/build.sbt.mustache new file mode 100644 index 00000000000..d6b88c91d96 --- /dev/null +++ b/libraries/google-api-client/build.sbt.mustache @@ -0,0 +1,33 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "io.swagger" % "swagger-annotations" % "1.5.17", + "com.google.api-client" % "google-api-client" % "1.23.0", + "org.glassfish.jersey.core" % "jersey-common" % "2.25.1", + "com.fasterxml.jackson.core" % "jackson-core" % "2.8.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.9" % "compile", + {{#withXml}} + "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.8.9" % "compile", + {{/withXml}} + {{#joda}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.8.9" % "compile", + {{/joda}} + {{#java8}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.8.9" % "compile", + {{/java8}} + {{#threetenbp}} + "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4" % "compile", + {{/threetenbp}} + "junit" % "junit" % "4.12" % "test", + "com.novocode" % "junit-interface" % "0.10" % "test" + ) + ) diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache new file mode 100644 index 00000000000..fb2d2bdfab7 --- /dev/null +++ b/libraries/google-api-client/pom.mustache @@ -0,0 +1,299 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{artifactUrl}} + {{artifactDescription}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + {{#java8}} + + 1.8 + 1.8 + {{/java8}} + {{^java8}} + + 1.7 + 1.7 + {{/java8}} + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-annotations-version} + + + + com.google.api-client + google-api-client + ${google-api-client-version} + + + + org.glassfish.jersey.core + jersey-common + ${jersey-common-version} + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-version} + + {{#withXml}} + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson-version} + + {{/withXml}} + {{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{/java8}} + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + + joda-time + joda-time + ${jodatime-version} + + {{/joda}} + {{#threetenbp}} + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${jackson-threetenbp-version} + + {{/threetenbp}} + + + + junit + junit + ${junit-version} + test + + + + UTF-8 + 1.5.17 + 1.23.0 + 2.25.1 + 2.8.9 + {{#joda}} + 2.9.9 + {{/joda}} + {{#threetenbp}} + 2.6.4 + {{/threetenbp}} + 1.0.0 + 4.12 + + diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache new file mode 100644 index 00000000000..a699e001f17 --- /dev/null +++ b/libraries/jersey2/ApiClient.mustache @@ -0,0 +1,799 @@ +package {{invokerPackage}}; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.Form; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.glassfish.jersey.client.ClientConfig; +import org.glassfish.jersey.client.ClientProperties; +import org.glassfish.jersey.client.HttpUrlConnectorProvider; +import org.glassfish.jersey.jackson.JacksonFeature; +import org.glassfish.jersey.media.multipart.FormDataBodyPart; +import org.glassfish.jersey.media.multipart.FormDataContentDisposition; +import org.glassfish.jersey.media.multipart.MultiPart; +import org.glassfish.jersey.media.multipart.MultiPartFeature; + +import java.io.IOException; +import java.io.InputStream; + +{{^supportJava6}} +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import org.glassfish.jersey.logging.LoggingFeature; +{{/supportJava6}} +{{#supportJava6}} +import org.apache.commons.io.FileUtils; +import org.glassfish.jersey.filter.LoggingFilter; +{{/supportJava6}} +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Map.Entry; +import java.util.HashMap; +import java.util.List; +import java.util.ArrayList; +import java.util.Date; +import java.util.TimeZone; + +import java.net.URLEncoder; + +import java.io.File; +import java.io.UnsupportedEncodingException; + +import java.text.DateFormat; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import {{invokerPackage}}.auth.Authentication; +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.OAuth; + +{{>generatedAnnotation}} +public class ApiClient { + protected Map defaultHeaderMap = new HashMap(); + protected String basePath = "{{{basePath}}}"; + protected boolean debugging = false; + protected int connectionTimeout = 0; + private int readTimeout = 0; + + protected Client httpClient; + protected JSON json; + protected String tempFolderPath = null; + + protected Map authentications; + + protected DateFormat dateFormat; + + public ApiClient() { + json = new JSON(); + httpClient = buildHttpClient(debugging); + + this.dateFormat = new RFC3339DateFormat(); + + // Set default User-Agent. + setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}Swagger-Codegen/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap();{{#authMethods}}{{#isBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + } + + /** + * Gets the JSON instance to do JSON serialization and deserialization. + * @return JSON + */ + public JSON getJSON() { + return json; + } + + public Client getHttpClient() { + return httpClient; + } + + public ApiClient setHttpClient(Client httpClient) { + this.httpClient = httpClient; + return this; + } + + public String getBasePath() { + return basePath; + } + + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Get authentications (key: authentication name, value: authentication). + * @return Map of authentication object + */ + public Map getAuthentications() { + return authentications; + } + + /** + * Get authentication for the given name. + * + * @param authName The authentication name + * @return The authentication, null if not found + */ + public Authentication getAuthentication(String authName) { + return authentications.get(authName); + } + + /** + * Helper method to set username for the first HTTP basic authentication. + * @param username Username + */ + public void setUsername(String username) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setUsername(username); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set password for the first HTTP basic authentication. + * @param password Password + */ + public void setPassword(String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setPassword(password); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set API key value for the first API key authentication. + * @param apiKey API key + */ + public void setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + * @param apiKeyPrefix API key prefix + */ + public void setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set access token for the first OAuth2 authentication. + * @param accessToken Access token + */ + public void setAccessToken(String accessToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setAccessToken(accessToken); + return; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Set the User-Agent header's value (by adding to the default header map). + * @param userAgent Http user agent + * @return API client + */ + public ApiClient setUserAgent(String userAgent) { + addDefaultHeader("User-Agent", userAgent); + return this; + } + + /** + * Add a default header. + * + * @param key The header's key + * @param value The header's value + * @return API client + */ + public ApiClient addDefaultHeader(String key, String value) { + defaultHeaderMap.put(key, value); + return this; + } + + /** + * Check that whether debugging is enabled for this API client. + * @return True if debugging is switched on + */ + public boolean isDebugging() { + return debugging; + } + + /** + * Enable/disable debugging for this API client. + * + * @param debugging To enable (true) or disable (false) debugging + * @return API client + */ + public ApiClient setDebugging(boolean debugging) { + this.debugging = debugging; + // Rebuild HTTP Client according to the new "debugging" value. + this.httpClient = buildHttpClient(debugging); + return this; + } + + /** + * The path of temporary folder used to store downloaded files from endpoints + * with file response. The default value is null, i.e. using + * the system's default tempopary folder. + * + * @return Temp folder path + */ + public String getTempFolderPath() { + return tempFolderPath; + } + + /** + * Set temp folder path + * @param tempFolderPath Temp folder path + * @return API client + */ + public ApiClient setTempFolderPath(String tempFolderPath) { + this.tempFolderPath = tempFolderPath; + return this; + } + + /** + * Connect timeout (in milliseconds). + * @return Connection timeout + */ + public int getConnectTimeout() { + return connectionTimeout; + } + + /** + * Set the connect timeout (in milliseconds). + * A value of 0 means no timeout, otherwise values must be between 1 and + * {@link Integer#MAX_VALUE}. + * @param connectionTimeout Connection timeout in milliseconds + * @return API client + */ + public ApiClient setConnectTimeout(int connectionTimeout) { + this.connectionTimeout = connectionTimeout; + httpClient.property(ClientProperties.CONNECT_TIMEOUT, connectionTimeout); + return this; + } + + /** + * read timeout (in milliseconds). + * @return Read timeout + */ + public int getReadTimeout() { + return readTimeout; + } + + /** + * Set the read timeout (in milliseconds). + * A value of 0 means no timeout, otherwise values must be between 1 and + * {@link Integer#MAX_VALUE}. + * @param readTimeout Read timeout in milliseconds + * @return API client + */ + public ApiClient setReadTimeout(int readTimeout) { + this.readTimeout = readTimeout; + httpClient.property(ClientProperties.READ_TIMEOUT, readTimeout); + return this; + } + + /** + * Get the date format used to parse/format date parameters. + * @return Date format + */ + public DateFormat getDateFormat() { + return dateFormat; + } + + /** + * Set the date format used to parse/format date parameters. + * @param dateFormat Date format + * @return API client + */ + public ApiClient setDateFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + // also set the date format for model (de)serialization with Date properties + this.json.setDateFormat((DateFormat) dateFormat.clone()); + return this; + } + + /** + * Parse the given string into Date object. + * @param str String + * @return Date + */ + public Date parseDate(String str) { + try { + return dateFormat.parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(e); + } + } + + /** + * Format the given Date object into string. + * @param date Date + * @return Date in string format + */ + public String formatDate(Date date) { + return dateFormat.format(date); + } + + /** + * Format the given parameter object into string. + * @param param Object + * @return Object in string format + */ + public String parameterToString(Object param) { + if (param == null) { + return ""; + } else if (param instanceof Date) { + return formatDate((Date) param); + } else if (param instanceof Collection) { + StringBuilder b = new StringBuilder(); + for(Object o : (Collection)param) { + if(b.length() > 0) { + b.append(','); + } + b.append(String.valueOf(o)); + } + return b.toString(); + } else { + return String.valueOf(param); + } + } + + /* + * Format to {@code Pair} objects. + * @param collectionFormat Collection format + * @param name Name + * @param value Value + * @return List of pairs + */ + public List parameterToPairs(String collectionFormat, String name, Object value){ + List params = new ArrayList(); + + // preconditions + if (name == null || name.isEmpty() || value == null) return params; + + Collection valueCollection; + if (value instanceof Collection) { + valueCollection = (Collection) value; + } else { + params.add(new Pair(name, parameterToString(value))); + return params; + } + + if (valueCollection.isEmpty()){ + return params; + } + + // get the collection format (default: csv) + String format = (collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat); + + // create the params based on the collection format + if ("multi".equals(format)) { + for (Object item : valueCollection) { + params.add(new Pair(name, parameterToString(item))); + } + + return params; + } + + String delimiter = ","; + + if ("csv".equals(format)) { + delimiter = ","; + } else if ("ssv".equals(format)) { + delimiter = " "; + } else if ("tsv".equals(format)) { + delimiter = "\t"; + } else if ("pipes".equals(format)) { + delimiter = "|"; + } + + StringBuilder sb = new StringBuilder() ; + for (Object item : valueCollection) { + sb.append(delimiter); + sb.append(parameterToString(item)); + } + + params.add(new Pair(name, sb.substring(1))); + + return params; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * application/vnd.company+json + * "* / *" is also default to JSON + * @param mime MIME + * @return True if the MIME type is JSON + */ + public boolean isJsonMime(String mime) { + String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$"; + return mime != null && (mime.matches(jsonMime) || mime.equals("*/*")); + } + + /** + * Select the Accept header's value from the given accepts array: + * if JSON exists in the given array, use it; + * otherwise use all of them (joining into a string) + * + * @param accepts The accepts array to select from + * @return The Accept header to use. If the given array is empty, + * null will be returned (not to set the Accept header explicitly). + */ + public String selectHeaderAccept(String[] accepts) { + if (accepts.length == 0) { + return null; + } + for (String accept : accepts) { + if (isJsonMime(accept)) { + return accept; + } + } + return StringUtil.join(accepts, ","); + } + + /** + * Select the Content-Type header's value from the given array: + * if JSON exists in the given array, use it; + * otherwise use the first one of the array. + * + * @param contentTypes The Content-Type array to select from + * @return The Content-Type header to use. If the given array is empty, + * JSON will be used. + */ + public String selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0) { + return "application/json"; + } + for (String contentType : contentTypes) { + if (isJsonMime(contentType)) { + return contentType; + } + } + return contentTypes[0]; + } + + /** + * Escape the given string to be used as URL query value. + * @param str String + * @return Escaped string + */ + public String escapeString(String str) { + try { + return URLEncoder.encode(str, "utf8").replaceAll("\\+", "%20"); + } catch (UnsupportedEncodingException e) { + return str; + } + } + + /** + * Serialize the given Java object into string entity according the given + * Content-Type (only JSON is supported for now). + * @param obj Object + * @param formParams Form parameters + * @param contentType Context type + * @return Entity + * @throws ApiException API exception + */ + public Entity serialize(Object obj, Map formParams, String contentType) throws ApiException { + Entity entity; + if (contentType.startsWith("multipart/form-data")) { + MultiPart multiPart = new MultiPart(); + for (Entry param: formParams.entrySet()) { + if (param.getValue() instanceof File) { + File file = (File) param.getValue(); + FormDataContentDisposition contentDisp = FormDataContentDisposition.name(param.getKey()) + .fileName(file.getName()).size(file.length()).build(); + multiPart.bodyPart(new FormDataBodyPart(contentDisp, file, MediaType.APPLICATION_OCTET_STREAM_TYPE)); + } else { + FormDataContentDisposition contentDisp = FormDataContentDisposition.name(param.getKey()).build(); + multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(param.getValue()))); + } + } + entity = Entity.entity(multiPart, MediaType.MULTIPART_FORM_DATA_TYPE); + } else if (contentType.startsWith("application/x-www-form-urlencoded")) { + Form form = new Form(); + for (Entry param: formParams.entrySet()) { + form.param(param.getKey(), parameterToString(param.getValue())); + } + entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE); + } else { + // We let jersey handle the serialization + entity = Entity.entity(obj, contentType); + } + return entity; + } + + /** + * Deserialize response body to Java object according to the Content-Type. + * @param Type + * @param response Response + * @param returnType Return type + * @return Deserialize object + * @throws ApiException API exception + */ + @SuppressWarnings("unchecked") + public T deserialize(Response response, GenericType returnType) throws ApiException { + if (response == null || returnType == null) { + return null; + } + + if ("byte[]".equals(returnType.toString())) { + // Handle binary response (byte array). + return (T) response.readEntity(byte[].class); + } else if (returnType.getRawType() == File.class) { + // Handle file downloading. + T file = (T) downloadFileFromResponse(response); + return file; + } + + String contentType = null; + List contentTypes = response.getHeaders().get("Content-Type"); + if (contentTypes != null && !contentTypes.isEmpty()) + contentType = String.valueOf(contentTypes.get(0)); + + return response.readEntity(returnType); + } + + /** + * Download file from the given response. + * @param response Response + * @return File + * @throws ApiException If fail to read file content from response and write to disk + */ + public File downloadFileFromResponse(Response response) throws ApiException { + try { + File file = prepareDownloadFile(response); +{{^supportJava6}} + Files.copy(response.readEntity(InputStream.class), file.toPath(), StandardCopyOption.REPLACE_EXISTING); +{{/supportJava6}} +{{#supportJava6}} + // Java6 falls back to commons.io for file copying + FileUtils.copyToFile(response.readEntity(InputStream.class), file); +{{/supportJava6}} + return file; + } catch (IOException e) { + throw new ApiException(e); + } + } + + public File prepareDownloadFile(Response response) throws IOException { + String filename = null; + String contentDisposition = (String) response.getHeaders().getFirst("Content-Disposition"); + if (contentDisposition != null && !"".equals(contentDisposition)) { + // Get filename from the Content-Disposition header. + Pattern pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?"); + Matcher matcher = pattern.matcher(contentDisposition); + if (matcher.find()) + filename = matcher.group(1); + } + + String prefix; + String suffix = null; + if (filename == null) { + prefix = "download-"; + suffix = ""; + } else { + int pos = filename.lastIndexOf('.'); + if (pos == -1) { + prefix = filename + "-"; + } else { + prefix = filename.substring(0, pos) + "-"; + suffix = filename.substring(pos); + } + // File.createTempFile requires the prefix to be at least three characters long + if (prefix.length() < 3) + prefix = "download-"; + } + + if (tempFolderPath == null) + return File.createTempFile(prefix, suffix); + else + return File.createTempFile(prefix, suffix, new File(tempFolderPath)); + } + + /** + * Invoke API by sending HTTP request with the given options. + * + * @param Type + * @param path The sub-path of the HTTP URL + * @param method The request method, one of "GET", "POST", "PUT", "HEAD" and "DELETE" + * @param queryParams The query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param formParams The form parameters + * @param accept The request's Accept header + * @param contentType The request's Content-Type header + * @param authNames The authentications to apply + * @param returnType The return type into which to deserialize the response + * @return The response body in type of string + * @throws ApiException API exception + */ + public ApiResponse invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { + updateParamsForAuth(authNames, queryParams, headerParams); + + // Not using `.target(this.basePath).path(path)` below, + // to support (constant) query string in `path`, e.g. "/posts?draft=1" + WebTarget target = httpClient.target(this.basePath + path); + + if (queryParams != null) { + for (Pair queryParam : queryParams) { + if (queryParam.getValue() != null) { + target = target.queryParam(queryParam.getName(), queryParam.getValue()); + } + } + } + + Invocation.Builder invocationBuilder = target.request().accept(accept); + + for (Entry entry : headerParams.entrySet()) { + String value = entry.getValue(); + if (value != null) { + invocationBuilder = invocationBuilder.header(entry.getKey(), value); + } + } + + for (Entry entry : defaultHeaderMap.entrySet()) { + String key = entry.getKey(); + if (!headerParams.containsKey(key)) { + String value = entry.getValue(); + if (value != null) { + invocationBuilder = invocationBuilder.header(key, value); + } + } + } + + Entity entity = serialize(body, formParams, contentType); + + Response response = null; + + try { + if ("GET".equals(method)) { + response = invocationBuilder.get(); + } else if ("POST".equals(method)) { + response = invocationBuilder.post(entity); + } else if ("PUT".equals(method)) { + response = invocationBuilder.put(entity); + } else if ("DELETE".equals(method)) { + response = invocationBuilder.delete(); + } else if ("PATCH".equals(method)) { + response = invocationBuilder.method("PATCH", entity); + } else if ("HEAD".equals(method)) { + response = invocationBuilder.head(); + } else { + throw new ApiException(500, "unknown method type " + method); + } + + int statusCode = response.getStatusInfo().getStatusCode(); + Map> responseHeaders = buildResponseHeaders(response); + + if (response.getStatus() == Status.NO_CONTENT.getStatusCode()) { + return new ApiResponse<>(statusCode, responseHeaders); + } else if (response.getStatusInfo().getFamily() == Status.Family.SUCCESSFUL) { + if (returnType == null) + return new ApiResponse<>(statusCode, responseHeaders); + else + return new ApiResponse<>(statusCode, responseHeaders, deserialize(response, returnType)); + } else { + String message = "error"; + String respBody = null; + if (response.hasEntity()) { + try { + respBody = String.valueOf(response.readEntity(String.class)); + message = respBody; + } catch (RuntimeException e) { + // e.printStackTrace(); + } + } + throw new ApiException( + response.getStatus(), + message, + buildResponseHeaders(response), + respBody); + } + } finally { + try { + response.close(); + } catch (Exception e) { + // it's not critical, since the response object is local in method invokeAPI; that's fine, just continue + } + } + } + + /** + * Build the Client used to make HTTP requests. + * @param debugging Debug setting + * @return Client + */ + protected Client buildHttpClient(boolean debugging) { + final ClientConfig clientConfig = new ClientConfig(); + clientConfig.register(MultiPartFeature.class); + clientConfig.register(json); + clientConfig.register(JacksonFeature.class); + clientConfig.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true); + if (debugging) { +{{^supportJava6}} + clientConfig.register(new LoggingFeature(java.util.logging.Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME), java.util.logging.Level.INFO, LoggingFeature.Verbosity.PAYLOAD_ANY, 1024*50 /* Log payloads up to 50K */)); + clientConfig.property(LoggingFeature.LOGGING_FEATURE_VERBOSITY, LoggingFeature.Verbosity.PAYLOAD_ANY); + // Set logger to ALL + java.util.logging.Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME).setLevel(java.util.logging.Level.ALL); +{{/supportJava6}} +{{#supportJava6}} + clientConfig.register(new LoggingFilter(java.util.logging.Logger.getLogger(LoggingFilter.class.getName()), true)); +{{/supportJava6}} + } + performAdditionalClientConfiguration(clientConfig); + return ClientBuilder.newClient(clientConfig); + } + + protected void performAdditionalClientConfiguration(ClientConfig clientConfig) { + // No-op extension point + } + + protected Map> buildResponseHeaders(Response response) { + Map> responseHeaders = new HashMap>(); + for (Entry> entry: response.getHeaders().entrySet()) { + List values = entry.getValue(); + List headers = new ArrayList(); + for (Object o : values) { + headers.add(String.valueOf(o)); + } + responseHeaders.put(entry.getKey(), headers); + } + return responseHeaders; + } + + /** + * Update query and header parameters based on authentication settings. + * + * @param authNames The authentications to apply + */ + protected void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams) { + for (String authName : authNames) { + Authentication auth = authentications.get(authName); + if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + auth.applyToParams(queryParams, headerParams); + } + } +} diff --git a/libraries/jersey2/ApiResponse.mustache b/libraries/jersey2/ApiResponse.mustache new file mode 100644 index 00000000000..2f01685a0af --- /dev/null +++ b/libraries/jersey2/ApiResponse.mustache @@ -0,0 +1,48 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import java.util.List; +import java.util.Map; + +/** + * API response returned by API call. + * + * @param The type of data that is deserialized from response body + */ +public class ApiResponse { + private final int statusCode; + private final Map> headers; + private final T data; + + /** + * @param statusCode The status code of HTTP response + * @param headers The headers of HTTP response + */ + public ApiResponse(int statusCode, Map> headers) { + this(statusCode, headers, null); + } + + /** + * @param statusCode The status code of HTTP response + * @param headers The headers of HTTP response + * @param data The object deserialized from response bod + */ + public ApiResponse(int statusCode, Map> headers, T data) { + this.statusCode = statusCode; + this.headers = headers; + this.data = data; + } + + public int getStatusCode() { + return statusCode; + } + + public Map> getHeaders() { + return headers; + } + + public T getData() { + return data; + } +} diff --git a/libraries/jersey2/JSON.mustache b/libraries/jersey2/JSON.mustache new file mode 100644 index 00000000000..911391a6baf --- /dev/null +++ b/libraries/jersey2/JSON.mustache @@ -0,0 +1,62 @@ +package {{invokerPackage}}; + +{{#threetenbp}} +import org.threeten.bp.*; +{{/threetenbp}} +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.*; +{{#java8}} +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{/java8}} +{{#joda}} +import com.fasterxml.jackson.datatype.joda.JodaModule; +{{/joda}} +{{#threetenbp}} +import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; +{{/threetenbp}} + +import java.text.DateFormat; + +import javax.ws.rs.ext.ContextResolver; + +{{>generatedAnnotation}} +public class JSON implements ContextResolver { + private ObjectMapper mapper; + + public JSON() { + mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.setDateFormat(new RFC3339DateFormat()); + {{#java8}} + mapper.registerModule(new JavaTimeModule()); + {{/java8}} + {{#joda}} + mapper.registerModule(new JodaModule()); + {{/joda}} + {{#threetenbp}} + ThreeTenModule module = new ThreeTenModule(); + module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); + module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); + module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); + mapper.registerModule(module); + {{/threetenbp}} + } + + /** + * Set the date format for JSON (de)serialization with Date properties. + * @param dateFormat Date format + */ + public void setDateFormat(DateFormat dateFormat) { + mapper.setDateFormat(dateFormat); + } + + @Override + public ObjectMapper getContext(Class type) { + return mapper; + } +} diff --git a/libraries/jersey2/api.mustache b/libraries/jersey2/api.mustache new file mode 100644 index 00000000000..fed034609c8 --- /dev/null +++ b/libraries/jersey2/api.mustache @@ -0,0 +1,143 @@ +package {{package}}; + +import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.ApiResponse; +import {{invokerPackage}}.Configuration; +import {{invokerPackage}}.Pair; + +import javax.ws.rs.core.GenericType; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}} { + private ApiClient {{localVariablePrefix}}apiClient; + + public {{classname}}() { + this(Configuration.getDefaultApiClient()); + } + + public {{classname}}(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + public ApiClient getApiClient() { + return {{localVariablePrefix}}apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + {{#operation}} + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} + {{#returnType}} + * @return {{returnType}} + {{/returnType}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + {{#returnType}} + return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}).getData(); + {{/returnType}}{{^returnType}} + {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{/returnType}} + } + + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} + {{#returnType}} + * @return ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + {{/returnType}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + Object {{localVariablePrefix}}localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + } + {{/required}}{{/allParams}} + // create path and map variables + String {{localVariablePrefix}}localVarPath = "{{{path}}}"{{#pathParams}} + .replaceAll("\\{" + "{{baseName}}" + "\\}", {{localVariablePrefix}}apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; + + // query params + {{javaUtilPrefix}}List {{localVariablePrefix}}localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarFormParams = new {{javaUtilPrefix}}HashMap(); + + {{#queryParams}} + {{localVariablePrefix}}localVarQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); + {{/queryParams}} + + {{#headerParams}}if ({{paramName}} != null) + {{localVariablePrefix}}localVarHeaderParams.put("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}})); + {{/headerParams}} + + {{#formParams}}if ({{paramName}} != null) + {{localVariablePrefix}}localVarFormParams.put("{{baseName}}", {{paramName}}); + {{/formParams}} + + final String[] {{localVariablePrefix}}localVarAccepts = { + {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} + }; + final String {{localVariablePrefix}}localVarAccept = {{localVariablePrefix}}apiClient.selectHeaderAccept({{localVariablePrefix}}localVarAccepts); + + final String[] {{localVariablePrefix}}localVarContentTypes = { + {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} + }; + final String {{localVariablePrefix}}localVarContentType = {{localVariablePrefix}}apiClient.selectHeaderContentType({{localVariablePrefix}}localVarContentTypes); + + String[] {{localVariablePrefix}}localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + + {{#returnType}} + GenericType<{{{returnType}}}> {{localVariablePrefix}}localVarReturnType = new GenericType<{{{returnType}}}>() {}; + return {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarPostBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccept, {{localVariablePrefix}}localVarContentType, {{localVariablePrefix}}localVarAuthNames, {{localVariablePrefix}}localVarReturnType); + {{/returnType}}{{^returnType}} + return {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarPostBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccept, {{localVariablePrefix}}localVarContentType, {{localVariablePrefix}}localVarAuthNames, null); + {{/returnType}} + } + {{/operation}} +} +{{/operations}} diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache new file mode 100644 index 00000000000..19d8c2c6d84 --- /dev/null +++ b/libraries/jersey2/build.gradle.mustache @@ -0,0 +1,146 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + } + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + {{#java8}} + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + {{/java8}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + swagger_annotations_version = "1.5.17" + jackson_version = "2.8.9" + {{#supportJava6}} + jersey_version = "2.6" + commons_io_version=2.5 + commons_lang3_version=3.6 + {{/supportJava6}} + {{^supportJava6}} + jersey_version = "2.25.1" + {{/supportJava6}} + junit_version = "4.12" +} + +dependencies { + compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "org.glassfish.jersey.core:jersey-client:$jersey_version" + compile "org.glassfish.jersey.media:jersey-media-multipart:$jersey_version" + compile "org.glassfish.jersey.media:jersey-media-json-jackson:$jersey_version" + compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + {{#joda}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version", + {{/joda}} + {{#java8}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version", + {{/java8}} + {{#supportJava6}} + compile "commons-io:commons-io:$commons_io_version" + compile "org.apache.commons:commons-lang3:$commons_lang3_version" + {{/supportJava6}} + {{#threetenbp}} + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_version", + {{/threetenbp}} + {{^java8}} + compile "com.brsanthu:migbase64:2.2" + {{/java8}} + testCompile "junit:junit:$junit_version" +} diff --git a/libraries/jersey2/build.sbt.mustache b/libraries/jersey2/build.sbt.mustache new file mode 100644 index 00000000000..544297d481d --- /dev/null +++ b/libraries/jersey2/build.sbt.mustache @@ -0,0 +1,38 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "io.swagger" % "swagger-annotations" % "1.5.17", + "org.glassfish.jersey.core" % "jersey-client" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, + "org.glassfish.jersey.media" % "jersey-media-multipart" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, + "org.glassfish.jersey.media" % "jersey-media-json-jackson" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, + "com.fasterxml.jackson.core" % "jackson-core" % "{{^threetenbp}}2.8.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "{{^threetenbp}}2.8.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "{{^threetenbp}}2.8.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" % "compile", + {{#joda}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.8.9" % "compile", + {{/joda}} + {{#java8}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.8.9" % "compile", + {{/java8}} + {{#threetenbp}} + "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4" % "compile", + {{/threetenbp}} + {{^java8}} + "com.brsanthu" % "migbase64" % "2.2", + {{/java8}} + {{#supportJava6}} + "org.apache.commons" % "commons-lang3" % "3.6", + "commons-io" % "commons-io" % "2.5", + {{/supportJava6}} + "junit" % "junit" % "4.12" % "test", + "com.novocode" % "junit-interface" % "0.10" % "test" + ) + ) diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache new file mode 100644 index 00000000000..2dff93306a0 --- /dev/null +++ b/libraries/jersey2/pom.mustache @@ -0,0 +1,330 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{artifactUrl}} + {{artifactDescription}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.6 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + {{#java8}} + + 1.8 + 1.8 + {{/java8}} + {{^java8}} + + 1.7 + 1.7 + {{/java8}} + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-core-version} + + + + + org.glassfish.jersey.core + jersey-client + ${jersey-version} + + + org.glassfish.jersey.media + jersey-media-multipart + ${jersey-version} + + + org.glassfish.jersey.media + jersey-media-json-jackson + ${jersey-version} + + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-version} + + {{#withXml}} + + + + org.glassfish.jersey.media + jersey-media-jaxb + ${jersey-version} + + + {{/withXml}} + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + {{/joda}} + {{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{/java8}} + {{#threetenbp}} + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${jackson-version} + + {{/threetenbp}} + {{^java8}} + + + com.brsanthu + migbase64 + 2.2 + + {{/java8}} + {{#supportJava6}} + + org.apache.commons + commons-lang3 + ${commons_lang3_version} + + + commons-io + commons-io + ${commons_io_version} + + {{/supportJava6}} + {{#useBeanValidation}} + + + javax.validation + validation-api + 1.1.0.Final + provided + + {{/useBeanValidation}} + + + junit + junit + ${junit-version} + test + + + + UTF-8 + 1.5.18 + {{^supportJava6}} + 2.25.1 + {{/supportJava6}} + {{#supportJava6}} + 2.6 + 2.5 + 3.6 + {{/supportJava6}} + {{^threetenbp}}2.7.5{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} + 1.0.0 + 4.12 + + diff --git a/libraries/okhttp-gson/ApiCallback.mustache b/libraries/okhttp-gson/ApiCallback.mustache new file mode 100644 index 00000000000..4cc99a76ec3 --- /dev/null +++ b/libraries/okhttp-gson/ApiCallback.mustache @@ -0,0 +1,51 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import java.io.IOException; + +import java.util.Map; +import java.util.List; + +/** + * Callback for asynchronous API call. + * + * @param The return type + */ +public interface ApiCallback { + /** + * This is called when the API call fails. + * + * @param e The exception causing the failure + * @param statusCode Status code of the response if available, otherwise it would be 0 + * @param responseHeaders Headers of the response if available, otherwise it would be null + */ + void onFailure(ApiException e, int statusCode, Map> responseHeaders); + + /** + * This is called when the API call succeeded. + * + * @param result The result deserialized from response + * @param statusCode Status code of the response + * @param responseHeaders Headers of the response + */ + void onSuccess(T result, int statusCode, Map> responseHeaders); + + /** + * This is called when the API upload processing. + * + * @param bytesWritten bytes Written + * @param contentLength content length of request body + * @param done write end + */ + void onUploadProgress(long bytesWritten, long contentLength, boolean done); + + /** + * This is called when the API downlond processing. + * + * @param bytesRead bytes Read + * @param contentLength content lenngth of the response + * @param done Read end + */ + void onDownloadProgress(long bytesRead, long contentLength, boolean done); +} diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache new file mode 100644 index 00000000000..0ae00335726 --- /dev/null +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -0,0 +1,1227 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import com.squareup.okhttp.*; +import com.squareup.okhttp.internal.http.HttpMethod; +import com.squareup.okhttp.logging.HttpLoggingInterceptor; +import com.squareup.okhttp.logging.HttpLoggingInterceptor.Level; +import okio.BufferedSink; +import okio.Okio; +{{#joda}} +import org.joda.time.DateTime; +import org.joda.time.LocalDate; +import org.joda.time.format.DateTimeFormatter; +{{/joda}} +{{#threetenbp}} +import org.threeten.bp.LocalDate; +import org.threeten.bp.OffsetDateTime; +import org.threeten.bp.format.DateTimeFormatter; +{{/threetenbp}} + +import javax.net.ssl.*; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Type; +import java.net.URLConnection; +import java.net.URLEncoder; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.SecureRandom; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.text.DateFormat; +{{#java8}} +import java.time.LocalDate; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +{{/java8}} +import java.util.*; +import java.util.Map.Entry; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import {{invokerPackage}}.auth.Authentication; +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.OAuth; + +public class ApiClient { + + private String basePath = "{{{basePath}}}"; + private boolean debugging = false; + private Map defaultHeaderMap = new HashMap(); + private String tempFolderPath = null; + + private Map authentications; + + private DateFormat dateFormat; + private DateFormat datetimeFormat; + private boolean lenientDatetimeFormat; + private int dateLength; + + private InputStream sslCaCert; + private boolean verifyingSsl; + private KeyManager[] keyManagers; + + private OkHttpClient httpClient; + private JSON json; + + private HttpLoggingInterceptor loggingInterceptor; + + /* + * Constructor for ApiClient + */ + public ApiClient() { + httpClient = new OkHttpClient(); + + {{#useGzipFeature}} + // Enable gzip request compression + httpClient.interceptors().add(new GzipRequestInterceptor()); + {{/useGzipFeature}} + + verifyingSsl = true; + + json = new JSON(); + + // Set default User-Agent. + setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}Swagger-Codegen/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap();{{#authMethods}}{{#isBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + } + + /** + * Get base path + * + * @return Baes path + */ + public String getBasePath() { + return basePath; + } + + /** + * Set base path + * + * @param basePath Base path of the URL (e.g {{{basePath}}} + * @return An instance of OkHttpClient + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Get HTTP client + * + * @return An instance of OkHttpClient + */ + public OkHttpClient getHttpClient() { + return httpClient; + } + + /** + * Set HTTP client + * + * @param httpClient An instance of OkHttpClient + * @return Api Client + */ + public ApiClient setHttpClient(OkHttpClient httpClient) { + this.httpClient = httpClient; + return this; + } + + /** + * Get JSON + * + * @return JSON object + */ + public JSON getJSON() { + return json; + } + + /** + * Set JSON + * + * @param json JSON object + * @return Api client + */ + public ApiClient setJSON(JSON json) { + this.json = json; + return this; + } + + /** + * True if isVerifyingSsl flag is on + * + * @return True if isVerifySsl flag is on + */ + public boolean isVerifyingSsl() { + return verifyingSsl; + } + + /** + * Configure whether to verify certificate and hostname when making https requests. + * Default to true. + * NOTE: Do NOT set to false in production code, otherwise you would face multiple types of cryptographic attacks. + * + * @param verifyingSsl True to verify TLS/SSL connection + * @return ApiClient + */ + public ApiClient setVerifyingSsl(boolean verifyingSsl) { + this.verifyingSsl = verifyingSsl; + applySslSettings(); + return this; + } + + /** + * Get SSL CA cert. + * + * @return Input stream to the SSL CA cert + */ + public InputStream getSslCaCert() { + return sslCaCert; + } + + /** + * Configure the CA certificate to be trusted when making https requests. + * Use null to reset to default. + * + * @param sslCaCert input stream for SSL CA cert + * @return ApiClient + */ + public ApiClient setSslCaCert(InputStream sslCaCert) { + this.sslCaCert = sslCaCert; + applySslSettings(); + return this; + } + + public KeyManager[] getKeyManagers() { + return keyManagers; + } + + /** + * Configure client keys to use for authorization in an SSL session. + * Use null to reset to default. + * + * @param managers The KeyManagers to use + * @return ApiClient + */ + public ApiClient setKeyManagers(KeyManager[] managers) { + this.keyManagers = managers; + applySslSettings(); + return this; + } + + public DateFormat getDateFormat() { + return dateFormat; + } + + public ApiClient setDateFormat(DateFormat dateFormat) { + this.json.setDateFormat(dateFormat); + return this; + } + + public ApiClient setSqlDateFormat(DateFormat dateFormat) { + this.json.setSqlDateFormat(dateFormat); + return this; + } + + {{#joda}} + public ApiClient setDateTimeFormat(DateTimeFormatter dateFormat) { + this.json.setDateTimeFormat(dateFormat); + return this; + } + + public ApiClient setLocalDateFormat(DateTimeFormatter dateFormat) { + this.json.setLocalDateFormat(dateFormat); + return this; + } + + {{/joda}} + {{#jsr310}} + public ApiClient setOffsetDateTimeFormat(DateTimeFormatter dateFormat) { + this.json.setOffsetDateTimeFormat(dateFormat); + return this; + } + + public ApiClient setLocalDateFormat(DateTimeFormatter dateFormat) { + this.json.setLocalDateFormat(dateFormat); + return this; + } + + {{/jsr310}} + public ApiClient setLenientOnJson(boolean lenientOnJson) { + this.json.setLenientOnJson(lenientOnJson); + return this; + } + + /** + * Get authentications (key: authentication name, value: authentication). + * + * @return Map of authentication objects + */ + public Map getAuthentications() { + return authentications; + } + + /** + * Get authentication for the given name. + * + * @param authName The authentication name + * @return The authentication, null if not found + */ + public Authentication getAuthentication(String authName) { + return authentications.get(authName); + } + + /** + * Helper method to set username for the first HTTP basic authentication. + * + * @param username Username + */ + public void setUsername(String username) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setUsername(username); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set password for the first HTTP basic authentication. + * + * @param password Password + */ + public void setPassword(String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setPassword(password); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set API key value for the first API key authentication. + * + * @param apiKey API key + */ + public void setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + * + * @param apiKeyPrefix API key prefix + */ + public void setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set access token for the first OAuth2 authentication. + * + * @param accessToken Access token + */ + public void setAccessToken(String accessToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setAccessToken(accessToken); + return; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Set the User-Agent header's value (by adding to the default header map). + * + * @param userAgent HTTP request's user agent + * @return ApiClient + */ + public ApiClient setUserAgent(String userAgent) { + addDefaultHeader("User-Agent", userAgent); + return this; + } + + /** + * Add a default header. + * + * @param key The header's key + * @param value The header's value + * @return ApiClient + */ + public ApiClient addDefaultHeader(String key, String value) { + defaultHeaderMap.put(key, value); + return this; + } + + /** + * Check that whether debugging is enabled for this API client. + * + * @return True if debugging is enabled, false otherwise. + */ + public boolean isDebugging() { + return debugging; + } + + /** + * Enable/disable debugging for this API client. + * + * @param debugging To enable (true) or disable (false) debugging + * @return ApiClient + */ + public ApiClient setDebugging(boolean debugging) { + if (debugging != this.debugging) { + if (debugging) { + loggingInterceptor = new HttpLoggingInterceptor(); + loggingInterceptor.setLevel(Level.BODY); + httpClient.interceptors().add(loggingInterceptor); + } else { + httpClient.interceptors().remove(loggingInterceptor); + loggingInterceptor = null; + } + } + this.debugging = debugging; + return this; + } + + /** + * The path of temporary folder used to store downloaded files from endpoints + * with file response. The default value is null, i.e. using + * the system's default tempopary folder. + * + * @see createTempFile + * @return Temporary folder path + */ + public String getTempFolderPath() { + return tempFolderPath; + } + + /** + * Set the temporary folder path (for downloading files) + * + * @param tempFolderPath Temporary folder path + * @return ApiClient + */ + public ApiClient setTempFolderPath(String tempFolderPath) { + this.tempFolderPath = tempFolderPath; + return this; + } + + /** + * Get connection timeout (in milliseconds). + * + * @return Timeout in milliseconds + */ + public int getConnectTimeout() { + return httpClient.getConnectTimeout(); + } + + /** + * Sets the connect timeout (in milliseconds). + * A value of 0 means no timeout, otherwise values must be between 1 and + * {@link Integer#MAX_VALUE}. + * + * @param connectionTimeout connection timeout in milliseconds + * @return Api client + */ + public ApiClient setConnectTimeout(int connectionTimeout) { + httpClient.setConnectTimeout(connectionTimeout, TimeUnit.MILLISECONDS); + return this; + } + + /** + * Get read timeout (in milliseconds). + * + * @return Timeout in milliseconds + */ + public int getReadTimeout() { + return httpClient.getReadTimeout(); + } + + /** + * Sets the read timeout (in milliseconds). + * A value of 0 means no timeout, otherwise values must be between 1 and + * {@link Integer#MAX_VALUE}. + * + * @param readTimeout read timeout in milliseconds + * @return Api client + */ + public ApiClient setReadTimeout(int readTimeout) { + httpClient.setReadTimeout(readTimeout, TimeUnit.MILLISECONDS); + return this; + } + + /** + * Get write timeout (in milliseconds). + * + * @return Timeout in milliseconds + */ + public int getWriteTimeout() { + return httpClient.getWriteTimeout(); + } + + /** + * Sets the write timeout (in milliseconds). + * A value of 0 means no timeout, otherwise values must be between 1 and + * {@link Integer#MAX_VALUE}. + * + * @param writeTimeout connection timeout in milliseconds + * @return Api client + */ + public ApiClient setWriteTimeout(int writeTimeout) { + httpClient.setWriteTimeout(writeTimeout, TimeUnit.MILLISECONDS); + return this; + } + + /** + * Format the given parameter object into string. + * + * @param param Parameter + * @return String representation of the parameter + */ + public String parameterToString(Object param) { + if (param == null) { + return ""; + } else if (param instanceof Date {{#joda}}|| param instanceof DateTime || param instanceof LocalDate{{/joda}}{{#jsr310}}|| param instanceof OffsetDateTime || param instanceof LocalDate{{/jsr310}}) { + //Serialize to json string and remove the " enclosing characters + String jsonStr = json.serialize(param); + return jsonStr.substring(1, jsonStr.length() - 1); + } else if (param instanceof Collection) { + StringBuilder b = new StringBuilder(); + for (Object o : (Collection)param) { + if (b.length() > 0) { + b.append(","); + } + b.append(String.valueOf(o)); + } + return b.toString(); + } else { + return String.valueOf(param); + } + } + + /** + * Formats the specified query parameter to a list containing a single {@code Pair} object. + * + * Note that {@code value} must not be a collection. + * + * @param name The name of the parameter. + * @param value The value of the parameter. + * @return A list containing a single {@code Pair} object. + */ + public List parameterToPair(String name, Object value) { + List params = new ArrayList(); + + // preconditions + if (name == null || name.isEmpty() || value == null || value instanceof Collection) return params; + + params.add(new Pair(name, parameterToString(value))); + return params; + } + + /** + * Formats the specified collection query parameters to a list of {@code Pair} objects. + * + * Note that the values of each of the returned Pair objects are percent-encoded. + * + * @param collectionFormat The collection format of the parameter. + * @param name The name of the parameter. + * @param value The value of the parameter. + * @return A list of {@code Pair} objects. + */ + public List parameterToPairs(String collectionFormat, String name, Collection value) { + List params = new ArrayList(); + + // preconditions + if (name == null || name.isEmpty() || value == null || value.isEmpty()) { + return params; + } + + // create the params based on the collection format + if ("multi".equals(collectionFormat)) { + for (Object item : value) { + params.add(new Pair(name, escapeString(parameterToString(item)))); + } + return params; + } + + // collectionFormat is assumed to be "csv" by default + String delimiter = ","; + + // escape all delimiters except commas, which are URI reserved + // characters + if ("ssv".equals(collectionFormat)) { + delimiter = escapeString(" "); + } else if ("tsv".equals(collectionFormat)) { + delimiter = escapeString("\t"); + } else if ("pipes".equals(collectionFormat)) { + delimiter = escapeString("|"); + } + + StringBuilder sb = new StringBuilder() ; + for (Object item : value) { + sb.append(delimiter); + sb.append(escapeString(parameterToString(item))); + } + + params.add(new Pair(name, sb.substring(delimiter.length()))); + + return params; + } + + /** + * Sanitize filename by removing path. + * e.g. ../../sun.gif becomes sun.gif + * + * @param filename The filename to be sanitized + * @return The sanitized filename + */ + public String sanitizeFilename(String filename) { + return filename.replaceAll(".*[/\\\\]", ""); + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * application/vnd.company+json + * "* / *" is also default to JSON + * @param mime MIME (Multipurpose Internet Mail Extensions) + * @return True if the given MIME is JSON, false otherwise. + */ + public boolean isJsonMime(String mime) { + String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$"; + return mime != null && (mime.matches(jsonMime) || mime.equals("*/*")); + } + + /** + * Select the Accept header's value from the given accepts array: + * if JSON exists in the given array, use it; + * otherwise use all of them (joining into a string) + * + * @param accepts The accepts array to select from + * @return The Accept header to use. If the given array is empty, + * null will be returned (not to set the Accept header explicitly). + */ + public String selectHeaderAccept(String[] accepts) { + if (accepts.length == 0) { + return null; + } + for (String accept : accepts) { + if (isJsonMime(accept)) { + return accept; + } + } + return StringUtil.join(accepts, ","); + } + + /** + * Select the Content-Type header's value from the given array: + * if JSON exists in the given array, use it; + * otherwise use the first one of the array. + * + * @param contentTypes The Content-Type array to select from + * @return The Content-Type header to use. If the given array is empty, + * or matches "any", JSON will be used. + */ + public String selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0 || contentTypes[0].equals("*/*")) { + return "application/json"; + } + for (String contentType : contentTypes) { + if (isJsonMime(contentType)) { + return contentType; + } + } + return contentTypes[0]; + } + + /** + * Escape the given string to be used as URL query value. + * + * @param str String to be escaped + * @return Escaped string + */ + public String escapeString(String str) { + try { + return URLEncoder.encode(str, "utf8").replaceAll("\\+", "%20"); + } catch (UnsupportedEncodingException e) { + return str; + } + } + + /** + * Deserialize response body to Java object, according to the return type and + * the Content-Type response header. + * + * @param Type + * @param response HTTP response + * @param returnType The type of the Java object + * @return The deserialized Java object + * @throws ApiException If fail to deserialize response body, i.e. cannot read response body + * or the Content-Type of the response is not supported. + */ + @SuppressWarnings("unchecked") + public T deserialize(Response response, Type returnType) throws ApiException { + if (response == null || returnType == null) { + return null; + } + + if ("byte[]".equals(returnType.toString())) { + // Handle binary response (byte array). + try { + return (T) response.body().bytes(); + } catch (IOException e) { + throw new ApiException(e); + } + } else if (returnType.equals(File.class)) { + // Handle file downloading. + return (T) downloadFileFromResponse(response); + } + + String respBody; + try { + if (response.body() != null) + respBody = response.body().string(); + else + respBody = null; + } catch (IOException e) { + throw new ApiException(e); + } + + if (respBody == null || "".equals(respBody)) { + return null; + } + + String contentType = response.headers().get("Content-Type"); + if (contentType == null) { + // ensuring a default content type + contentType = "application/json"; + } + if (isJsonMime(contentType)) { + return json.deserialize(respBody, returnType); + } else if (returnType.equals(String.class)) { + // Expecting string, return the raw response body. + return (T) respBody; + } else { + throw new ApiException( + "Content type \"" + contentType + "\" is not supported for type: " + returnType, + response.code(), + response.headers().toMultimap(), + respBody); + } + } + + /** + * Serialize the given Java object into request body according to the object's + * class and the request Content-Type. + * + * @param obj The Java object + * @param contentType The request Content-Type + * @return The serialized request body + * @throws ApiException If fail to serialize the given object + */ + public RequestBody serialize(Object obj, String contentType) throws ApiException { + if (obj instanceof byte[]) { + // Binary (byte array) body parameter support. + return RequestBody.create(MediaType.parse(contentType), (byte[]) obj); + } else if (obj instanceof File) { + // File body parameter support. + return RequestBody.create(MediaType.parse(contentType), (File) obj); + } else if (isJsonMime(contentType)) { + String content; + if (obj != null) { + content = json.serialize(obj); + } else { + content = null; + } + return RequestBody.create(MediaType.parse(contentType), content); + } else { + throw new ApiException("Content type \"" + contentType + "\" is not supported"); + } + } + + /** + * Download file from the given response. + * + * @param response An instance of the Response object + * @throws ApiException If fail to read file content from response and write to disk + * @return Downloaded file + */ + public File downloadFileFromResponse(Response response) throws ApiException { + try { + File file = prepareDownloadFile(response); + BufferedSink sink = Okio.buffer(Okio.sink(file)); + sink.writeAll(response.body().source()); + sink.close(); + return file; + } catch (IOException e) { + throw new ApiException(e); + } + } + + /** + * Prepare file for download + * + * @param response An instance of the Response object + * @throws IOException If fail to prepare file for download + * @return Prepared file for the download + */ + public File prepareDownloadFile(Response response) throws IOException { + String filename = null; + String contentDisposition = response.header("Content-Disposition"); + if (contentDisposition != null && !"".equals(contentDisposition)) { + // Get filename from the Content-Disposition header. + Pattern pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?"); + Matcher matcher = pattern.matcher(contentDisposition); + if (matcher.find()) { + filename = sanitizeFilename(matcher.group(1)); + } + } + + String prefix = null; + String suffix = null; + if (filename == null) { + prefix = "download-"; + suffix = ""; + } else { + int pos = filename.lastIndexOf("."); + if (pos == -1) { + prefix = filename + "-"; + } else { + prefix = filename.substring(0, pos) + "-"; + suffix = filename.substring(pos); + } + // File.createTempFile requires the prefix to be at least three characters long + if (prefix.length() < 3) + prefix = "download-"; + } + + if (tempFolderPath == null) + return File.createTempFile(prefix, suffix); + else + return File.createTempFile(prefix, suffix, new File(tempFolderPath)); + } + + /** + * {@link #execute(Call, Type)} + * + * @param Type + * @param call An instance of the Call object + * @throws ApiException If fail to execute the call + * @return ApiResponse<T> + */ + public ApiResponse execute(Call call) throws ApiException { + return execute(call, null); + } + + /** + * Execute HTTP call and deserialize the HTTP response body into the given return type. + * + * @param returnType The return type used to deserialize HTTP response body + * @param The return type corresponding to (same with) returnType + * @param call Call + * @return ApiResponse object containing response status, headers and + * data, which is a Java object deserialized from response body and would be null + * when returnType is null. + * @throws ApiException If fail to execute the call + */ + public ApiResponse execute(Call call, Type returnType) throws ApiException { + try { + Response response = call.execute(); + T data = handleResponse(response, returnType); + return new ApiResponse(response.code(), response.headers().toMultimap(), data); + } catch (IOException e) { + throw new ApiException(e); + } + } + + /** + * {@link #executeAsync(Call, Type, ApiCallback)} + * + * @param Type + * @param call An instance of the Call object + * @param callback ApiCallback<T> + */ + public void executeAsync(Call call, ApiCallback callback) { + executeAsync(call, null, callback); + } + + /** + * Execute HTTP call asynchronously. + * + * @see #execute(Call, Type) + * @param Type + * @param call The callback to be executed when the API call finishes + * @param returnType Return type + * @param callback ApiCallback + */ + @SuppressWarnings("unchecked") + public void executeAsync(Call call, final Type returnType, final ApiCallback callback) { + call.enqueue(new Callback() { + @Override + public void onFailure(Request request, IOException e) { + callback.onFailure(new ApiException(e), 0, null); + } + + @Override + public void onResponse(Response response) throws IOException { + T result; + try { + result = (T) handleResponse(response, returnType); + } catch (ApiException e) { + callback.onFailure(e, response.code(), response.headers().toMultimap()); + return; + } + callback.onSuccess(result, response.code(), response.headers().toMultimap()); + } + }); + } + + /** + * Handle the given response, return the deserialized object when the response is successful. + * + * @param Type + * @param response Response + * @param returnType Return type + * @throws ApiException If the response has a unsuccessful status code or + * fail to deserialize the response body + * @return Type + */ + public T handleResponse(Response response, Type returnType) throws ApiException { + if (response.isSuccessful()) { + if (returnType == null || response.code() == 204) { + // returning null if the returnType is not defined, + // or the status code is 204 (No Content) + if (response.body() != null) { + try { + response.body().close(); + } catch (IOException e) { + throw new ApiException(response.message(), e, response.code(), response.headers().toMultimap()); + } + } + return null; + } else { + return deserialize(response, returnType); + } + } else { + String respBody = null; + if (response.body() != null) { + try { + respBody = response.body().string(); + } catch (IOException e) { + throw new ApiException(response.message(), e, response.code(), response.headers().toMultimap()); + } + } + throw new ApiException(response.message(), response.code(), response.headers().toMultimap(), respBody); + } + } + + /** + * Build HTTP call with the given options. + * + * @param path The sub-path of the HTTP URL + * @param method The request method, one of "GET", "HEAD", "OPTIONS", "POST", "PUT", "PATCH" and "DELETE" + * @param queryParams The query parameters + * @param collectionQueryParams The collection query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param formParams The form parameters + * @param authNames The authentications to apply + * @param progressRequestListener Progress request listener + * @return The HTTP call + * @throws ApiException If fail to serialize the request body object + */ + public Call buildCall(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map formParams, String[] authNames, ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException { + Request request = buildRequest(path, method, queryParams, collectionQueryParams, body, headerParams, formParams, authNames, progressRequestListener); + + return httpClient.newCall(request); + } + + /** + * Build an HTTP request with the given options. + * + * @param path The sub-path of the HTTP URL + * @param method The request method, one of "GET", "HEAD", "OPTIONS", "POST", "PUT", "PATCH" and "DELETE" + * @param queryParams The query parameters + * @param collectionQueryParams The collection query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param formParams The form parameters + * @param authNames The authentications to apply + * @param progressRequestListener Progress request listener + * @return The HTTP request + * @throws ApiException If fail to serialize the request body object + */ + public Request buildRequest(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map formParams, String[] authNames, ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException { + updateParamsForAuth(authNames, queryParams, headerParams); + + final String url = buildUrl(path, queryParams, collectionQueryParams); + final Request.Builder reqBuilder = new Request.Builder().url(url); + processHeaderParams(headerParams, reqBuilder); + + String contentType = (String) headerParams.get("Content-Type"); + // ensuring a default content type + if (contentType == null) { + contentType = "application/json"; + } + + RequestBody reqBody; + if (!HttpMethod.permitsRequestBody(method)) { + reqBody = null; + } else if ("application/x-www-form-urlencoded".equals(contentType)) { + reqBody = buildRequestBodyFormEncoding(formParams); + } else if ("multipart/form-data".equals(contentType)) { + reqBody = buildRequestBodyMultipart(formParams); + } else if (body == null) { + if ("DELETE".equals(method)) { + // allow calling DELETE without sending a request body + reqBody = null; + } else { + // use an empty request body (for POST, PUT and PATCH) + reqBody = RequestBody.create(MediaType.parse(contentType), ""); + } + } else { + reqBody = serialize(body, contentType); + } + + Request request = null; + + if(progressRequestListener != null && reqBody != null) { + ProgressRequestBody progressRequestBody = new ProgressRequestBody(reqBody, progressRequestListener); + request = reqBuilder.method(method, progressRequestBody).build(); + } else { + request = reqBuilder.method(method, reqBody).build(); + } + + return request; + } + + /** + * Build full URL by concatenating base path, the given sub path and query parameters. + * + * @param path The sub path + * @param queryParams The query parameters + * @param collectionQueryParams The collection query parameters + * @return The full URL + */ + public String buildUrl(String path, List queryParams, List collectionQueryParams) { + final StringBuilder url = new StringBuilder(); + url.append(basePath).append(path); + + if (queryParams != null && !queryParams.isEmpty()) { + // support (constant) query string in `path`, e.g. "/posts?draft=1" + String prefix = path.contains("?") ? "&" : "?"; + for (Pair param : queryParams) { + if (param.getValue() != null) { + if (prefix != null) { + url.append(prefix); + prefix = null; + } else { + url.append("&"); + } + String value = parameterToString(param.getValue()); + url.append(escapeString(param.getName())).append("=").append(escapeString(value)); + } + } + } + + if (collectionQueryParams != null && !collectionQueryParams.isEmpty()) { + String prefix = url.toString().contains("?") ? "&" : "?"; + for (Pair param : collectionQueryParams) { + if (param.getValue() != null) { + if (prefix != null) { + url.append(prefix); + prefix = null; + } else { + url.append("&"); + } + String value = parameterToString(param.getValue()); + // collection query parameter value already escaped as part of parameterToPairs + url.append(escapeString(param.getName())).append("=").append(value); + } + } + } + + return url.toString(); + } + + /** + * Set header parameters to the request builder, including default headers. + * + * @param headerParams Header parameters in the ofrm of Map + * @param reqBuilder Reqeust.Builder + */ + public void processHeaderParams(Map headerParams, Request.Builder reqBuilder) { + for (Entry param : headerParams.entrySet()) { + reqBuilder.header(param.getKey(), parameterToString(param.getValue())); + } + for (Entry header : defaultHeaderMap.entrySet()) { + if (!headerParams.containsKey(header.getKey())) { + reqBuilder.header(header.getKey(), parameterToString(header.getValue())); + } + } + } + + /** + * Update query and header parameters based on authentication settings. + * + * @param authNames The authentications to apply + * @param queryParams List of query parameters + * @param headerParams Map of header parameters + */ + public void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams) { + for (String authName : authNames) { + Authentication auth = authentications.get(authName); + if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + auth.applyToParams(queryParams, headerParams); + } + } + + /** + * Build a form-encoding request body with the given form parameters. + * + * @param formParams Form parameters in the form of Map + * @return RequestBody + */ + public RequestBody buildRequestBodyFormEncoding(Map formParams) { + FormEncodingBuilder formBuilder = new FormEncodingBuilder(); + for (Entry param : formParams.entrySet()) { + formBuilder.add(param.getKey(), parameterToString(param.getValue())); + } + return formBuilder.build(); + } + + /** + * Build a multipart (file uploading) request body with the given form parameters, + * which could contain text fields and file fields. + * + * @param formParams Form parameters in the form of Map + * @return RequestBody + */ + public RequestBody buildRequestBodyMultipart(Map formParams) { + MultipartBuilder mpBuilder = new MultipartBuilder().type(MultipartBuilder.FORM); + for (Entry param : formParams.entrySet()) { + if (param.getValue() instanceof File) { + File file = (File) param.getValue(); + Headers partHeaders = Headers.of("Content-Disposition", "form-data; name=\"" + param.getKey() + "\"; filename=\"" + file.getName() + "\""); + MediaType mediaType = MediaType.parse(guessContentTypeFromFile(file)); + mpBuilder.addPart(partHeaders, RequestBody.create(mediaType, file)); + } else { + Headers partHeaders = Headers.of("Content-Disposition", "form-data; name=\"" + param.getKey() + "\""); + mpBuilder.addPart(partHeaders, RequestBody.create(null, parameterToString(param.getValue()))); + } + } + return mpBuilder.build(); + } + + /** + * Guess Content-Type header from the given file (defaults to "application/octet-stream"). + * + * @param file The given file + * @return The guessed Content-Type + */ + public String guessContentTypeFromFile(File file) { + String contentType = URLConnection.guessContentTypeFromName(file.getName()); + if (contentType == null) { + return "application/octet-stream"; + } else { + return contentType; + } + } + + /** + * Apply SSL related settings to httpClient according to the current values of + * verifyingSsl and sslCaCert. + */ + private void applySslSettings() { + try { + TrustManager[] trustManagers = null; + HostnameVerifier hostnameVerifier = null; + if (!verifyingSsl) { + TrustManager trustAll = new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {} + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {} + @Override + public X509Certificate[] getAcceptedIssuers() { return null; } + }; + SSLContext sslContext = SSLContext.getInstance("TLS"); + trustManagers = new TrustManager[]{ trustAll }; + hostnameVerifier = new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { return true; } + }; + } else if (sslCaCert != null) { + char[] password = null; // Any password will work. + CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); + Collection certificates = certificateFactory.generateCertificates(sslCaCert); + if (certificates.isEmpty()) { + throw new IllegalArgumentException("expected non-empty set of trusted certificates"); + } + KeyStore caKeyStore = newEmptyKeyStore(password); + int index = 0; + for (Certificate certificate : certificates) { + String certificateAlias = "ca" + Integer.toString(index++); + caKeyStore.setCertificateEntry(certificateAlias, certificate); + } + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + trustManagerFactory.init(caKeyStore); + trustManagers = trustManagerFactory.getTrustManagers(); + } + + if (keyManagers != null || trustManagers != null) { + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(keyManagers, trustManagers, new SecureRandom()); + httpClient.setSslSocketFactory(sslContext.getSocketFactory()); + } else { + httpClient.setSslSocketFactory(null); + } + httpClient.setHostnameVerifier(hostnameVerifier); + } catch (GeneralSecurityException e) { + throw new RuntimeException(e); + } + } + + private KeyStore newEmptyKeyStore(char[] password) throws GeneralSecurityException { + try { + KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + keyStore.load(null, password); + return keyStore; + } catch (IOException e) { + throw new AssertionError(e); + } + } +} diff --git a/libraries/okhttp-gson/ApiResponse.mustache b/libraries/okhttp-gson/ApiResponse.mustache new file mode 100644 index 00000000000..3909393697c --- /dev/null +++ b/libraries/okhttp-gson/ApiResponse.mustache @@ -0,0 +1,48 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import java.util.List; +import java.util.Map; + +/** + * API response returned by API call. + * + * @param The type of data that is deserialized from response body + */ +public class ApiResponse { + final private int statusCode; + final private Map> headers; + final private T data; + + /** + * @param statusCode The status code of HTTP response + * @param headers The headers of HTTP response + */ + public ApiResponse(int statusCode, Map> headers) { + this(statusCode, headers, null); + } + + /** + * @param statusCode The status code of HTTP response + * @param headers The headers of HTTP response + * @param data The object deserialized from response bod + */ + public ApiResponse(int statusCode, Map> headers, T data) { + this.statusCode = statusCode; + this.headers = headers; + this.data = data; + } + + public int getStatusCode() { + return statusCode; + } + + public Map> getHeaders() { + return headers; + } + + public T getData() { + return data; + } +} diff --git a/libraries/okhttp-gson/GzipRequestInterceptor.mustache b/libraries/okhttp-gson/GzipRequestInterceptor.mustache new file mode 100644 index 00000000000..23224cf5d5b --- /dev/null +++ b/libraries/okhttp-gson/GzipRequestInterceptor.mustache @@ -0,0 +1,70 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import com.squareup.okhttp.*; +import okio.Buffer; +import okio.BufferedSink; +import okio.GzipSink; +import okio.Okio; + +import java.io.IOException; + +/** + * Encodes request bodies using gzip. + * + * Taken from https://github.com/square/okhttp/issues/350 + */ +class GzipRequestInterceptor implements Interceptor { + @Override public Response intercept(Chain chain) throws IOException { + Request originalRequest = chain.request(); + if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) { + return chain.proceed(originalRequest); + } + + Request compressedRequest = originalRequest.newBuilder() + .header("Content-Encoding", "gzip") + .method(originalRequest.method(), forceContentLength(gzip(originalRequest.body()))) + .build(); + return chain.proceed(compressedRequest); + } + + private RequestBody forceContentLength(final RequestBody requestBody) throws IOException { + final Buffer buffer = new Buffer(); + requestBody.writeTo(buffer); + return new RequestBody() { + @Override + public MediaType contentType() { + return requestBody.contentType(); + } + + @Override + public long contentLength() { + return buffer.size(); + } + + @Override + public void writeTo(BufferedSink sink) throws IOException { + sink.write(buffer.snapshot()); + } + }; + } + + private RequestBody gzip(final RequestBody body) { + return new RequestBody() { + @Override public MediaType contentType() { + return body.contentType(); + } + + @Override public long contentLength() { + return -1; // We don't know the compressed length in advance! + } + + @Override public void writeTo(BufferedSink sink) throws IOException { + BufferedSink gzipSink = Okio.buffer(new GzipSink(sink)); + body.writeTo(gzipSink); + gzipSink.close(); + } + }; + } +} \ No newline at end of file diff --git a/libraries/okhttp-gson/ProgressRequestBody.mustache b/libraries/okhttp-gson/ProgressRequestBody.mustache new file mode 100644 index 00000000000..0f15c1f415d --- /dev/null +++ b/libraries/okhttp-gson/ProgressRequestBody.mustache @@ -0,0 +1,66 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import com.squareup.okhttp.MediaType; +import com.squareup.okhttp.RequestBody; + +import java.io.IOException; + +import okio.Buffer; +import okio.BufferedSink; +import okio.ForwardingSink; +import okio.Okio; +import okio.Sink; + +public class ProgressRequestBody extends RequestBody { + + public interface ProgressRequestListener { + void onRequestProgress(long bytesWritten, long contentLength, boolean done); + } + + private final RequestBody requestBody; + + private final ProgressRequestListener progressListener; + + public ProgressRequestBody(RequestBody requestBody, ProgressRequestListener progressListener) { + this.requestBody = requestBody; + this.progressListener = progressListener; + } + + @Override + public MediaType contentType() { + return requestBody.contentType(); + } + + @Override + public long contentLength() throws IOException { + return requestBody.contentLength(); + } + + @Override + public void writeTo(BufferedSink sink) throws IOException { + BufferedSink bufferedSink = Okio.buffer(sink(sink)); + requestBody.writeTo(bufferedSink); + bufferedSink.flush(); + } + + private Sink sink(Sink sink) { + return new ForwardingSink(sink) { + + long bytesWritten = 0L; + long contentLength = 0L; + + @Override + public void write(Buffer source, long byteCount) throws IOException { + super.write(source, byteCount); + if (contentLength == 0) { + contentLength = contentLength(); + } + + bytesWritten += byteCount; + progressListener.onRequestProgress(bytesWritten, contentLength, bytesWritten == contentLength); + } + }; + } +} diff --git a/libraries/okhttp-gson/ProgressResponseBody.mustache b/libraries/okhttp-gson/ProgressResponseBody.mustache new file mode 100644 index 00000000000..3f53133697c --- /dev/null +++ b/libraries/okhttp-gson/ProgressResponseBody.mustache @@ -0,0 +1,65 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import com.squareup.okhttp.MediaType; +import com.squareup.okhttp.ResponseBody; + +import java.io.IOException; + +import okio.Buffer; +import okio.BufferedSource; +import okio.ForwardingSource; +import okio.Okio; +import okio.Source; + +public class ProgressResponseBody extends ResponseBody { + + public interface ProgressListener { + void update(long bytesRead, long contentLength, boolean done); + } + + private final ResponseBody responseBody; + private final ProgressListener progressListener; + private BufferedSource bufferedSource; + + public ProgressResponseBody(ResponseBody responseBody, ProgressListener progressListener) { + this.responseBody = responseBody; + this.progressListener = progressListener; + } + + @Override + public MediaType contentType() { + return responseBody.contentType(); + } + + @Override + public long contentLength() throws IOException { + return responseBody.contentLength(); + } + + @Override + public BufferedSource source() throws IOException { + if (bufferedSource == null) { + bufferedSource = Okio.buffer(source(responseBody.source())); + } + return bufferedSource; + } + + private Source source(Source source) { + return new ForwardingSource(source) { + long totalBytesRead = 0L; + + @Override + public long read(Buffer sink, long byteCount) throws IOException { + long bytesRead = super.read(sink, byteCount); + // read() returns the number of bytes read, or -1 if this source is exhausted. + totalBytesRead += bytesRead != -1 ? bytesRead : 0; + progressListener.update(totalBytesRead, responseBody.contentLength(), bytesRead == -1); + return bytesRead; + } + }; + } +} + + diff --git a/libraries/okhttp-gson/api.mustache b/libraries/okhttp-gson/api.mustache new file mode 100644 index 00000000000..ffc68bc7b5a --- /dev/null +++ b/libraries/okhttp-gson/api.mustache @@ -0,0 +1,268 @@ +{{>licenseInfo}} + +package {{package}}; + +import {{invokerPackage}}.ApiCallback; +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.ApiResponse; +import {{invokerPackage}}.Configuration; +import {{invokerPackage}}.Pair; +import {{invokerPackage}}.ProgressRequestBody; +import {{invokerPackage}}.ProgressResponseBody; +{{#performBeanValidation}} +import {{invokerPackage}}.BeanValidationException; +{{/performBeanValidation}} + +import com.google.gson.reflect.TypeToken; + +import java.io.IOException; + +{{#useBeanValidation}} +import javax.validation.constraints.*; +{{/useBeanValidation}} +{{#performBeanValidation}} +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.ValidatorFactory; +import javax.validation.executable.ExecutableValidator; +import java.util.Set; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +{{/performBeanValidation}} + +{{#imports}}import {{import}}; +{{/imports}} + +import java.lang.reflect.Type; +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +{{#operations}} +public class {{classname}} { + private ApiClient {{localVariablePrefix}}apiClient; + + public {{classname}}() { + this(Configuration.getDefaultApiClient()); + } + + public {{classname}}(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + public ApiClient getApiClient() { + return {{localVariablePrefix}}apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + {{#operation}} + /** + * Build call for {{operationId}}{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + * @param progressListener Progress listener + * @param progressRequestListener Progress request listener + * @return Call to execute + * @throws ApiException If fail to serialize the request body object + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public com.squareup.okhttp.Call {{operationId}}Call({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ProgressResponseBody.ProgressListener progressListener, final ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException { + Object {{localVariablePrefix}}localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + + // create path and map variables + String {{localVariablePrefix}}localVarPath = "{{{path}}}"{{#pathParams}} + .replaceAll("\\{" + "{{baseName}}" + "\\}", {{localVariablePrefix}}apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; + + {{javaUtilPrefix}}List {{localVariablePrefix}}localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}List {{localVariablePrefix}}localVarCollectionQueryParams = new {{javaUtilPrefix}}ArrayList();{{#queryParams}} + if ({{paramName}} != null) + {{localVariablePrefix}}{{#collectionFormat}}localVarCollectionQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPairs("{{{collectionFormat}}}", {{/collectionFormat}}{{^collectionFormat}}localVarQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPair({{/collectionFormat}}"{{baseName}}", {{paramName}}));{{/queryParams}} + + {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarHeaderParams = new {{javaUtilPrefix}}HashMap();{{#headerParams}} + if ({{paramName}} != null) + {{localVariablePrefix}}localVarHeaderParams.put("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}}));{{/headerParams}} + + {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarFormParams = new {{javaUtilPrefix}}HashMap();{{#formParams}} + if ({{paramName}} != null) + {{localVariablePrefix}}localVarFormParams.put("{{baseName}}", {{paramName}});{{/formParams}} + + final String[] {{localVariablePrefix}}localVarAccepts = { + {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} + }; + final String {{localVariablePrefix}}localVarAccept = {{localVariablePrefix}}apiClient.selectHeaderAccept({{localVariablePrefix}}localVarAccepts); + if ({{localVariablePrefix}}localVarAccept != null) {{localVariablePrefix}}localVarHeaderParams.put("Accept", {{localVariablePrefix}}localVarAccept); + + final String[] {{localVariablePrefix}}localVarContentTypes = { + {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} + }; + final String {{localVariablePrefix}}localVarContentType = {{localVariablePrefix}}apiClient.selectHeaderContentType({{localVariablePrefix}}localVarContentTypes); + {{localVariablePrefix}}localVarHeaderParams.put("Content-Type", {{localVariablePrefix}}localVarContentType); + + if(progressListener != null) { + apiClient.getHttpClient().networkInterceptors().add(new com.squareup.okhttp.Interceptor() { + @Override + public com.squareup.okhttp.Response intercept(com.squareup.okhttp.Interceptor.Chain chain) throws IOException { + com.squareup.okhttp.Response originalResponse = chain.proceed(chain.request()); + return originalResponse.newBuilder() + .body(new ProgressResponseBody(originalResponse.body(), progressListener)) + .build(); + } + }); + } + + String[] {{localVariablePrefix}}localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + return {{localVariablePrefix}}apiClient.buildCall({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarCollectionQueryParams, {{localVariablePrefix}}localVarPostBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAuthNames, progressRequestListener); + } + + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + @SuppressWarnings("rawtypes") + private com.squareup.okhttp.Call {{operationId}}ValidateBeforeCall({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ProgressResponseBody.ProgressListener progressListener, final ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException { + {{^performBeanValidation}} + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new ApiException("Missing the required parameter '{{paramName}}' when calling {{operationId}}(Async)"); + } + {{/required}}{{/allParams}} + + com.squareup.okhttp.Call {{localVariablePrefix}}call = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}progressListener, progressRequestListener); + return {{localVariablePrefix}}call; + + {{/performBeanValidation}} + {{#performBeanValidation}} + try { + ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); + ExecutableValidator executableValidator = factory.getValidator().forExecutables(); + + Object[] parameterValues = { {{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}} }; + Method method = this.getClass().getMethod("{{operationId}}WithHttpInfo"{{#allParams}}, {{#isListContainer}}java.util.List{{/isListContainer}}{{#isMapContainer}}java.util.Map{{/isMapContainer}}{{^isListContainer}}{{^isMapContainer}}{{{dataType}}}{{/isMapContainer}}{{/isListContainer}}.class{{/allParams}}); + Set> violations = executableValidator.validateParameters(this, method, + parameterValues); + + if (violations.size() == 0) { + com.squareup.okhttp.Call {{localVariablePrefix}}call = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}progressListener, progressRequestListener); + return {{localVariablePrefix}}call; + + } else { + throw new BeanValidationException((Set) violations); + } + } catch (NoSuchMethodException e) { + e.printStackTrace(); + throw new ApiException(e.getMessage()); + } catch (SecurityException e) { + e.printStackTrace(); + throw new ApiException(e.getMessage()); + } + + {{/performBeanValidation}} + } + + /** + * {{summary}} + * {{notes}}{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}}{{#returnType}} + * @return {{returnType}}{{/returnType}} + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + {{#returnType}}ApiResponse<{{{returnType}}}> {{localVariablePrefix}}resp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + return {{localVariablePrefix}}resp.getData();{{/returnType}} + } + + /** + * {{summary}} + * {{notes}}{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + * @return ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + com.squareup.okhttp.Call {{localVariablePrefix}}call = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}null, null); + {{#returnType}}Type {{localVariablePrefix}}localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType(); + return {{localVariablePrefix}}apiClient.execute({{localVariablePrefix}}call, {{localVariablePrefix}}localVarReturnType);{{/returnType}}{{^returnType}}return {{localVariablePrefix}}apiClient.execute({{localVariablePrefix}}call);{{/returnType}} + } + + /** + * {{summary}} (asynchronously) + * {{notes}}{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + * @param callback The callback to be executed when the API call finishes + * @return The request call + * @throws ApiException If fail to process the API call, e.g. serializing the request body object + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public com.squareup.okhttp.Call {{operationId}}Async({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ApiCallback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{localVariablePrefix}}callback) throws ApiException { + + ProgressResponseBody.ProgressListener progressListener = null; + ProgressRequestBody.ProgressRequestListener progressRequestListener = null; + + if (callback != null) { + progressListener = new ProgressResponseBody.ProgressListener() { + @Override + public void update(long bytesRead, long contentLength, boolean done) { + callback.onDownloadProgress(bytesRead, contentLength, done); + } + }; + + progressRequestListener = new ProgressRequestBody.ProgressRequestListener() { + @Override + public void onRequestProgress(long bytesWritten, long contentLength, boolean done) { + callback.onUploadProgress(bytesWritten, contentLength, done); + } + }; + } + + com.squareup.okhttp.Call {{localVariablePrefix}}call = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}progressListener, progressRequestListener); + {{#returnType}}Type {{localVariablePrefix}}localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType(); + {{localVariablePrefix}}apiClient.executeAsync({{localVariablePrefix}}call, {{localVariablePrefix}}localVarReturnType, {{localVariablePrefix}}callback);{{/returnType}}{{^returnType}}{{localVariablePrefix}}apiClient.executeAsync({{localVariablePrefix}}call, {{localVariablePrefix}}callback);{{/returnType}} + return {{localVariablePrefix}}call; + } + {{/operation}} +} +{{/operations}} \ No newline at end of file diff --git a/libraries/okhttp-gson/auth/HttpBasicAuth.mustache b/libraries/okhttp-gson/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..320903b0319 --- /dev/null +++ b/libraries/okhttp-gson/auth/HttpBasicAuth.mustache @@ -0,0 +1,43 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; + +import com.squareup.okhttp.Credentials; + +import java.util.Map; +import java.util.List; + +import java.io.UnsupportedEncodingException; + +public class HttpBasicAuth implements Authentication { + private String username; + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public void applyToParams(List queryParams, Map headerParams) { + if (username == null && password == null) { + return; + } + headerParams.put("Authorization", Credentials.basic( + username == null ? "" : username, + password == null ? "" : password)); + } +} diff --git a/libraries/okhttp-gson/build.gradle.mustache b/libraries/okhttp-gson/build.gradle.mustache new file mode 100644 index 00000000000..27fe1caaf25 --- /dev/null +++ b/libraries/okhttp-gson/build.gradle.mustache @@ -0,0 +1,115 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + } + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + sourceCompatibility = JavaVersion.VERSION_{{^java8}}1_7{{/java8}}{{#java8}}1_8{{/java8}} + targetCompatibility = JavaVersion.VERSION_{{^java8}}1_7{{/java8}}{{#java8}}1_8{{/java8}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +dependencies { + compile 'io.swagger:swagger-annotations:1.5.17' + compile 'com.squareup.okhttp:okhttp:2.7.5' + compile 'com.squareup.okhttp:logging-interceptor:2.7.5' + compile 'com.google.code.gson:gson:2.8.1' + compile 'io.gsonfire:gson-fire:1.8.0' + {{#joda}} + compile 'joda-time:joda-time:2.9.9' + {{/joda}} + {{#threetenbp}} + compile 'org.threeten:threetenbp:1.3.5' + {{/threetenbp}} + testCompile 'junit:junit:4.12' +} diff --git a/libraries/okhttp-gson/build.sbt.mustache b/libraries/okhttp-gson/build.sbt.mustache new file mode 100644 index 00000000000..fcf788885d6 --- /dev/null +++ b/libraries/okhttp-gson/build.sbt.mustache @@ -0,0 +1,26 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "io.swagger" % "swagger-annotations" % "1.5.17", + "com.squareup.okhttp" % "okhttp" % "2.7.5", + "com.squareup.okhttp" % "logging-interceptor" % "2.7.5", + "com.google.code.gson" % "gson" % "2.8.1", + {{#joda}} + "joda-time" % "joda-time" % "2.9.9" % "compile", + {{/joda}} + {{#threetenbp}} + "org.threeten" % "threetenbp" % "1.3.5" % "compile", + {{/threetenbp}} + "io.gsonfire" % "gson-fire" % "1.8.0" % "compile", + "junit" % "junit" % "4.12" % "test", + "com.novocode" % "junit-interface" % "0.10" % "test" + ) + ) diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache new file mode 100644 index 00000000000..b5119774a05 --- /dev/null +++ b/libraries/okhttp-gson/pom.mustache @@ -0,0 +1,287 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{artifactUrl}} + {{artifactDescription}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-core-version} + + + com.squareup.okhttp + okhttp + ${okhttp-version} + + + com.squareup.okhttp + logging-interceptor + ${okhttp-version} + + + com.google.code.gson + gson + ${gson-version} + + + io.gsonfire + gson-fire + ${gson-fire-version} + + {{#joda}} + + joda-time + joda-time + ${jodatime-version} + + {{/joda}} + {{#threetenbp}} + + org.threeten + threetenbp + ${threetenbp-version} + + {{/threetenbp}} + {{#useBeanValidation}} + + + javax.validation + validation-api + 1.1.0.Final + provided + + {{/useBeanValidation}} + {{#performBeanValidation}} + + + org.hibernate + hibernate-validator + 5.4.1.Final + + + javax.el + el-api + 2.2 + + {{/performBeanValidation}} + {{#parcelableModel}} + + + com.google.android + android + 4.1.1.4 + provided + + {{/parcelableModel}} + + + junit + junit + ${junit-version} + test + + + + {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}} + ${java.version} + ${java.version} + 1.8.0 + 1.5.18 + 2.7.5 + 2.8.1 + {{#joda}} + 2.9.9 + {{/joda}} + {{#threetenbp}} + 1.3.5 + {{/threetenbp}} + 1.0.0 + 4.12 + UTF-8 + + diff --git a/libraries/rest-assured/ApiClient.mustache b/libraries/rest-assured/ApiClient.mustache new file mode 100644 index 00000000000..2b269854872 --- /dev/null +++ b/libraries/rest-assured/ApiClient.mustache @@ -0,0 +1,59 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import {{apiPackage}}.*; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import io.restassured.RestAssured; +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.builder.ResponseSpecBuilder; +import io.restassured.response.Response; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; +{{/fullJavaUtil}} + +public class ApiClient { + + private final Config config; + + private ApiClient(Config config) { + this.config = config; + } + + public static ApiClient api(Config config) { + return new ApiClient(config); + } + + {{#apiInfo}} + {{#apis}} + public {{classname}} {{classVarName}}() { + return {{classname}}.{{classVarName}}(config.baseReqSpec.get()); + } + {{/apis}} + {{/apiInfo}} + + public static class Config { + private Supplier baseReqSpec; + + /** + * Use common specification for all operations + */ + public Config reqSpecSupplier(Supplier supplier) { + this.baseReqSpec = supplier; + return this; + } + + public static Config apiConfig() { + return new Config(); + } + } +} \ No newline at end of file diff --git a/libraries/rest-assured/GsonObjectMapper.mustache b/libraries/rest-assured/GsonObjectMapper.mustache new file mode 100644 index 00000000000..320d8141f95 --- /dev/null +++ b/libraries/rest-assured/GsonObjectMapper.mustache @@ -0,0 +1,30 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import io.restassured.mapper.ObjectMapper; +import io.restassured.mapper.ObjectMapperDeserializationContext; +import io.restassured.mapper.ObjectMapperSerializationContext; + +public class GsonObjectMapper implements ObjectMapper { + + private JSON json; + + private GsonObjectMapper() { + this.json = new JSON(); + } + + public static GsonObjectMapper gson() { + return new GsonObjectMapper(); + } + + @Override + public Object deserialize(ObjectMapperDeserializationContext context) { + return json.deserialize(context.getDataToDeserialize().asString(), context.getType()); + } + + @Override + public Object serialize(ObjectMapperSerializationContext context) { + return json.serialize(context.getObjectToSerialize()); + } +} \ No newline at end of file diff --git a/libraries/rest-assured/README.mustache b/libraries/rest-assured/README.mustache new file mode 100644 index 00000000000..56560172ee3 --- /dev/null +++ b/libraries/rest-assured/README.mustache @@ -0,0 +1,43 @@ +# {{artifactId}} + +## Requirements + +Building the API client library requires [Maven](https://maven.apache.org/) to be installed. + +## Installation & Usage + +To install the API client library to your local Maven repository, simply execute: + +```shell +mvn install +``` + +To deploy it to a remote Maven repository instead, configure the settings of the repository and execute: + +```shell +mvn deploy +``` + +Refer to the [official documentation](https://maven.apache.org/plugins/maven-deploy-plugin/usage.html) for more information. + +After the client library is installed/deployed, you can use it in your Maven project by adding the following to your *pom.xml*: + +```xml + + {{groupId}} + {{artifactId}} + {{artifactVersion}} + compile + + +``` + +## Recommendation + +It's recommended to create an instance of `ApiClient` per thread in a multithreaded environment to avoid any potential issues. + +## Author + +{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} +{{/hasMore}}{{/apis}}{{/apiInfo}} + diff --git a/libraries/rest-assured/ResponseSpecBuilders.mustache b/libraries/rest-assured/ResponseSpecBuilders.mustache new file mode 100644 index 00000000000..af7e7ac960f --- /dev/null +++ b/libraries/rest-assured/ResponseSpecBuilders.mustache @@ -0,0 +1,31 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import io.restassured.builder.ResponseSpecBuilder; +import io.restassured.response.Response; +import io.restassured.specification.ResponseSpecification; + +import java.util.function.Function; + +public class ResponseSpecBuilders { + + private ResponseSpecBuilders() { + } + + public static Function validatedWith(ResponseSpecification respSpec) { + return response -> response.then().spec(respSpec).extract().response(); + } + + public static Function validatedWith(ResponseSpecBuilder respSpec) { + return validatedWith(respSpec.build()); + } + + /** + * @param code expected status code + * @return ResponseSpecBuilder + */ + public static ResponseSpecBuilder shouldBeCode(int code) { + return new ResponseSpecBuilder().expectStatusCode(code); + } +} \ No newline at end of file diff --git a/libraries/rest-assured/api.mustache b/libraries/rest-assured/api.mustache new file mode 100644 index 00000000000..1d1a5d9ae54 --- /dev/null +++ b/libraries/rest-assured/api.mustache @@ -0,0 +1,243 @@ +{{>licenseInfo}} + +package {{package}}; + +import com.google.gson.reflect.TypeToken; +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import io.restassured.RestAssured; +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.builder.ResponseSpecBuilder; +import io.restassured.response.Response; + +import java.lang.reflect.Type; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; +{{/fullJavaUtil}} +import {{invokerPackage}}.JSON; + +import static io.restassured.http.Method.*; + +public class {{classname}} { + + private RequestSpecBuilder reqSpec; + + private JSON json; + + private {{classname}}(RequestSpecBuilder reqSpec) { + this.reqSpec = reqSpec; + this.json = new JSON(); + } + + public static {{classname}} {{classVarName}}(RequestSpecBuilder reqSpec) { + return new {{classname}}(reqSpec); + } + +{{#operations}} +{{#operation}} + + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{operationIdCamelCase}}Oper {{operationId}}() { + return new {{operationIdCamelCase}}Oper(reqSpec); + } +{{/operation}} +{{/operations}} + + /** + * Get JSON + * + * @return JSON object + */ + public JSON getJSON() { + return json; + } + + /** + * Set JSON + * + * @param json JSON object + * @return {{classname}} + */ + public {{classname}} setJSON(JSON json) { + this.json = json; + return this; + } + + /** + * Customise request specification + */ + public {{classname}} reqSpec(Consumer consumer) { + consumer.accept(reqSpec); + return this; + } + + {{#operations}} + {{#operation}} + /** + * {{summary}} + * {{notes}} + * + {{#allParams}} + * @see #{{#isPathParam}}{{paramName}}Path{{/isPathParam}}{{#isQueryParam}}{{paramName}}Query{{/isQueryParam}}{{#isFormParam}}{{^isFile}}{{paramName}}Form{{/isFile}}{{#isFile}}{{paramName}}MultiPart{{/isFile}}{{/isFormParam}}{{#isHeaderParam}}{{paramName}}Header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} + {{#returnType}} + * return {{{returnType}}} + {{/returnType}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public class {{operationIdCamelCase}}Oper { + + public static final String REQ_URI = "{{path}}"; + + private RequestSpecBuilder reqSpec; + + private ResponseSpecBuilder respSpec; + + public {{operationIdCamelCase}}Oper() { + this.reqSpec = new RequestSpecBuilder(); + {{#vendorExtensions}} + {{#x-contentType}} + reqSpec.setContentType("{{x-contentType}}"); + {{/x-contentType}} + {{#x-accepts}} + reqSpec.setAccept("{{x-accepts}}"); + {{/x-accepts}} + {{/vendorExtensions}} + this.respSpec = new ResponseSpecBuilder(); + } + + public {{operationIdCamelCase}}Oper(RequestSpecBuilder reqSpec) { + this.reqSpec = reqSpec; + {{#vendorExtensions}} + {{#x-contentType}} + reqSpec.setContentType("{{x-contentType}}"); + {{/x-contentType}} + {{#x-accepts}} + reqSpec.setAccept("{{x-accepts}}"); + {{/x-accepts}} + {{/vendorExtensions}} + this.respSpec = new ResponseSpecBuilder(); + } + + /** + * {{httpMethod}} {{path}} + */ + public T execute(Function handler) { + return handler.apply(RestAssured.given().spec(reqSpec.build()).expect().spec(respSpec.build()).when().request({{httpMethod}}, REQ_URI)); + } + {{#returnType}} + + /** + * {{httpMethod}} {{path}} + * @return {{{returnType}}} + */ + public {{{returnType}}} executeAs(Function handler) { + Type type = new TypeToken<{{{returnType}}}>(){}.getType(); + return getJSON().deserialize(execute(handler).asString(), type); + } + {{/returnType}} + {{#bodyParams}} + + /** + * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + */ + public {{operationIdCamelCase}}Oper body({{{dataType}}} {{paramName}}) { + reqSpec.setBody(getJSON().serialize({{paramName}})); + return this; + } + {{/bodyParams}} + {{#headerParams}} + + /** + * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + */ + public {{operationIdCamelCase}}Oper {{paramName}}Header(String {{paramName}}) { + reqSpec.addHeader("{{baseName}}", {{paramName}}); + return this; + } + {{/headerParams}} + {{#pathParams}} + + /** + * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + */ + public {{operationIdCamelCase}}Oper {{paramName}}Path(Object {{paramName}}) { + reqSpec.addPathParam("{{baseName}}", {{paramName}}); + return this; + } + {{/pathParams}} + {{#queryParams}} + + /** + * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + */ + public {{operationIdCamelCase}}Oper {{paramName}}Query(Object... {{paramName}}) { + reqSpec.addQueryParam("{{baseName}}", {{paramName}}); + return this; + } + {{/queryParams}} + {{#formParams}} + {{^isFile}} + + /** + * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + */ + public {{operationIdCamelCase}}Oper {{paramName}}Form(Object... {{paramName}}) { + reqSpec.addFormParam("{{baseName}}", {{paramName}}); + return this; + } + {{/isFile}} + {{/formParams}} + {{#formParams}} + {{#isFile}} + + /** + * It will assume that the control name is file and the is + * @see #reqSpec for customise + * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + */ + public {{operationIdCamelCase}}Oper {{paramName}}MultiPart({{{dataType}}} {{paramName}}) { + reqSpec.addMultiPart({{paramName}}); + return this; + } + {{/isFile}} + {{/formParams}} + + /** + * Customise request specification + */ + public {{operationIdCamelCase}}Oper reqSpec(Consumer consumer) { + consumer.accept(reqSpec); + return this; + } + + /** + * Customise response specification + */ + public {{operationIdCamelCase}}Oper respSpec(Consumer consumer) { + consumer.accept(respSpec); + return this; + } + } +{{/operation}} +{{/operations}} +} \ No newline at end of file diff --git a/libraries/rest-assured/api_doc.mustache b/libraries/rest-assured/api_doc.mustache new file mode 100644 index 00000000000..c8bf20319e7 --- /dev/null +++ b/libraries/rest-assured/api_doc.mustache @@ -0,0 +1,62 @@ +# {{classname}}{{#description}} +{{description}}{{/description}} + +All URIs are relative to *{{basePath}}* + +Method | HTTP request | Description +------------- | ------------- | ------------- +{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}} + +{{#operations}} +{{#operation}} + +# **{{operationId}}** +> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) + +{{summary}}{{#notes}} + +{{notes}}{{/notes}} + +### Example +```java +// Import classes: +//import {{invokerPackage}}.ApiClient; +//import io.restassured.builder.RequestSpecBuilder; +//import io.restassured.filter.log.ErrorLoggingFilter; + +{{classname}} api = ApiClient.api(ApiClient.Config.apiConfig().withReqSpecSupplier( + () -> new RequestSpecBuilder() + .setBaseUri("{{basePath}}"))).{{classVarName}}(); + +api.{{operationId}}(){{#allParams}}{{#required}}{{#isPathParam}} + .{{paramName}}Path({{paramName}}){{/isPathParam}}{{#isQueryParam}} + .{{paramName}}Query({{paramName}}){{/isQueryParam}}{{#isFormParam}}{{^isFile}} + .{{paramName}}Form({{paramName}}){{/isFile}}{{/isFormParam}}{{#isFormParam}}{{#isFile}} + .{{paramName}}MultiPart({{paramName}}){{/isFile}}{{/isFormParam}}{{#isHeaderParam}} + .{{paramName}}Header({{paramName}}){{/isHeaderParam}}{{#isBodyParam}} + .body({{paramName}}){{/isBodyParam}}{{/required}}{{/allParams}}.execute(r -> r.prettyPeek()); +``` + +### Parameters +{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} +Name | Type | Description | Notes +------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} +{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} +{{/allParams}} + +### Return type + +{{#returnType}}{{#returnTypeIsPrimitive}}**{{returnType}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{returnType}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}null (empty response body){{/returnType}} + +### Authorization + +{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{name}}](../README.md#{{name}}){{^-last}}, {{/-last}}{{/authMethods}} + +### HTTP request headers + + - **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} + - **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} + +{{/operation}} +{{/operations}} diff --git a/libraries/rest-assured/api_test.mustache b/libraries/rest-assured/api_test.mustache new file mode 100644 index 00000000000..5c17db415e3 --- /dev/null +++ b/libraries/rest-assured/api_test.mustache @@ -0,0 +1,65 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} +import {{invokerPackage}}.ApiClient; +import {{apiPackage}}.{{classname}}; +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.filter.log.ErrorLoggingFilter; +import org.junit.Before; +import org.junit.Test; +import org.junit.Ignore; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} +import static io.restassured.config.ObjectMapperConfig.objectMapperConfig; +import static io.restassured.config.RestAssuredConfig.config; +import static {{invokerPackage}}.GsonObjectMapper.gson; + +/** + * API tests for {{classname}} + */ +@Ignore +public class {{classname}}Test { + + private {{classname}} api; + + @Before + public void createApi() { + api = ApiClient.api(ApiClient.Config.apiConfig().reqSpecSupplier( + () -> new RequestSpecBuilder().setConfig(config().objectMapperConfig(objectMapperConfig().defaultObjectMapper(gson()))) + .addFilter(new ErrorLoggingFilter()) + .setBaseUri("{{{basePath}}}"))).{{classVarName}}(); + } +{{#operations}} +{{#operation}} + + {{#responses}} + /** + * {{message}} + */ + @Test + public void shouldSee{{code}}After{{operationIdCamelCase}}() { + {{#allParams}} + {{#isHeaderParam}}String {{paramName}} = null;{{/isHeaderParam}}{{^isHeaderParam}}{{{dataType}}} {{paramName}} = null;{{/isHeaderParam}} + {{/allParams}} + api.{{operationId}}(){{#allParams}}{{#required}}{{#isPathParam}} + .{{paramName}}Path({{paramName}}){{/isPathParam}}{{#isQueryParam}} + .{{paramName}}Query({{paramName}}){{/isQueryParam}}{{#isFormParam}}{{^isFile}} + .{{paramName}}Form({{paramName}}){{/isFile}}{{/isFormParam}}{{#isFormParam}}{{#isFile}} + .{{paramName}}MultiPart({{paramName}}){{/isFile}}{{/isFormParam}}{{#isHeaderParam}} + .{{paramName}}Header({{paramName}}){{/isHeaderParam}}{{#isBodyParam}} + .body({{paramName}}){{/isBodyParam}}{{/required}}{{/allParams}}.execute(r -> r.prettyPeek()); + // TODO: test validations + } + + {{/responses}} +{{/operation}} +{{/operations}} +} \ No newline at end of file diff --git a/libraries/rest-assured/build.gradle.mustache b/libraries/rest-assured/build.gradle.mustache new file mode 100644 index 00000000000..fc67b62d13e --- /dev/null +++ b/libraries/rest-assured/build.gradle.mustache @@ -0,0 +1,124 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.5.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 23 + buildToolsVersion '23.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 22 + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + swagger_annotations_version = "1.5.15" + rest_assured_version = "3.0.6" + junit_version = "4.12" + gson_version = "2.6.1" + gson_fire_version = "1.8.2" +{{#joda}} + jodatime_version = "2.9.9" +{{/joda}} +{{#threetenbp}} + threetenbp_version = "1.3.5" +{{/threetenbp}} + okio_version = "1.13.0" +} + +dependencies { + compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "io.rest-assured:scala-support:$rest_assured_version" + compile "io.gsonfire:gson-fire:$gson_fire_version" +{{#joda}} + compile "joda-time:joda-time:$jodatime_version" + compile 'com.google.code.gson:gson:$gson_version' +{{/joda}} +{{#threetenbp}} + compile "org.threeten:threetenbp:$threetenbp_version" +{{/threetenbp}} + compile "com.squareup.okio:okio:$okio_version" + testCompile "junit:junit:$junit_version" +} diff --git a/libraries/rest-assured/build.sbt.mustache b/libraries/rest-assured/build.sbt.mustache new file mode 100644 index 00000000000..289345c3a0a --- /dev/null +++ b/libraries/rest-assured/build.sbt.mustache @@ -0,0 +1,26 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "io.swagger" % "swagger-annotations" % "1.5.15", + "io.rest-assured" % "scala-support" % "3.0.6", + "com.google.code.gson" % "gson" % "2.6.1", + "io.gsonfire" % "gson-fire" % "1.8.2" % "compile", +{{#joda}} + "joda-time" % "joda-time" % "2.9.9" % "compile", +{{/joda}} +{{#threetenbp}} + "org.threeten" % "threetenbp" % "1.3.5" % "compile", +{{/threetenbp}} + "com.squareup.okio" % "okio" % "1.13.0" % "compile", + "junit" % "junit" % "4.12" % "test", + "com.novocode" % "junit-interface" % "0.10" % "test" + ) + ) diff --git a/libraries/rest-assured/pom.mustache b/libraries/rest-assured/pom.mustache new file mode 100644 index 00000000000..80f043340c2 --- /dev/null +++ b/libraries/rest-assured/pom.mustache @@ -0,0 +1,262 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{artifactUrl}} + {{artifactDescription}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add_sources + generate-sources + + add-source + + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-core-version} + + + io.rest-assured + rest-assured + ${rest-assured.version} + + + com.google.code.gson + gson + ${gson-version} + + {{#joda}} + + joda-time + joda-time + ${jodatime-version} + + {{/joda}} + {{#threetenbp}} + + org.threeten + threetenbp + ${threetenbp-version} + + {{/threetenbp}} + + io.gsonfire + gson-fire + ${gson-fire-version} + + + com.squareup.okio + okio + ${okio-version} + + + + junit + junit + ${junit-version} + test + + + + UTF-8 + 1.5.15 + 3.0.6 + 2.6.1 + 1.8.2 + 1.0.0 + {{#joda}} + 2.9.9 + {{/joda}} + {{#threetenbp}} + 1.3.5 + {{/threetenbp}} + 1.13.0 + 4.12 + + diff --git a/libraries/resteasy/ApiClient.mustache b/libraries/resteasy/ApiClient.mustache new file mode 100644 index 00000000000..a8b3ca6f5b8 --- /dev/null +++ b/libraries/resteasy/ApiClient.mustache @@ -0,0 +1,693 @@ +package {{invokerPackage}}; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.file.Files; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TimeZone; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.Form; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.jboss.logging.Logger; +import org.jboss.resteasy.client.jaxrs.internal.ClientConfiguration; +import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput; +import org.jboss.resteasy.spi.ResteasyProviderFactory; + +import {{invokerPackage}}.auth.Authentication; +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.OAuth; + +{{>generatedAnnotation}} +public class ApiClient { + private Map defaultHeaderMap = new HashMap(); + private String basePath = "{{{basePath}}}"; + private boolean debugging = false; + + private Client httpClient; + private JSON json; + private String tempFolderPath = null; + + private Map authentications; + + private int statusCode; + private Map> responseHeaders; + + private DateFormat dateFormat; + + public ApiClient() { + json = new JSON(); + httpClient = buildHttpClient(debugging); + + this.dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + + // Use UTC as the default time zone. + this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + + this.json.setDateFormat((DateFormat) dateFormat.clone()); + + // Set default User-Agent. + setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}Swagger-Codegen/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap();{{#authMethods}}{{#isBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + } + + /** + * Gets the JSON instance to do JSON serialization and deserialization. + */ + public JSON getJSON() { + return json; + } + + public Client getHttpClient() { + return httpClient; + } + + public ApiClient setHttpClient(Client httpClient) { + this.httpClient = httpClient; + return this; + } + + public String getBasePath() { + return basePath; + } + + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Gets the status code of the previous request + */ + public int getStatusCode() { + return statusCode; + } + + /** + * Gets the response headers of the previous request + */ + public Map> getResponseHeaders() { + return responseHeaders; + } + + /** + * Get authentications (key: authentication name, value: authentication). + */ + public Map getAuthentications() { + return authentications; + } + + /** + * Get authentication for the given name. + * + * @param authName The authentication name + * @return The authentication, null if not found + */ + public Authentication getAuthentication(String authName) { + return authentications.get(authName); + } + + /** + * Helper method to set username for the first HTTP basic authentication. + */ + public void setUsername(String username) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setUsername(username); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set password for the first HTTP basic authentication. + */ + public void setPassword(String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setPassword(password); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set API key value for the first API key authentication. + */ + public void setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + */ + public void setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set access token for the first OAuth2 authentication. + */ + public void setAccessToken(String accessToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setAccessToken(accessToken); + return; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Set the User-Agent header's value (by adding to the default header map). + */ + public ApiClient setUserAgent(String userAgent) { + addDefaultHeader("User-Agent", userAgent); + return this; + } + + /** + * Add a default header. + * + * @param key The header's key + * @param value The header's value + */ + public ApiClient addDefaultHeader(String key, String value) { + defaultHeaderMap.put(key, value); + return this; + } + + /** + * Check that whether debugging is enabled for this API client. + */ + public boolean isDebugging() { + return debugging; + } + + /** + * Enable/disable debugging for this API client. + * + * @param debugging To enable (true) or disable (false) debugging + */ + public ApiClient setDebugging(boolean debugging) { + this.debugging = debugging; + // Rebuild HTTP Client according to the new "debugging" value. + this.httpClient = buildHttpClient(debugging); + return this; + } + + /** + * The path of temporary folder used to store downloaded files from endpoints + * with file response. The default value is null, i.e. using + * the system's default tempopary folder. + * + * @see https://docs.oracle.com/javase/7/docs/api/java/io/File.html#createTempFile(java.lang.String,%20java.lang.String,%20java.io.File) + */ + public String getTempFolderPath() { + return tempFolderPath; + } + + public ApiClient setTempFolderPath(String tempFolderPath) { + this.tempFolderPath = tempFolderPath; + return this; + } + + /** + * Get the date format used to parse/format date parameters. + */ + public DateFormat getDateFormat() { + return dateFormat; + } + + /** + * Set the date format used to parse/format date parameters. + */ + public ApiClient setDateFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + // also set the date format for model (de)serialization with Date properties + this.json.setDateFormat((DateFormat) dateFormat.clone()); + return this; + } + + /** + * Parse the given string into Date object. + */ + public Date parseDate(String str) { + try { + return dateFormat.parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(e); + } + } + + /** + * Format the given Date object into string. + */ + public String formatDate(Date date) { + return dateFormat.format(date); + } + + /** + * Format the given parameter object into string. + */ + public String parameterToString(Object param) { + if (param == null) { + return ""; + } else if (param instanceof Date) { + return formatDate((Date) param); + } else if (param instanceof Collection) { + StringBuilder b = new StringBuilder(); + for(Object o : (Collection)param) { + if(b.length() > 0) { + b.append(","); + } + b.append(String.valueOf(o)); + } + return b.toString(); + } else { + return String.valueOf(param); + } + } + + /* + Format to {@code Pair} objects. + */ + public List parameterToPairs(String collectionFormat, String name, Object value){ + List params = new ArrayList(); + + // preconditions + if (name == null || name.isEmpty() || value == null) return params; + + Collection valueCollection = null; + if (value instanceof Collection) { + valueCollection = (Collection) value; + } else { + params.add(new Pair(name, parameterToString(value))); + return params; + } + + if (valueCollection.isEmpty()){ + return params; + } + + // get the collection format + collectionFormat = (collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat); // default: csv + + // create the params based on the collection format + if (collectionFormat.equals("multi")) { + for (Object item : valueCollection) { + params.add(new Pair(name, parameterToString(item))); + } + + return params; + } + + String delimiter = ","; + + if (collectionFormat.equals("csv")) { + delimiter = ","; + } else if (collectionFormat.equals("ssv")) { + delimiter = " "; + } else if (collectionFormat.equals("tsv")) { + delimiter = "\t"; + } else if (collectionFormat.equals("pipes")) { + delimiter = "|"; + } + + StringBuilder sb = new StringBuilder() ; + for (Object item : valueCollection) { + sb.append(delimiter); + sb.append(parameterToString(item)); + } + + params.add(new Pair(name, sb.substring(1))); + + return params; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * application/vnd.company+json + * @param mime MIME (Multipurpose Internet Mail Extensions) + * @return True if the given MIME is JSON, false otherwise. + */ + public boolean isJsonMime(String mime) { + String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$"; + return mime != null && (mime.matches(jsonMime) || mime.equals("*/*")); + } + + /** + * Select the Accept header's value from the given accepts array: + * if JSON exists in the given array, use it; + * otherwise use all of them (joining into a string) + * + * @param accepts The accepts array to select from + * @return The Accept header to use. If the given array is empty, + * null will be returned (not to set the Accept header explicitly). + */ + public String selectHeaderAccept(String[] accepts) { + if (accepts.length == 0) { + return null; + } + for (String accept : accepts) { + if (isJsonMime(accept)) { + return accept; + } + } + return StringUtil.join(accepts, ","); + } + + /** + * Select the Content-Type header's value from the given array: + * if JSON exists in the given array, use it; + * otherwise use the first one of the array. + * + * @param contentTypes The Content-Type array to select from + * @return The Content-Type header to use. If the given array is empty, + * JSON will be used. + */ + public String selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0) { + return "application/json"; + } + for (String contentType : contentTypes) { + if (isJsonMime(contentType)) { + return contentType; + } + } + return contentTypes[0]; + } + + /** + * Escape the given string to be used as URL query value. + */ + public String escapeString(String str) { + try { + return URLEncoder.encode(str, "utf8").replaceAll("\\+", "%20"); + } catch (UnsupportedEncodingException e) { + return str; + } + } + + /** + * Serialize the given Java object into string entity according the given + * Content-Type (only JSON is supported for now). + */ + public Entity serialize(Object obj, Map formParams, String contentType) throws ApiException { + Entity entity = null; + if (contentType.startsWith("multipart/form-data")) { + MultipartFormDataOutput multipart = new MultipartFormDataOutput(); + //MultiPart multiPart = new MultiPart(); + for (Entry param: formParams.entrySet()) { + if (param.getValue() instanceof File) { + File file = (File) param.getValue(); + try { + multipart.addFormData(param.getValue().toString(),new FileInputStream(file),MediaType.APPLICATION_OCTET_STREAM_TYPE); + } catch (FileNotFoundException e) { + throw new ApiException("Could not serialize multipart/form-data "+e.getMessage()); + } + } else { + multipart.addFormData(param.getValue().toString(),param.getValue().toString(),MediaType.APPLICATION_OCTET_STREAM_TYPE); + } + } + entity = Entity.entity(multipart.getFormData(), MediaType.MULTIPART_FORM_DATA_TYPE); + } else if (contentType.startsWith("application/x-www-form-urlencoded")) { + Form form = new Form(); + for (Entry param: formParams.entrySet()) { + form.param(param.getKey(), parameterToString(param.getValue())); + } + entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE); + } else { + // We let jersey handle the serialization + entity = Entity.entity(obj, contentType); + } + return entity; + } + + /** + * Deserialize response body to Java object according to the Content-Type. + */ + public T deserialize(Response response, GenericType returnType) throws ApiException { + if (response == null || returnType == null) { + return null; + } + + if ("byte[]".equals(returnType.toString())) { + // Handle binary response (byte array). + return (T) response.readEntity(byte[].class); + } else if (returnType.equals(File.class)) { + // Handle file downloading. + @SuppressWarnings("unchecked") + T file = (T) downloadFileFromResponse(response); + return file; + } + + String contentType = null; + List contentTypes = response.getHeaders().get("Content-Type"); + if (contentTypes != null && !contentTypes.isEmpty()) + contentType = String.valueOf(contentTypes.get(0)); + if (contentType == null) + throw new ApiException(500, "missing Content-Type in response"); + + return response.readEntity(returnType); + } + + /** + * Download file from the given response. + * @throws ApiException If fail to read file content from response and write to disk + */ + public File downloadFileFromResponse(Response response) throws ApiException { + try { + File file = prepareDownloadFile(response); +{{^supportJava6}} + Files.copy(response.readEntity(InputStream.class), file.toPath()); +{{/supportJava6}} +{{#supportJava6}} + // Java6 falls back to commons.io for file copying + FileUtils.copyToFile(response.readEntity(InputStream.class), file); +{{/supportJava6}} + return file; + } catch (IOException e) { + throw new ApiException(e); + } + } + + public File prepareDownloadFile(Response response) throws IOException { + String filename = null; + String contentDisposition = (String) response.getHeaders().getFirst("Content-Disposition"); + if (contentDisposition != null && !"".equals(contentDisposition)) { + // Get filename from the Content-Disposition header. + Pattern pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?"); + Matcher matcher = pattern.matcher(contentDisposition); + if (matcher.find()) + filename = matcher.group(1); + } + + String prefix = null; + String suffix = null; + if (filename == null) { + prefix = "download-"; + suffix = ""; + } else { + int pos = filename.lastIndexOf("."); + if (pos == -1) { + prefix = filename + "-"; + } else { + prefix = filename.substring(0, pos) + "-"; + suffix = filename.substring(pos); + } + // File.createTempFile requires the prefix to be at least three characters long + if (prefix.length() < 3) + prefix = "download-"; + } + + if (tempFolderPath == null) + return File.createTempFile(prefix, suffix); + else + return File.createTempFile(prefix, suffix, new File(tempFolderPath)); + } + + /** + * Invoke API by sending HTTP request with the given options. + * + * @param path The sub-path of the HTTP URL + * @param method The request method, one of "GET", "POST", "PUT", "HEAD" and "DELETE" + * @param queryParams The query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param formParams The form parameters + * @param accept The request's Accept header + * @param contentType The request's Content-Type header + * @param authNames The authentications to apply + * @param returnType The return type into which to deserialize the response + * @return The response body in type of string + */ + public T invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { + updateParamsForAuth(authNames, queryParams, headerParams); + + // Not using `.target(this.basePath).path(path)` below, + // to support (constant) query string in `path`, e.g. "/posts?draft=1" + WebTarget target = httpClient.target(this.basePath + path); + + if (queryParams != null) { + for (Pair queryParam : queryParams) { + if (queryParam.getValue() != null) { + target = target.queryParam(queryParam.getName(), queryParam.getValue()); + } + } + } + + Invocation.Builder invocationBuilder = target.request().accept(accept); + + for (Entry headerParamsEnrty : headerParams.entrySet()) { + String value = headerParamsEnrty.getValue(); + if (value != null) { + invocationBuilder = invocationBuilder.header(headerParamsEnrty.getKey(), value); + } + } + + for (Entry defaultHeaderEnrty: defaultHeaderMap.entrySet()) { + if (!headerParams.containsKey(defaultHeaderEnrty.getKey())) { + String value = defaultHeaderEnrty.getKey(); + if (value != null) { + invocationBuilder = invocationBuilder.header(defaultHeaderEnrty.getKey(), value); + } + } + } + + Entity entity = serialize(body, formParams, contentType); + + Response response = null; + + if ("GET".equals(method)) { + response = invocationBuilder.get(); + } else if ("POST".equals(method)) { + response = invocationBuilder.post(entity); + } else if ("PUT".equals(method)) { + response = invocationBuilder.put(entity); + } else if ("DELETE".equals(method)) { + response = invocationBuilder.delete(); + } else if ("PATCH".equals(method)) { + response = invocationBuilder.header("X-HTTP-Method-Override", "PATCH").post(entity); + } else if ("HEAD".equals(method)) { + response = invocationBuilder.head(); + } else { + throw new ApiException(500, "unknown method type " + method); + } + + statusCode = response.getStatusInfo().getStatusCode(); + responseHeaders = buildResponseHeaders(response); + + if (response.getStatus() == Status.NO_CONTENT.getStatusCode()) { + return null; + } else if (response.getStatusInfo().getFamily().equals(Status.Family.SUCCESSFUL)) { + if (returnType == null) + return null; + else + return deserialize(response, returnType); + } else { + String message = "error"; + String respBody = null; + if (response.hasEntity()) { + try { + respBody = String.valueOf(response.readEntity(String.class)); + message = respBody; + } catch (RuntimeException e) { + // e.printStackTrace(); + } + } + throw new ApiException( + response.getStatus(), + message, + buildResponseHeaders(response), + respBody); + } + } + + /** + * Build the Client used to make HTTP requests. + */ + private Client buildHttpClient(boolean debugging) { + final ClientConfiguration clientConfig = new ClientConfiguration(ResteasyProviderFactory.getInstance()); + clientConfig.register(json); + if(debugging){ + clientConfig.register(Logger.class); + } + return ClientBuilder.newClient(clientConfig); + } + private Map> buildResponseHeaders(Response response) { + Map> responseHeaders = new HashMap>(); + for (Entry> entry: response.getHeaders().entrySet()) { + List values = entry.getValue(); + List headers = new ArrayList(); + for (Object o : values) { + headers.add(String.valueOf(o)); + } + responseHeaders.put(entry.getKey(), headers); + } + return responseHeaders; + } + + /** + * Update query and header parameters based on authentication settings. + * + * @param authNames The authentications to apply + */ + private void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams) { + for (String authName : authNames) { + Authentication auth = authentications.get(authName); + if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + auth.applyToParams(queryParams, headerParams); + } + } +} diff --git a/libraries/resteasy/JSON.mustache b/libraries/resteasy/JSON.mustache new file mode 100644 index 00000000000..27d2aa65d23 --- /dev/null +++ b/libraries/resteasy/JSON.mustache @@ -0,0 +1,48 @@ +package {{invokerPackage}}; + +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.*; +{{#java8}} +import com.fasterxml.jackson.datatype.jsr310.*; +{{/java8}} +{{^java8}} +import com.fasterxml.jackson.datatype.joda.*; +{{/java8}} + +import java.text.DateFormat; + +import javax.ws.rs.ext.ContextResolver; + +{{>generatedAnnotation}} +public class JSON implements ContextResolver { + private ObjectMapper mapper; + + public JSON() { + mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.setDateFormat(new RFC3339DateFormat()); + {{#java8}} + mapper.registerModule(new JavaTimeModule()); + {{/java8}} + {{^java8}} + mapper.registerModule(new JodaModule()); + {{/java8}} + } + + /** + * Set the date format for JSON (de)serialization with Date properties. + */ + public void setDateFormat(DateFormat dateFormat) { + mapper.setDateFormat(dateFormat); + } + + @Override + public ObjectMapper getContext(Class type) { + return mapper; + } +} diff --git a/libraries/resteasy/api.mustache b/libraries/resteasy/api.mustache new file mode 100644 index 00000000000..f3fd01ed61b --- /dev/null +++ b/libraries/resteasy/api.mustache @@ -0,0 +1,109 @@ +package {{package}}; + +import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.Configuration; +import {{invokerPackage}}.Pair; + +import javax.ws.rs.core.GenericType; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}} { + private ApiClient {{localVariablePrefix}}apiClient; + + public {{classname}}() { + this(Configuration.getDefaultApiClient()); + } + + public {{classname}}(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + public ApiClient getApiClient() { + return {{localVariablePrefix}}apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + {{#operation}} + /** + * {{summary}} + * {{notes}}{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}}{{#returnType}} + * @return {{{returnType}}}{{/returnType}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + Object {{localVariablePrefix}}localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + } + {{/required}}{{/allParams}} + // create path and map variables + String {{localVariablePrefix}}localVarPath = "{{{path}}}".replaceAll("\\{format\\}","json"){{#pathParams}} + .replaceAll("\\{" + "{{baseName}}" + "\\}", {{localVariablePrefix}}apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; + + // query params + {{javaUtilPrefix}}List {{localVariablePrefix}}localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarFormParams = new {{javaUtilPrefix}}HashMap(); + + {{#queryParams}} + {{localVariablePrefix}}localVarQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); + {{/queryParams}} + + {{#headerParams}}if ({{paramName}} != null) + {{localVariablePrefix}}localVarHeaderParams.put("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}})); + {{/headerParams}} + + {{#formParams}}if ({{paramName}} != null) + {{localVariablePrefix}}localVarFormParams.put("{{baseName}}", {{paramName}}); + {{/formParams}} + + final String[] {{localVariablePrefix}}localVarAccepts = { + {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} + }; + final String {{localVariablePrefix}}localVarAccept = {{localVariablePrefix}}apiClient.selectHeaderAccept({{localVariablePrefix}}localVarAccepts); + + final String[] {{localVariablePrefix}}localVarContentTypes = { + {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} + }; + final String {{localVariablePrefix}}localVarContentType = {{localVariablePrefix}}apiClient.selectHeaderContentType({{localVariablePrefix}}localVarContentTypes); + + String[] {{localVariablePrefix}}localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + + {{#returnType}} + GenericType<{{{returnType}}}> {{localVariablePrefix}}localVarReturnType = new GenericType<{{{returnType}}}>() {}; + return {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarPostBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccept, {{localVariablePrefix}}localVarContentType, {{localVariablePrefix}}localVarAuthNames, {{localVariablePrefix}}localVarReturnType); + {{/returnType}}{{^returnType}} + {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarPostBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccept, {{localVariablePrefix}}localVarContentType, {{localVariablePrefix}}localVarAuthNames, null); + {{/returnType}} + } + {{/operation}} +} +{{/operations}} diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache new file mode 100644 index 00000000000..fc42da3e68c --- /dev/null +++ b/libraries/resteasy/build.gradle.mustache @@ -0,0 +1,147 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.5.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 23 + buildToolsVersion '23.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 23 + } + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + {{#java8}} + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + {{/java8}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + swagger_annotations_version = "1.5.8" + jackson_version = "2.6.4" + jersey_version = "2.22.2" + resteasy_version = "3.1.3.Final" + {{^java8}} + jodatime_version = "2.9.4" + {{/java8}} + {{#supportJava6}} + commons_io_version=2.5 + commons_lang3_version=3.5 + {{/supportJava6}} + junit_version = "4.12" +} + +dependencies { + compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "org.jboss.resteasy:resteasy-client:$resteasy_version" + compile "org.jboss.resteasy:resteasy-multipart-provider:$resteasy_version" + compile "org.jboss.resteasy:resteasy-jackson2-provider:$resteasy_version" + compile "org.glassfish.jersey.core:jersey-client:$jersey_version" + compile "org.glassfish.jersey.media:jersey-media-multipart:$jersey_version" + compile "org.glassfish.jersey.media:jersey-media-json-jackson:$jersey_version" + compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_version" + {{#java8}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{/java8}} + {{^java8}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + compile "joda-time:joda-time:$jodatime_version" + compile "com.brsanthu:migbase64:2.2" + {{/java8}} + {{#supportJava6}} + compile "commons-io:commons-io:$commons_io_version" + compile "org.apache.commons:commons-lang3:$commons_lang3_version" + {{/supportJava6}} + testCompile "junit:junit:$junit_version" +} diff --git a/libraries/resteasy/build.sbt.mustache b/libraries/resteasy/build.sbt.mustache new file mode 100644 index 00000000000..348d29d96d1 --- /dev/null +++ b/libraries/resteasy/build.sbt.mustache @@ -0,0 +1,34 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "io.swagger" % "swagger-annotations" % "1.5.8", + "org.glassfish.jersey.core" % "jersey-client" % "2.22.2", + "org.glassfish.jersey.media" % "jersey-media-multipart" % "2.22.2", + "org.glassfish.jersey.media" % "jersey-media-json-jackson" % "2.22.2", + "com.fasterxml.jackson.core" % "jackson-core" % "2.7.5", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.7.5", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.7.5", + {{#java8}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.7.5", + {{/java8}} + {{^java8}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.7.5", + "joda-time" % "joda-time" % "2.9.4", + "com.brsanthu" % "migbase64" % "2.2", + {{/java8}} + {{#supportJava6}} + "org.apache.commons" % "commons-lang3" % "3.5", + "commons-io" % "commons-io" % "2.5", + {{/supportJava6}} + "junit" % "junit" % "4.12" % "test", + "com.novocode" % "junit-interface" % "0.10" % "test" + ) + ) diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache new file mode 100644 index 00000000000..2b4a9aa5537 --- /dev/null +++ b/libraries/resteasy/pom.mustache @@ -0,0 +1,263 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + + scm:git:git@github.com:swagger-api/swagger-mustache.git + scm:git:git@github.com:swagger-api/swagger-codegen.git + https://github.com/swagger-api/swagger-codegen + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.6 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.5.1 + + {{#java8}} + + 1.8 + 1.8 + {{/java8}} + {{^java8}} + + 1.7 + 1.7 + {{/java8}} + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + + + + + io.swagger + swagger-annotations + ${swagger-core-version} + + + + org.jboss.resteasy + resteasy-client + ${resteasy-version} + + + org.jboss.resteasy + resteasy-multipart-provider + ${resteasy-version} + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-version} + + {{#withXml}} + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson-version} + + + {{/withXml}} + {{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{/java8}} + {{^java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + + joda-time + joda-time + ${jodatime-version} + + + + + com.brsanthu + migbase64 + 2.2 + + {{/java8}} + + {{#supportJava6}} + + org.apache.commons + commons-lang3 + ${commons_lang3_version} + + + + commons-io + commons-io + ${commons_io_version} + + {{/supportJava6}} + + org.jboss.resteasy + resteasy-jackson2-provider + 3.1.3.Final + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${jackson-version} + + + + junit + junit + ${junit-version} + test + + + + UTF-8 + 1.5.18 + 3.1.3.Final + 2.6.4 + {{^java8}} + 2.9.9 + {{/java8}} + {{#supportJava6}} + 2.5 + 3.6 + {{/supportJava6}} + 1.0.0 + 4.12 + + diff --git a/libraries/resttemplate/ApiClient.mustache b/libraries/resttemplate/ApiClient.mustache new file mode 100644 index 00000000000..54f2b14573b --- /dev/null +++ b/libraries/resttemplate/ApiClient.mustache @@ -0,0 +1,678 @@ +package {{invokerPackage}}; + +{{#withXml}} +import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; +{{/withXml}} +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpRequest; +import org.springframework.http.HttpStatus; +import org.springframework.http.InvalidMediaTypeException; +import org.springframework.http.MediaType; +import org.springframework.http.RequestEntity; +import org.springframework.http.RequestEntity.BodyBuilder; +import org.springframework.http.ResponseEntity; +import org.springframework.http.client.BufferingClientHttpRequestFactory; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.http.client.ClientHttpResponse; +{{#withXml}} +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter; +{{/withXml}} +import org.springframework.stereotype.Component; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.util.StringUtils; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; +{{#threetenbp}} +import org.threeten.bp.*; +import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter; +import com.fasterxml.jackson.databind.ObjectMapper; +{{/threetenbp}} + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; +import java.text.DateFormat; +import java.text.ParseException; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TimeZone; + +import {{invokerPackage}}.auth.Authentication; +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.OAuth; + +{{>generatedAnnotation}} +@Component("{{invokerPackage}}.ApiClient") +public class ApiClient { + public enum CollectionFormat { + CSV(","), TSV("\t"), SSV(" "), PIPES("|"), MULTI(null); + + private final String separator; + private CollectionFormat(String separator) { + this.separator = separator; + } + + private String collectionToString(Collection collection) { + return StringUtils.collectionToDelimitedString(collection, separator); + } + } + + private boolean debugging = false; + + private HttpHeaders defaultHeaders = new HttpHeaders(); + + private String basePath = "{{basePath}}"; + + private RestTemplate restTemplate; + + private Map authentications; + + private HttpStatus statusCode; + private MultiValueMap responseHeaders; + + private DateFormat dateFormat; + + public ApiClient() { + this.restTemplate = buildRestTemplate(); + init(); + } + + @Autowired + public ApiClient(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + init(); + } + + protected void init() { + // Use RFC3339 format for date and datetime. + // See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14 + this.dateFormat = new RFC3339DateFormat(); + + // Use UTC as the default time zone. + this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + + // Set default User-Agent. + setUserAgent("Java-SDK"); + + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap();{{#authMethods}}{{#isBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + } + + /** + * Get the current base path + * @return String the base path + */ + public String getBasePath() { + return basePath; + } + + /** + * Set the base path, which should include the host + * @param basePath the base path + * @return ApiClient this client + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Gets the status code of the previous request + * @return HttpStatus the status code + */ + public HttpStatus getStatusCode() { + return statusCode; + } + + /** + * Gets the response headers of the previous request + * @return MultiValueMap a map of response headers + */ + public MultiValueMap getResponseHeaders() { + return responseHeaders; + } + + /** + * Get authentications (key: authentication name, value: authentication). + * @return Map the currently configured authentication types + */ + public Map getAuthentications() { + return authentications; + } + + /** + * Get authentication for the given name. + * + * @param authName The authentication name + * @return The authentication, null if not found + */ + public Authentication getAuthentication(String authName) { + return authentications.get(authName); + } + + /** + * Helper method to set username for the first HTTP basic authentication. + * @param username the username + */ + public void setUsername(String username) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setUsername(username); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set password for the first HTTP basic authentication. + * @param password the password + */ + public void setPassword(String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setPassword(password); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set API key value for the first API key authentication. + * @param apiKey the API key + */ + public void setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + * @param apiKeyPrefix the API key prefix + */ + public void setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set access token for the first OAuth2 authentication. + * @param accessToken the access token + */ + public void setAccessToken(String accessToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setAccessToken(accessToken); + return; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Set the User-Agent header's value (by adding to the default header map). + * @param userAgent the user agent string + * @return ApiClient this client + */ + public ApiClient setUserAgent(String userAgent) { + addDefaultHeader("User-Agent", userAgent); + return this; + } + + /** + * Add a default header. + * + * @param name The header's name + * @param value The header's value + * @return ApiClient this client + */ + public ApiClient addDefaultHeader(String name, String value) { + if (defaultHeaders.containsKey(name)) { + defaultHeaders.remove(name); + } + defaultHeaders.add(name, value); + return this; + } + + public void setDebugging(boolean debugging) { + List currentInterceptors = this.restTemplate.getInterceptors(); + if(debugging) { + if (currentInterceptors == null) { + currentInterceptors = new ArrayList(); + } + ClientHttpRequestInterceptor interceptor = new ApiClientHttpRequestInterceptor(); + currentInterceptors.add(interceptor); + this.restTemplate.setInterceptors(currentInterceptors); + } else { + if (currentInterceptors != null && !currentInterceptors.isEmpty()) { + Iterator iter = currentInterceptors.iterator(); + while (iter.hasNext()) { + ClientHttpRequestInterceptor interceptor = iter.next(); + if (interceptor instanceof ApiClientHttpRequestInterceptor) { + iter.remove(); + } + } + this.restTemplate.setInterceptors(currentInterceptors); + } + } + this.debugging = debugging; + } + + /** + * Check that whether debugging is enabled for this API client. + * @return boolean true if this client is enabled for debugging, false otherwise + */ + public boolean isDebugging() { + return debugging; + } + + /** + * Get the date format used to parse/format date parameters. + * @return DateFormat format + */ + public DateFormat getDateFormat() { + return dateFormat; + } + + /** + * Set the date format used to parse/format date parameters. + * @param dateFormat Date format + * @return API client + */ + public ApiClient setDateFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + {{#threetenbp}} + for(HttpMessageConverter converter:restTemplate.getMessageConverters()){ + if(converter instanceof AbstractJackson2HttpMessageConverter){ + ObjectMapper mapper = ((AbstractJackson2HttpMessageConverter)converter).getObjectMapper(); + mapper.setDateFormat(dateFormat); + } + } + {{/threetenbp}} + return this; + } + + /** + * Parse the given string into Date object. + */ + public Date parseDate(String str) { + try { + return dateFormat.parse(str); + } catch (ParseException e) { + throw new RuntimeException(e); + } + } + + /** + * Format the given Date object into string. + */ + public String formatDate(Date date) { + return dateFormat.format(date); + } + + /** + * Format the given parameter object into string. + * @param param the object to convert + * @return String the parameter represented as a String + */ + public String parameterToString(Object param) { + if (param == null) { + return ""; + } else if (param instanceof Date) { + return formatDate( (Date) param); + } else if (param instanceof Collection) { + StringBuilder b = new StringBuilder(); + for(Object o : (Collection) param) { + if(b.length() > 0) { + b.append(","); + } + b.append(String.valueOf(o)); + } + return b.toString(); + } else { + return String.valueOf(param); + } + } + + /** + * Converts a parameter to a {@link MultiValueMap} for use in REST requests + * @param collectionFormat The format to convert to + * @param name The name of the parameter + * @param value The parameter's value + * @return a Map containing the String value(s) of the input parameter + */ + public MultiValueMap parameterToMultiValueMap(CollectionFormat collectionFormat, String name, Object value) { + final MultiValueMap params = new LinkedMultiValueMap(); + + if (name == null || name.isEmpty() || value == null) { + return params; + } + + if(collectionFormat == null) { + collectionFormat = CollectionFormat.CSV; + } + + Collection valueCollection = null; + if (value instanceof Collection) { + valueCollection = (Collection) value; + } else { + params.add(name, parameterToString(value)); + return params; + } + + if (valueCollection.isEmpty()){ + return params; + } + + if (collectionFormat.equals(CollectionFormat.MULTI)) { + for (Object item : valueCollection) { + params.add(name, parameterToString(item)); + } + return params; + } + + List values = new ArrayList(); + for(Object o : valueCollection) { + values.add(parameterToString(o)); + } + params.add(name, collectionFormat.collectionToString(values)); + + return params; + } + + /** + * Check if the given {@code String} is a JSON MIME. + * @param mediaType the input MediaType + * @return boolean true if the MediaType represents JSON, false otherwise + */ + public boolean isJsonMime(String mediaType) { + // "* / *" is default to JSON + if ("*/*".equals(mediaType)) { + return true; + } + + try { + return isJsonMime(MediaType.parseMediaType(mediaType)); + } catch (InvalidMediaTypeException e) { + } + return false; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * @param mediaType the input MediaType + * @return boolean true if the MediaType represents JSON, false otherwise + */ + public boolean isJsonMime(MediaType mediaType) { + return mediaType != null && (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType) || mediaType.getSubtype().matches("^.*\\+json[;]?\\s*$")); + } + + /** + * Select the Accept header's value from the given accepts array: + * if JSON exists in the given array, use it; + * otherwise use all of them (joining into a string) + * + * @param accepts The accepts array to select from + * @return List The list of MediaTypes to use for the Accept header + */ + public List selectHeaderAccept(String[] accepts) { + if (accepts.length == 0) { + return null; + } + for (String accept : accepts) { + MediaType mediaType = MediaType.parseMediaType(accept); + if (isJsonMime(mediaType)) { + return Collections.singletonList(mediaType); + } + } + return MediaType.parseMediaTypes(StringUtils.arrayToCommaDelimitedString(accepts)); + } + + /** + * Select the Content-Type header's value from the given array: + * if JSON exists in the given array, use it; + * otherwise use the first one of the array. + * + * @param contentTypes The Content-Type array to select from + * @return MediaType The Content-Type header to use. If the given array is empty, JSON will be used. + */ + public MediaType selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0) { + return MediaType.APPLICATION_JSON; + } + for (String contentType : contentTypes) { + MediaType mediaType = MediaType.parseMediaType(contentType); + if (isJsonMime(mediaType)) { + return mediaType; + } + } + return MediaType.parseMediaType(contentTypes[0]); + } + + /** + * Select the body to use for the request + * @param obj the body object + * @param formParams the form parameters + * @param contentType the content type of the request + * @return Object the selected body + */ + protected Object selectBody(Object obj, MultiValueMap formParams, MediaType contentType) { + boolean isForm = MediaType.MULTIPART_FORM_DATA.isCompatibleWith(contentType) || MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(contentType); + return isForm ? formParams : obj; + } + + /** + * Invoke API by sending HTTP request with the given options. + * + * @param the return type to use + * @param path The sub-path of the HTTP URL + * @param method The request method + * @param queryParams The query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param formParams The form parameters + * @param accept The request's Accept header + * @param contentType The request's Content-Type header + * @param authNames The authentications to apply + * @param returnType The return type into which to deserialize the response + * @return The response body in chosen type + */ + public T invokeAPI(String path, HttpMethod method, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { + updateParamsForAuth(authNames, queryParams, headerParams); + + final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(path); + if (queryParams != null) { + builder.queryParams(queryParams); + } + + final BodyBuilder requestBuilder = RequestEntity.method(method, builder.build().toUri()); + if(accept != null) { + requestBuilder.accept(accept.toArray(new MediaType[accept.size()])); + } + if(contentType != null) { + requestBuilder.contentType(contentType); + } + + addHeadersToRequest(headerParams, requestBuilder); + addHeadersToRequest(defaultHeaders, requestBuilder); + + RequestEntity requestEntity = requestBuilder.body(selectBody(body, formParams, contentType)); + + ResponseEntity responseEntity = restTemplate.exchange(requestEntity, returnType); + + statusCode = responseEntity.getStatusCode(); + responseHeaders = responseEntity.getHeaders(); + + if (responseEntity.getStatusCode() == HttpStatus.NO_CONTENT) { + return null; + } else if (responseEntity.getStatusCode().is2xxSuccessful()) { + if (returnType == null) { + return null; + } + return responseEntity.getBody(); + } else { + // The error handler built into the RestTemplate should handle 400 and 500 series errors. + throw new RestClientException("API returned " + statusCode + " and it wasn't handled by the RestTemplate error handler"); + } + } + + /** + * Add headers to the request that is being built + * @param headers The headers to add + * @param requestBuilder The current request + */ + protected void addHeadersToRequest(HttpHeaders headers, BodyBuilder requestBuilder) { + for (Entry> entry : headers.entrySet()) { + List values = entry.getValue(); + for(String value : values) { + if (value != null) { + requestBuilder.header(entry.getKey(), value); + } + } + } + } + + /** + * Build the RestTemplate used to make HTTP requests. + * @return RestTemplate + */ + protected RestTemplate buildRestTemplate() { + {{#withXml}}List> messageConverters = new ArrayList>(); + messageConverters.add(new MappingJackson2HttpMessageConverter()); + XmlMapper xmlMapper = new XmlMapper(); + xmlMapper.configure(ToXmlGenerator.Feature.WRITE_XML_DECLARATION, true); + messageConverters.add(new MappingJackson2XmlHttpMessageConverter(xmlMapper)); + + RestTemplate restTemplate = new RestTemplate(messageConverters); + {{/withXml}}{{^withXml}}RestTemplate restTemplate = new RestTemplate();{{/withXml}} + {{#threetenbp}} + for(HttpMessageConverter converter:restTemplate.getMessageConverters()){ + if(converter instanceof AbstractJackson2HttpMessageConverter){ + ObjectMapper mapper = ((AbstractJackson2HttpMessageConverter)converter).getObjectMapper(); + ThreeTenModule module = new ThreeTenModule(); + module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); + module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); + module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); + mapper.registerModule(module); + } + } + {{/threetenbp}} + // This allows us to read the response more than once - Necessary for debugging. + restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(restTemplate.getRequestFactory())); + return restTemplate; + } + + /** + * Update query and header parameters based on authentication settings. + * + * @param authNames The authentications to apply + * @param queryParams The query parameters + * @param headerParams The header parameters + */ + private void updateParamsForAuth(String[] authNames, MultiValueMap queryParams, HttpHeaders headerParams) { + for (String authName : authNames) { + Authentication auth = authentications.get(authName); + if (auth == null) { + throw new RestClientException("Authentication undefined: " + authName); + } + auth.applyToParams(queryParams, headerParams); + } + } + + private class ApiClientHttpRequestInterceptor implements ClientHttpRequestInterceptor { + private final Log log = LogFactory.getLog(ApiClientHttpRequestInterceptor.class); + + @Override + public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { + logRequest(request, body); + ClientHttpResponse response = execution.execute(request, body); + logResponse(response); + return response; + } + + private void logRequest(HttpRequest request, byte[] body) throws UnsupportedEncodingException { + log.info("URI: " + request.getURI()); + log.info("HTTP Method: " + request.getMethod()); + log.info("HTTP Headers: " + headersToString(request.getHeaders())); + log.info("Request Body: " + new String(body, StandardCharsets.UTF_8)); + } + + private void logResponse(ClientHttpResponse response) throws IOException { + log.info("HTTP Status Code: " + response.getRawStatusCode()); + log.info("Status Text: " + response.getStatusText()); + log.info("HTTP Headers: " + headersToString(response.getHeaders())); + log.info("Response Body: " + bodyToString(response.getBody())); + } + + private String headersToString(HttpHeaders headers) { + StringBuilder builder = new StringBuilder(); + for(Entry> entry : headers.entrySet()) { + builder.append(entry.getKey()).append("=["); + for(String value : entry.getValue()) { + builder.append(value).append(","); + } + builder.setLength(builder.length() - 1); // Get rid of trailing comma + builder.append("],"); + } + builder.setLength(builder.length() - 1); // Get rid of trailing comma + return builder.toString(); + } + + private String bodyToString(InputStream body) throws IOException { + StringBuilder builder = new StringBuilder(); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(body, StandardCharsets.UTF_8)); + String line = bufferedReader.readLine(); + while (line != null) { + builder.append(line).append(System.lineSeparator()); + line = bufferedReader.readLine(); + } + bufferedReader.close(); + return builder.toString(); + } + } +} diff --git a/libraries/resttemplate/api.mustache b/libraries/resttemplate/api.mustache new file mode 100644 index 00000000000..f48180f4381 --- /dev/null +++ b/libraries/resttemplate/api.mustache @@ -0,0 +1,107 @@ +package {{package}}; + +import {{invokerPackage}}.ApiClient; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}}import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map;{{/fullJavaUtil}} + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.util.UriComponentsBuilder; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.core.io.FileSystemResource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; + +{{>generatedAnnotation}} +@Component("{{package}}.{{classname}}") +{{#operations}} +public class {{classname}} { + private ApiClient {{localVariablePrefix}}apiClient; + + public {{classname}}() { + this(new ApiClient()); + } + + @Autowired + public {{classname}}(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + public ApiClient getApiClient() { + return {{localVariablePrefix}}apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + {{#operation}} + /** + * {{summary}} + * {{notes}} +{{#responses}} *

{{code}}{{#message}} - {{message}}{{/message}} +{{/responses}}{{#allParams}} * @param {{paramName}} {{description}}{{^description}}The {{paramName}} parameter{{/description}} +{{/allParams}}{{#returnType}} * @return {{returnType}} +{{/returnType}} * @throws RestClientException if an error occurs while attempting to invoke the API +{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation +{{/externalDocs}} + */ + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { + Object {{localVariablePrefix}}postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + } + {{/required}}{{/allParams}}{{#hasPathParams}} + // create path and map variables + final Map uriVariables = new HashMap();{{#pathParams}} + uriVariables.put("{{baseName}}", {{{paramName}}});{{/pathParams}}{{/hasPathParams}} + String {{localVariablePrefix}}path = UriComponentsBuilder.fromPath("{{{path}}}"){{#hasPathParams}}.buildAndExpand(uriVariables){{/hasPathParams}}{{^hasPathParams}}.build(){{/hasPathParams}}.toUriString(); + + final MultiValueMap {{localVariablePrefix}}queryParams = new LinkedMultiValueMap(); + final HttpHeaders {{localVariablePrefix}}headerParams = new HttpHeaders(); + final MultiValueMap {{localVariablePrefix}}formParams = new LinkedMultiValueMap();{{#hasQueryParams}} + + {{#queryParams}}{{localVariablePrefix}}queryParams.putAll({{localVariablePrefix}}apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase()){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{#hasMore}} + {{/hasMore}}{{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}} + + {{#headerParams}}if ({{paramName}} != null) + {{localVariablePrefix}}headerParams.add("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}}));{{#hasMore}} + {{/hasMore}}{{/headerParams}}{{/hasHeaderParams}}{{#hasFormParams}} + + {{#formParams}}if ({{paramName}} != null) + {{localVariablePrefix}}formParams.add("{{baseName}}", {{#isFile}}new FileSystemResource({{paramName}}){{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} + {{/hasMore}}{{/formParams}}{{/hasFormParams}} + + final String[] {{localVariablePrefix}}accepts = { {{#hasProduces}} + {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} + {{/hasProduces}}}; + final List {{localVariablePrefix}}accept = {{localVariablePrefix}}apiClient.selectHeaderAccept({{localVariablePrefix}}accepts); + final String[] {{localVariablePrefix}}contentTypes = { {{#hasConsumes}} + {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} + {{/hasConsumes}}}; + final MediaType {{localVariablePrefix}}contentType = {{localVariablePrefix}}apiClient.selectHeaderContentType({{localVariablePrefix}}contentTypes); + + String[] {{localVariablePrefix}}authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + + {{#returnType}}ParameterizedTypeReference<{{{returnType}}}> {{localVariablePrefix}}returnType = new ParameterizedTypeReference<{{{returnType}}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference {{localVariablePrefix}}returnType = new ParameterizedTypeReference() {};{{/returnType}} + {{#returnType}}return {{/returnType}}{{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}path, HttpMethod.{{httpMethod}}, {{localVariablePrefix}}queryParams, {{localVariablePrefix}}postBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames, {{localVariablePrefix}}returnType); + } + {{/operation}} +} +{{/operations}} diff --git a/libraries/resttemplate/api_test.mustache b/libraries/resttemplate/api_test.mustache new file mode 100644 index 00000000000..127ac2defc5 --- /dev/null +++ b/libraries/resttemplate/api_test.mustache @@ -0,0 +1,44 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Test; +import org.junit.Ignore; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +@Ignore +public class {{classname}}Test { + + private final {{classname}} api = new {{classname}}(); + + {{#operations}}{{#operation}} + /** + * {{summary}} + * + * {{notes}} + * + * @throws ApiException + * if the Api call fails + */ + @Test + public void {{operationId}}Test() { + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + + // TODO: test validations + } + {{/operation}}{{/operations}} +} diff --git a/libraries/resttemplate/auth/ApiKeyAuth.mustache b/libraries/resttemplate/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..8b8c40fde75 --- /dev/null +++ b/libraries/resttemplate/auth/ApiKeyAuth.mustache @@ -0,0 +1,60 @@ +package {{invokerPackage}}.auth; + +import org.springframework.http.HttpHeaders; +import org.springframework.util.MultiValueMap; + +{{>generatedAnnotation}} +public class ApiKeyAuth implements Authentication { + private final String location; + private final String paramName; + + private String apiKey; + private String apiKeyPrefix; + + public ApiKeyAuth(String location, String paramName) { + this.location = location; + this.paramName = paramName; + } + + public String getLocation() { + return location; + } + + public String getParamName() { + return paramName; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + public String getApiKeyPrefix() { + return apiKeyPrefix; + } + + public void setApiKeyPrefix(String apiKeyPrefix) { + this.apiKeyPrefix = apiKeyPrefix; + } + + @Override + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams) { + if (apiKey == null) { + return; + } + String value; + if (apiKeyPrefix != null) { + value = apiKeyPrefix + " " + apiKey; + } else { + value = apiKey; + } + if (location.equals("query")) { + queryParams.add(paramName, value); + } else if (location.equals("header")) { + headerParams.add(paramName, value); + } + } +} diff --git a/libraries/resttemplate/auth/Authentication.mustache b/libraries/resttemplate/auth/Authentication.mustache new file mode 100644 index 00000000000..586de70836a --- /dev/null +++ b/libraries/resttemplate/auth/Authentication.mustache @@ -0,0 +1,13 @@ +package {{invokerPackage}}.auth; + +import org.springframework.http.HttpHeaders; +import org.springframework.util.MultiValueMap; + +public interface Authentication { + /** + * Apply authentication settings to header and / or query parameters. + * @param queryParams The query parameters for the request + * @param headerParams The header parameters for the request + */ + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams); +} diff --git a/libraries/resttemplate/auth/HttpBasicAuth.mustache b/libraries/resttemplate/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..5f535b3698a --- /dev/null +++ b/libraries/resttemplate/auth/HttpBasicAuth.mustache @@ -0,0 +1,39 @@ +package {{invokerPackage}}.auth; + +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; + +import org.springframework.http.HttpHeaders; +import org.springframework.util.Base64Utils; +import org.springframework.util.MultiValueMap; + +{{>generatedAnnotation}} +public class HttpBasicAuth implements Authentication { + private String username; + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams) { + if (username == null && password == null) { + return; + } + String str = (username == null ? "" : username) + ":" + (password == null ? "" : password); + headerParams.add(HttpHeaders.AUTHORIZATION, "Basic " + Base64Utils.encodeToString(str.getBytes(StandardCharsets.UTF_8))); + } +} diff --git a/libraries/resttemplate/auth/OAuth.mustache b/libraries/resttemplate/auth/OAuth.mustache new file mode 100644 index 00000000000..fbb2f7f9c72 --- /dev/null +++ b/libraries/resttemplate/auth/OAuth.mustache @@ -0,0 +1,24 @@ +package {{invokerPackage}}.auth; + +import org.springframework.http.HttpHeaders; +import org.springframework.util.MultiValueMap; + +{{>generatedAnnotation}} +public class OAuth implements Authentication { + private String accessToken; + + public String getAccessToken() { + return accessToken; + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + @Override + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams) { + if (accessToken != null) { + headerParams.add(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken); + } + } +} diff --git a/libraries/resttemplate/auth/OAuthFlow.mustache b/libraries/resttemplate/auth/OAuthFlow.mustache new file mode 100644 index 00000000000..7ab35f6d890 --- /dev/null +++ b/libraries/resttemplate/auth/OAuthFlow.mustache @@ -0,0 +1,5 @@ +package {{invokerPackage}}.auth; + +public enum OAuthFlow { + accessCode, implicit, password, application +} \ No newline at end of file diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache new file mode 100644 index 00000000000..e4fc1caa4f0 --- /dev/null +++ b/libraries/resttemplate/build.gradle.mustache @@ -0,0 +1,140 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.5.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 23 + buildToolsVersion '23.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 22 + } + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + {{#java8}} + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + {{/java8}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + swagger_annotations_version = "1.5.17" + jackson_version = "2.8.9" + spring_web_version = "4.3.9.RELEASE" + jodatime_version = "2.9.9" + junit_version = "4.12" + {{#threetenbp}} + jackson_threeten_version = "2.6.4" + {{/threetenbp}} +} + +dependencies { + compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "org.springframework:spring-web:$spring_web_version" + compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + {{#java8}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{/java8}} + {{#joda}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + compile "joda-time:joda-time:$jodatime_version" + {{/joda}} + {{#threetenbp}} + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threeten_version" + {{/threetenbp}} + {{#withXml}} + compile "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jackson_version" + {{/withXml}} + testCompile "junit:junit:$junit_version" +} diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache new file mode 100644 index 00000000000..e2bdc3a8b68 --- /dev/null +++ b/libraries/resttemplate/pom.mustache @@ -0,0 +1,301 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{artifactUrl}} + {{artifactDescription}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + {{#java8}} + + 1.8 + 1.8 + {{/java8}} + {{^java8}} + + 1.7 + 1.7 + {{/java8}} + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-annotations-version} + + + + + org.springframework + spring-web + ${spring-web-version} + + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-version} + + + com.fasterxml.jackson.jaxrs + jackson-jaxrs-json-provider + ${jackson-version} + + {{#withXml}} + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson-version} + + + {{/withXml}} + {{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{/java8}} + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + + joda-time + joda-time + ${jodatime-version} + + {{/joda}} + {{#threetenbp}} + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${jackson-threetenbp-version} + + {{/threetenbp}} + + + + junit + junit + ${junit-version} + test + + + + UTF-8 + 1.5.17 + 4.3.9.RELEASE + 2.8.9 + {{#joda}} + 2.9.9 + {{/joda}} + {{#threetenbp}} + 2.6.4 + {{/threetenbp}} + 1.0.0 + 4.12 + + diff --git a/libraries/retrofit/ApiClient.mustache b/libraries/retrofit/ApiClient.mustache new file mode 100644 index 00000000000..7c45e926bcf --- /dev/null +++ b/libraries/retrofit/ApiClient.mustache @@ -0,0 +1,418 @@ +package {{invokerPackage}}; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Type; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; +import org.joda.time.DateTime; +import org.joda.time.LocalDate; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.ISODateTimeFormat; + +import retrofit.RestAdapter; +import retrofit.client.OkClient; +import retrofit.converter.ConversionException; +import retrofit.converter.Converter; +import retrofit.converter.GsonConverter; +import retrofit.mime.TypedByteArray; +import retrofit.mime.TypedInput; +import retrofit.mime.TypedOutput; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonParseException; +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import com.squareup.okhttp.Interceptor; +import com.squareup.okhttp.OkHttpClient; + +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.OAuth; +import {{invokerPackage}}.auth.OAuth.AccessTokenListener; +import {{invokerPackage}}.auth.OAuthFlow; + + +public class ApiClient { + + private Map apiAuthorizations; + private OkHttpClient okClient; + private RestAdapter.Builder adapterBuilder; + + public ApiClient() { + apiAuthorizations = new LinkedHashMap(); + createDefaultAdapter(); + } + + public ApiClient(String[] authNames) { + this(); + for(String authName : authNames) { + {{#hasAuthMethods}} + Interceptor auth; + {{#authMethods}}if ("{{name}}".equals(authName)) { + {{#isBasic}} + auth = new HttpBasicAuth(); + {{/isBasic}} + {{#isApiKey}} + auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}");{{/isApiKey}} + {{#isOAuth}} + auth = new OAuth(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{#hasMore}}, {{/hasMore}}{{/scopes}}"); + {{/isOAuth}} + } else {{/authMethods}}{ + throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); + } + addAuthorization(authName, auth); + {{/hasAuthMethods}} + {{^hasAuthMethods}} + throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); + {{/hasAuthMethods}} + } + } + + /** + * Basic constructor for single auth name + * @param authName Authentication name + */ + public ApiClient(String authName) { + this(new String[]{authName}); + } + + /** + * Helper constructor for single api key + * @param authName Authentication name + * @param apiKey API key + */ + public ApiClient(String authName, String apiKey) { + this(authName); + this.setApiKey(apiKey); + } + + /** + * Helper constructor for single basic auth or password oauth2 + * @param authName Authentication name + * @param username Username + * @param password Password + */ + public ApiClient(String authName, String username, String password) { + this(authName); + this.setCredentials(username, password); + } + + /** + * Helper constructor for single password oauth2 + * @param authName Authentication name + * @param clientId Client ID + * @param secret Client secret + * @param username Username + * @param password Password + */ + public ApiClient(String authName, String clientId, String secret, String username, String password) { + this(authName); + this.getTokenEndPoint() + .setClientId(clientId) + .setClientSecret(secret) + .setUsername(username) + .setPassword(password); + } + + public void createDefaultAdapter() { + Gson gson = new GsonBuilder() + .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ") + .registerTypeAdapter(DateTime.class, new DateTimeTypeAdapter()) + .registerTypeAdapter(LocalDate.class, new LocalDateTypeAdapter()) + .create(); + + okClient = new OkHttpClient(); + + adapterBuilder = new RestAdapter + .Builder() + .setEndpoint("{{{basePath}}}") + .setClient(new OkClient(okClient)) + .setConverter(new GsonConverterWrapper(gson)); + } + + public S createService(Class serviceClass) { + return adapterBuilder.build().create(serviceClass); + + } + + /** + * Helper method to configure the first api key found + * @param apiKey API key + */ + private void setApiKey(String apiKey) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof ApiKeyAuth) { + ApiKeyAuth keyAuth = (ApiKeyAuth) apiAuthorization; + keyAuth.setApiKey(apiKey); + return; + } + } + } + + /** + * Helper method to configure the username/password for basic auth or password oauth + * @param username Username + * @param password Password + */ + private void setCredentials(String username, String password) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof HttpBasicAuth) { + HttpBasicAuth basicAuth = (HttpBasicAuth) apiAuthorization; + basicAuth.setCredentials(username, password); + return; + } + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.getTokenRequestBuilder().setUsername(username).setPassword(password); + return; + } + } + } + + /** + * Helper method to configure the token endpoint of the first oauth found in the apiAuthorizations (there should be only one) + * @return Token request builder + */ + public TokenRequestBuilder getTokenEndPoint() { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + return oauth.getTokenRequestBuilder(); + } + } + return null; + } + + /** + * Helper method to configure authorization endpoint of the first oauth found in the apiAuthorizations (there should be only one) + * @return Authentication request builder + */ + public AuthenticationRequestBuilder getAuthorizationEndPoint() { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + return oauth.getAuthenticationRequestBuilder(); + } + } + return null; + } + + /** + * Helper method to pre-set the oauth access token of the first oauth found in the apiAuthorizations (there should be only one) + * @param accessToken Access token + */ + public void setAccessToken(String accessToken) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.setAccessToken(accessToken); + return; + } + } + } + + /** + * Helper method to configure the oauth accessCode/implicit flow parameters + * @param clientId Client ID + * @param clientSecret Client secret + * @param redirectURI Redirect URI + */ + public void configureAuthorizationFlow(String clientId, String clientSecret, String redirectURI) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.getTokenRequestBuilder() + .setClientId(clientId) + .setClientSecret(clientSecret) + .setRedirectURI(redirectURI); + oauth.getAuthenticationRequestBuilder() + .setClientId(clientId) + .setRedirectURI(redirectURI); + return; + } + } + } + + /** + * Configures a listener which is notified when a new access token is received. + * @param accessTokenListener Access token listener + */ + public void registerAccessTokenListener(AccessTokenListener accessTokenListener) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.registerAccessTokenListener(accessTokenListener); + return; + } + } + } + + /** + * Adds an authorization to be used by the client + * @param authName Authentication name + * @param authorization Authorization + */ + public void addAuthorization(String authName, Interceptor authorization) { + if (apiAuthorizations.containsKey(authName)) { + throw new RuntimeException("auth name \"" + authName + "\" already in api authorizations"); + } + apiAuthorizations.put(authName, authorization); + okClient.interceptors().add(authorization); + } + + public Map getApiAuthorizations() { + return apiAuthorizations; + } + + public void setApiAuthorizations(Map apiAuthorizations) { + this.apiAuthorizations = apiAuthorizations; + } + + public RestAdapter.Builder getAdapterBuilder() { + return adapterBuilder; + } + + public void setAdapterBuilder(RestAdapter.Builder adapterBuilder) { + this.adapterBuilder = adapterBuilder; + } + + public OkHttpClient getOkClient() { + return okClient; + } + + public void addAuthsToOkClient(OkHttpClient okClient) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + okClient.interceptors().add(apiAuthorization); + } + } + + /** + * Clones the okClient given in parameter, adds the auth interceptors and uses it to configure the RestAdapter + * @param okClient OkHttp client + */ + public void configureFromOkclient(OkHttpClient okClient) { + OkHttpClient clone = okClient.clone(); + addAuthsToOkClient(clone); + adapterBuilder.setClient(new OkClient(clone)); + } +} + +/** + * This wrapper is to take care of this case: + * when the deserialization fails due to JsonParseException and the + * expected type is String, then just return the body string. + */ +class GsonConverterWrapper implements Converter { + private GsonConverter converter; + + public GsonConverterWrapper(Gson gson) { + converter = new GsonConverter(gson); + } + + @Override public Object fromBody(TypedInput body, Type type) throws ConversionException { + byte[] bodyBytes = readInBytes(body); + TypedByteArray newBody = new TypedByteArray(body.mimeType(), bodyBytes); + try { + return converter.fromBody(newBody, type); + } catch (ConversionException e) { + if (e.getCause() instanceof JsonParseException && type.equals(String.class)) { + return new String(bodyBytes); + } else { + throw e; + } + } + } + + @Override public TypedOutput toBody(Object object) { + return converter.toBody(object); + } + + private byte[] readInBytes(TypedInput body) throws ConversionException { + InputStream in = null; + try { + in = body.in(); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + byte[] buffer = new byte[0xFFFF]; + for (int len; (len = in.read(buffer)) != -1;) + os.write(buffer, 0, len); + os.flush(); + return os.toByteArray(); + } catch (IOException e) { + throw new ConversionException(e); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException ignored) { + } + } + } + + } +} + +/** + * Gson TypeAdapter for Joda DateTime type + */ +class DateTimeTypeAdapter extends TypeAdapter { + + private final DateTimeFormatter parseFormatter = ISODateTimeFormat.dateOptionalTimeParser(); + private final DateTimeFormatter printFormatter = ISODateTimeFormat.dateTime(); + + @Override + public void write(JsonWriter out, DateTime date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(printFormatter.print(date)); + } + } + + @Override + public DateTime read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + return parseFormatter.parseDateTime(date); + } + } +} + +/** + * Gson TypeAdapter for Joda DateTime type + */ +class LocalDateTypeAdapter extends TypeAdapter { + + private final DateTimeFormatter formatter = ISODateTimeFormat.date(); + + @Override + public void write(JsonWriter out, LocalDate date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.print(date)); + } + } + + @Override + public LocalDate read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + return formatter.parseLocalDate(date); + } + } +} diff --git a/libraries/retrofit/CollectionFormats.mustache b/libraries/retrofit/CollectionFormats.mustache new file mode 100644 index 00000000000..a549ea59d1c --- /dev/null +++ b/libraries/retrofit/CollectionFormats.mustache @@ -0,0 +1,95 @@ +package {{invokerPackage}}; + +import java.util.Arrays; +import java.util.List; + +public class CollectionFormats { + + public static class CSVParams { + + protected List params; + + public CSVParams() { + } + + public CSVParams(List params) { + this.params = params; + } + + public CSVParams(String... params) { + this.params = Arrays.asList(params); + } + + public List getParams() { + return params; + } + + public void setParams(List params) { + this.params = params; + } + + @Override + public String toString() { + return StringUtil.join(params.toArray(new String[0]), ","); + } + + } + + public static class SSVParams extends CSVParams { + + public SSVParams() { + } + + public SSVParams(List params) { + super(params); + } + + public SSVParams(String... params) { + super(params); + } + + @Override + public String toString() { + return StringUtil.join(params.toArray(new String[0]), " "); + } + } + + public static class TSVParams extends CSVParams { + + public TSVParams() { + } + + public TSVParams(List params) { + super(params); + } + + public TSVParams(String... params) { + super(params); + } + + @Override + public String toString() { + return StringUtil.join( params.toArray(new String[0]), "\t"); + } + } + + public static class PIPESParams extends CSVParams { + + public PIPESParams() { + } + + public PIPESParams(List params) { + super(params); + } + + public PIPESParams(String... params) { + super(params); + } + + @Override + public String toString() { + return StringUtil.join(params.toArray(new String[0]), "|"); + } + } + +} diff --git a/libraries/retrofit/README.mustache b/libraries/retrofit/README.mustache new file mode 100644 index 00000000000..56560172ee3 --- /dev/null +++ b/libraries/retrofit/README.mustache @@ -0,0 +1,43 @@ +# {{artifactId}} + +## Requirements + +Building the API client library requires [Maven](https://maven.apache.org/) to be installed. + +## Installation & Usage + +To install the API client library to your local Maven repository, simply execute: + +```shell +mvn install +``` + +To deploy it to a remote Maven repository instead, configure the settings of the repository and execute: + +```shell +mvn deploy +``` + +Refer to the [official documentation](https://maven.apache.org/plugins/maven-deploy-plugin/usage.html) for more information. + +After the client library is installed/deployed, you can use it in your Maven project by adding the following to your *pom.xml*: + +```xml + + {{groupId}} + {{artifactId}} + {{artifactVersion}} + compile + + +``` + +## Recommendation + +It's recommended to create an instance of `ApiClient` per thread in a multithreaded environment to avoid any potential issues. + +## Author + +{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} +{{/hasMore}}{{/apis}}{{/apiInfo}} + diff --git a/libraries/retrofit/api.mustache b/libraries/retrofit/api.mustache new file mode 100644 index 00000000000..46df0ecedf3 --- /dev/null +++ b/libraries/retrofit/api.mustache @@ -0,0 +1,62 @@ +package {{package}}; + +import {{invokerPackage}}.CollectionFormats.*; + +import retrofit.Callback; +import retrofit.http.*; +import retrofit.mime.*; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +{{#operations}} +public interface {{classname}} { + {{#operation}} + /** + * {{summary}} + * Sync method + * {{notes}} +{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} +{{/allParams}} + * @return {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}} +{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation +{{/externalDocs}} + */ + {{#formParams}}{{#-first}} + {{#isMultipart}}@retrofit.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit.http.FormUrlEncoded{{/isMultipart}}{{/-first}}{{/formParams}} + @{{httpMethod}}("{{{path}}}") + {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}} {{operationId}}({{^allParams}});{{/allParams}} + {{#allParams}}{{>libraries/retrofit/queryParams}}{{>libraries/retrofit/pathParams}}{{>libraries/retrofit/headerParams}}{{>libraries/retrofit/bodyParams}}{{>libraries/retrofit/formParams}}{{#hasMore}}, {{/hasMore}}{{^hasMore}} + );{{/hasMore}}{{/allParams}} + + /** + * {{summary}} + * Async method +{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} +{{/allParams}} + * @param cb callback method +{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation +{{/externalDocs}} + */ + {{#formParams}}{{#-first}} + {{#isMultipart}}@retrofit.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit.http.FormUrlEncoded{{/isMultipart}}{{/-first}}{{/formParams}} + @{{httpMethod}}("{{{path}}}") + void {{operationId}}( + {{#allParams}}{{>libraries/retrofit/queryParams}}{{>libraries/retrofit/pathParams}}{{>libraries/retrofit/headerParams}}{{>libraries/retrofit/bodyParams}}{{>libraries/retrofit/formParams}}, {{/allParams}}Callback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> cb + ); + {{/operation}} +} +{{/operations}} diff --git a/libraries/retrofit/api_test.mustache b/libraries/retrofit/api_test.mustache new file mode 100644 index 00000000000..a34cfe0e12b --- /dev/null +++ b/libraries/retrofit/api_test.mustache @@ -0,0 +1,44 @@ +package {{package}}; + +import {{invokerPackage}}.ApiClient; +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Before; +import org.junit.Test; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +public class {{classname}}Test { + + private {{classname}} api; + + @Before + public void setup() { + api = new ApiClient().createService({{classname}}.class); + } + + {{#operations}}{{#operation}} + /** + * {{summary}} + * + * {{notes}} + */ + @Test + public void {{operationId}}Test() { + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + // {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + + // TODO: test validations + } + {{/operation}}{{/operations}} +} diff --git a/libraries/retrofit/auth/ApiKeyAuth.mustache b/libraries/retrofit/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..f6a86f22ab4 --- /dev/null +++ b/libraries/retrofit/auth/ApiKeyAuth.mustache @@ -0,0 +1,68 @@ +package {{invokerPackage}}.auth; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import com.squareup.okhttp.Interceptor; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; + +public class ApiKeyAuth implements Interceptor { + private final String location; + private final String paramName; + + private String apiKey; + + public ApiKeyAuth(String location, String paramName) { + this.location = location; + this.paramName = paramName; + } + + public String getLocation() { + return location; + } + + public String getParamName() { + return paramName; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + @Override + public Response intercept(Chain chain) throws IOException { + String paramValue; + Request request = chain.request(); + + if ("query".equals(location)) { + String newQuery = request.uri().getQuery(); + paramValue = paramName + "=" + apiKey; + if (newQuery == null) { + newQuery = paramValue; + } else { + newQuery += "&" + paramValue; + } + + URI newUri; + try { + newUri = new URI(request.uri().getScheme(), request.uri().getAuthority(), + request.uri().getPath(), newQuery, request.uri().getFragment()); + } catch (URISyntaxException e) { + throw new IOException(e); + } + + request = request.newBuilder().url(newUri.toURL()).build(); + } else if ("header".equals(location)) { + request = request.newBuilder() + .addHeader(paramName, apiKey) + .build(); + } + return chain.proceed(request); + } +} diff --git a/libraries/retrofit/auth/HttpBasicAuth.mustache b/libraries/retrofit/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..394592f64d9 --- /dev/null +++ b/libraries/retrofit/auth/HttpBasicAuth.mustache @@ -0,0 +1,49 @@ +package {{invokerPackage}}.auth; + +import java.io.IOException; + +import com.squareup.okhttp.Credentials; +import com.squareup.okhttp.Interceptor; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; + +public class HttpBasicAuth implements Interceptor { + + private String username; + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public void setCredentials(String username, String password) { + this.username = username; + this.password = password; + } + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + + // If the request already have an authorization (eg. Basic auth), do nothing + if (request.header("Authorization") == null) { + String credentials = Credentials.basic(username, password); + request = request.newBuilder() + .addHeader("Authorization", credentials) + .build(); + } + return chain.proceed(request); + } +} diff --git a/libraries/retrofit/auth/OAuth.mustache b/libraries/retrofit/auth/OAuth.mustache new file mode 100644 index 00000000000..4c39f4e629e --- /dev/null +++ b/libraries/retrofit/auth/OAuth.mustache @@ -0,0 +1,185 @@ +package {{invokerPackage}}.auth; + +import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; +import static java.net.HttpURLConnection.HTTP_FORBIDDEN; + +import java.io.IOException; +import java.util.Map; + +import org.apache.oltu.oauth2.client.OAuthClient; +import org.apache.oltu.oauth2.client.request.OAuthBearerClientRequest; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; +import org.apache.oltu.oauth2.client.response.OAuthJSONAccessTokenResponse; +import org.apache.oltu.oauth2.common.exception.OAuthProblemException; +import org.apache.oltu.oauth2.common.exception.OAuthSystemException; +import org.apache.oltu.oauth2.common.message.types.GrantType; +import org.apache.oltu.oauth2.common.token.BasicOAuthToken; + +import com.squareup.okhttp.Interceptor; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Request.Builder; +import com.squareup.okhttp.Response; + +public class OAuth implements Interceptor { + + public interface AccessTokenListener { + public void notify(BasicOAuthToken token); + } + + private volatile String accessToken; + private OAuthClient oauthClient; + + private TokenRequestBuilder tokenRequestBuilder; + private AuthenticationRequestBuilder authenticationRequestBuilder; + + private AccessTokenListener accessTokenListener; + + public OAuth( OkHttpClient client, TokenRequestBuilder requestBuilder ) { + this.oauthClient = new OAuthClient(new OAuthOkHttpClient(client)); + this.tokenRequestBuilder = requestBuilder; + } + + public OAuth(TokenRequestBuilder requestBuilder ) { + this(new OkHttpClient(), requestBuilder); + } + + public OAuth(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { + this(OAuthClientRequest.tokenLocation(tokenUrl).setScope(scopes)); + setFlow(flow); + authenticationRequestBuilder = OAuthClientRequest.authorizationLocation(authorizationUrl); + } + + public void setFlow(OAuthFlow flow) { + switch(flow) { + case accessCode: + case implicit: + tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE); + break; + case password: + tokenRequestBuilder.setGrantType(GrantType.PASSWORD); + break; + case application: + tokenRequestBuilder.setGrantType(GrantType.CLIENT_CREDENTIALS); + break; + default: + break; + } + } + + @Override + public Response intercept(Chain chain) + throws IOException { + + return retryingIntercept(chain, true); + } + + private Response retryingIntercept(Chain chain, boolean updateTokenAndRetryOnAuthorizationFailure) throws IOException { + Request request = chain.request(); + + // If the request already have an authorization (eg. Basic auth), do nothing + if (request.header("Authorization") != null) { + return chain.proceed(request); + } + + // If first time, get the token + OAuthClientRequest oAuthRequest; + if (getAccessToken() == null) { + updateAccessToken(null); + } + + if (getAccessToken() != null) { + // Build the request + Builder rb = request.newBuilder(); + + String requestAccessToken = new String(getAccessToken()); + try { + oAuthRequest = new OAuthBearerClientRequest(request.urlString()) + .setAccessToken(requestAccessToken) + .buildHeaderMessage(); + } catch (OAuthSystemException e) { + throw new IOException(e); + } + + for ( Map.Entry header : oAuthRequest.getHeaders().entrySet() ) { + rb.addHeader(header.getKey(), header.getValue()); + } + rb.url( oAuthRequest.getLocationUri()); + + //Execute the request + Response response = chain.proceed(rb.build()); + + // 401/403 most likely indicates that access token has expired. Unless it happens two times in a row. + if ( response != null && (response.code() == HTTP_UNAUTHORIZED || response.code() == HTTP_FORBIDDEN) && updateTokenAndRetryOnAuthorizationFailure ) { + try { + if (updateAccessToken(requestAccessToken)) { + response.body().close(); + return retryingIntercept( chain, false ); + } + } catch (Exception e) { + response.body().close(); + throw e; + } + } + return response; + } else { + return chain.proceed(chain.request()); + } + } + + /* + * Returns true if the access token has been updated + */ + public synchronized boolean updateAccessToken(String requestAccessToken) throws IOException { + if (getAccessToken() == null || getAccessToken().equals(requestAccessToken)) { + try { + OAuthJSONAccessTokenResponse accessTokenResponse = oauthClient.accessToken(this.tokenRequestBuilder.buildBodyMessage()); + if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { + setAccessToken(accessTokenResponse.getAccessToken()); + if (accessTokenListener != null) { + accessTokenListener.notify((BasicOAuthToken) accessTokenResponse.getOAuthToken()); + } + return !getAccessToken().equals(requestAccessToken); + } else { + return false; + } + } catch (OAuthSystemException e) { + throw new IOException(e); + } catch (OAuthProblemException e) { + throw new IOException(e); + } + } + return true; + } + + public void registerAccessTokenListener(AccessTokenListener accessTokenListener) { + this.accessTokenListener = accessTokenListener; + } + + public synchronized String getAccessToken() { + return accessToken; + } + + public synchronized void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + public TokenRequestBuilder getTokenRequestBuilder() { + return tokenRequestBuilder; + } + + public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) { + this.tokenRequestBuilder = tokenRequestBuilder; + } + + public AuthenticationRequestBuilder getAuthenticationRequestBuilder() { + return authenticationRequestBuilder; + } + + public void setAuthenticationRequestBuilder(AuthenticationRequestBuilder authenticationRequestBuilder) { + this.authenticationRequestBuilder = authenticationRequestBuilder; + } + +} diff --git a/libraries/retrofit/auth/OAuthOkHttpClient.mustache b/libraries/retrofit/auth/OAuthOkHttpClient.mustache new file mode 100644 index 00000000000..ea195f7df04 --- /dev/null +++ b/libraries/retrofit/auth/OAuthOkHttpClient.mustache @@ -0,0 +1,69 @@ +package {{invokerPackage}}.auth; + +import java.io.IOException; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.oltu.oauth2.client.HttpClient; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest; +import org.apache.oltu.oauth2.client.response.OAuthClientResponse; +import org.apache.oltu.oauth2.client.response.OAuthClientResponseFactory; +import org.apache.oltu.oauth2.common.exception.OAuthProblemException; +import org.apache.oltu.oauth2.common.exception.OAuthSystemException; + +import com.squareup.okhttp.MediaType; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.RequestBody; +import com.squareup.okhttp.Response; + + +public class OAuthOkHttpClient implements HttpClient { + + private OkHttpClient client; + + public OAuthOkHttpClient() { + this.client = new OkHttpClient(); + } + + public OAuthOkHttpClient(OkHttpClient client) { + this.client = client; + } + + public T execute(OAuthClientRequest request, Map headers, + String requestMethod, Class responseClass) + throws OAuthSystemException, OAuthProblemException { + + MediaType mediaType = MediaType.parse("application/json"); + Request.Builder requestBuilder = new Request.Builder().url(request.getLocationUri()); + + if(headers != null) { + for (Entry entry : headers.entrySet()) { + if (entry.getKey().equalsIgnoreCase("Content-Type")) { + mediaType = MediaType.parse(entry.getValue()); + } else { + requestBuilder.addHeader(entry.getKey(), entry.getValue()); + } + } + } + + RequestBody body = request.getBody() != null ? RequestBody.create(mediaType, request.getBody()) : null; + requestBuilder.method(requestMethod, body); + + try { + Response response = client.newCall(requestBuilder.build()).execute(); + return OAuthClientResponseFactory.createCustomResponse( + response.body().string(), + response.body().contentType().toString(), + response.code(), + responseClass); + } catch (IOException e) { + throw new OAuthSystemException(e); + } + } + + public void shutdown() { + // Nothing to do here + } + +} diff --git a/libraries/retrofit/bodyParams.mustache b/libraries/retrofit/bodyParams.mustache new file mode 100644 index 00000000000..81de324b691 --- /dev/null +++ b/libraries/retrofit/bodyParams.mustache @@ -0,0 +1 @@ +{{#isBodyParam}}@retrofit.http.Body {{{dataType}}} {{paramName}}{{/isBodyParam}} \ No newline at end of file diff --git a/libraries/retrofit/build.gradle.mustache b/libraries/retrofit/build.gradle.mustache new file mode 100644 index 00000000000..60dec7e1260 --- /dev/null +++ b/libraries/retrofit/build.gradle.mustache @@ -0,0 +1,118 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + } + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + okhttp_version = "2.7.5" + oltu_version = "1.0.1" + retrofit_version = "1.9.0" + swagger_annotations_version = "1.5.8" + junit_version = "4.12" + jodatime_version = "2.9.3" +} + +dependencies { + compile "com.squareup.okhttp:okhttp:$okhttp_version" + compile "com.squareup.retrofit:retrofit:$retrofit_version" + compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version" + compile "joda-time:joda-time:$jodatime_version" + testCompile "junit:junit:$junit_version" +} diff --git a/libraries/retrofit/build.sbt.mustache b/libraries/retrofit/build.sbt.mustache new file mode 100644 index 00000000000..56f6cee13ab --- /dev/null +++ b/libraries/retrofit/build.sbt.mustache @@ -0,0 +1,20 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "com.squareup.okhttp" % "okhttp" % "2.7.5" % "compile", + "com.squareup.retrofit" % "retrofit" % "1.9.0" % "compile", + "io.swagger" % "swagger-annotations" % "1.5.8" % "compile", + "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", + "joda-time" % "joda-time" % "2.9.3" % "compile", + "junit" % "junit" % "4.12" % "test", + "com.novocode" % "junit-interface" % "0.10" % "test" + ) + ) diff --git a/libraries/retrofit/formParams.mustache b/libraries/retrofit/formParams.mustache new file mode 100644 index 00000000000..f1f9027ae51 --- /dev/null +++ b/libraries/retrofit/formParams.mustache @@ -0,0 +1 @@ +{{#isFormParam}}{{#notFile}}{{#isMultipart}}@retrofit.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit.http.Field{{/isMultipart}}("{{baseName}}") {{{dataType}}} {{paramName}}{{/notFile}}{{#isFile}}{{#isMultipart}}@retrofit.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit.http.Field{{/isMultipart}}("{{baseName}}") TypedFile {{paramName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file diff --git a/libraries/retrofit/headerParams.mustache b/libraries/retrofit/headerParams.mustache new file mode 100644 index 00000000000..5d6da4a9437 --- /dev/null +++ b/libraries/retrofit/headerParams.mustache @@ -0,0 +1 @@ +{{#isHeaderParam}}@retrofit.http.Header("{{baseName}}") {{{dataType}}} {{paramName}}{{/isHeaderParam}} \ No newline at end of file diff --git a/libraries/retrofit/pathParams.mustache b/libraries/retrofit/pathParams.mustache new file mode 100644 index 00000000000..7b8be8442e0 --- /dev/null +++ b/libraries/retrofit/pathParams.mustache @@ -0,0 +1 @@ +{{#isPathParam}}@retrofit.http.Path("{{baseName}}") {{{dataType}}} {{paramName}}{{/isPathParam}} \ No newline at end of file diff --git a/libraries/retrofit/pom.mustache b/libraries/retrofit/pom.mustache new file mode 100644 index 00000000000..b4ceff3aac0 --- /dev/null +++ b/libraries/retrofit/pom.mustache @@ -0,0 +1,254 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{artifactUrl}} + {{artifactDescription}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}} + {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}} + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-core-version} + + + com.squareup.retrofit + retrofit + ${retrofit-version} + + + org.apache.oltu.oauth2 + org.apache.oltu.oauth2.client + ${oltu-version} + + + com.squareup.okhttp + okhttp + ${okhttp-version} + + + joda-time + joda-time + ${jodatime-version} + + + {{#parcelableModel}} + + + com.google.android + android + 4.1.1.4 + provided + + {{/parcelableModel}} + + + + junit + junit + ${junit-version} + test + + + + UTF-8 + 1.5.18 + 1.9.0 + 2.7.5 + 2.9.9 + 1.0.1 + 1.0.0 + 4.12 + + diff --git a/libraries/retrofit/queryParams.mustache b/libraries/retrofit/queryParams.mustache new file mode 100644 index 00000000000..2a580ab34ec --- /dev/null +++ b/libraries/retrofit/queryParams.mustache @@ -0,0 +1 @@ +{{#isQueryParam}}@retrofit.http.Query("{{baseName}}") {{#collectionFormat}}{{#isCollectionFormatMulti}}{{{dataType}}}{{/isCollectionFormatMulti}}{{^isCollectionFormatMulti}}{{{collectionFormat.toUpperCase}}}Params{{/isCollectionFormatMulti}}{{/collectionFormat}}{{^collectionFormat}}{{{dataType}}}{{/collectionFormat}} {{paramName}}{{/isQueryParam}} \ No newline at end of file diff --git a/libraries/retrofit2/ApiClient.mustache b/libraries/retrofit2/ApiClient.mustache new file mode 100644 index 00000000000..66d3056e540 --- /dev/null +++ b/libraries/retrofit2/ApiClient.mustache @@ -0,0 +1,420 @@ +package {{invokerPackage}}; + +import com.google.gson.Gson; +import com.google.gson.JsonParseException; +import com.google.gson.JsonElement; +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.RequestBody; +import okhttp3.ResponseBody; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; +{{#joda}} +import org.joda.time.format.DateTimeFormatter; +{{/joda}} +{{#threetenbp}} +import org.threeten.bp.format.DateTimeFormatter; +{{/threetenbp}} +import retrofit2.Converter; +import retrofit2.Retrofit; +{{#useRxJava}} +import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; +{{/useRxJava}} +{{#useRxJava2}} +import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; +{{/useRxJava2}} +import retrofit2.converter.gson.GsonConverterFactory; +import retrofit2.converter.scalars.ScalarsConverterFactory; +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.OAuth; +import {{invokerPackage}}.auth.OAuth.AccessTokenListener; +import {{invokerPackage}}.auth.OAuthFlow; + +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.text.DateFormat; +{{#java8}} +import java.time.format.DateTimeFormatter; +{{/java8}} +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.HashMap; + +public class ApiClient { + + private Map apiAuthorizations; + private OkHttpClient.Builder okBuilder; + private Retrofit.Builder adapterBuilder; + private JSON json; + + public ApiClient() { + apiAuthorizations = new LinkedHashMap(); + createDefaultAdapter(); + } + + public ApiClient(String[] authNames) { + this(); + for(String authName : authNames) { + {{#hasAuthMethods}} + Interceptor auth; + {{#authMethods}}if ("{{name}}".equals(authName)) { + {{#isBasic}} + auth = new HttpBasicAuth(); + {{/isBasic}} + {{#isApiKey}} + auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"); + {{/isApiKey}} + {{#isOAuth}} + auth = new OAuth(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{#hasMore}}, {{/hasMore}}{{/scopes}}"); + {{/isOAuth}} + } else {{/authMethods}}{ + throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); + } + + addAuthorization(authName, auth); + {{/hasAuthMethods}} + {{^hasAuthMethods}} + throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); + {{/hasAuthMethods}} + } + } + + /** + * Basic constructor for single auth name + * @param authName Authentication name + */ + public ApiClient(String authName) { + this(new String[]{authName}); + } + + /** + * Helper constructor for single api key + * @param authName Authentication name + * @param apiKey API key + */ + public ApiClient(String authName, String apiKey) { + this(authName); + this.setApiKey(apiKey); + } + + /** + * Helper constructor for single basic auth or password oauth2 + * @param authName Authentication name + * @param username Username + * @param password Password + */ + public ApiClient(String authName, String username, String password) { + this(authName); + this.setCredentials(username, password); + } + + /** + * Helper constructor for single password oauth2 + * @param authName Authentication name + * @param clientId Client ID + * @param secret Client Secret + * @param username Username + * @param password Password + */ + public ApiClient(String authName, String clientId, String secret, String username, String password) { + this(authName); + this.getTokenEndPoint() + .setClientId(clientId) + .setClientSecret(secret) + .setUsername(username) + .setPassword(password); + } + + public void createDefaultAdapter() { + json = new JSON(); + okBuilder = new OkHttpClient.Builder(); + + String baseUrl = "{{{basePath}}}"; + if (!baseUrl.endsWith("/")) + baseUrl = baseUrl + "/"; + + adapterBuilder = new Retrofit + .Builder() + .baseUrl(baseUrl) + {{#useRxJava}} + .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) + {{/useRxJava}}{{#useRxJava2}} + .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) + {{/useRxJava2}} + .addConverterFactory(ScalarsConverterFactory.create()) + .addConverterFactory(GsonCustomConverterFactory.create(json.getGson())); + } + + public S createService(Class serviceClass) { + return adapterBuilder + .client(okBuilder.build()) + .build() + .create(serviceClass); + } + + public ApiClient setDateFormat(DateFormat dateFormat) { + this.json.setDateFormat(dateFormat); + return this; + } + + public ApiClient setSqlDateFormat(DateFormat dateFormat) { + this.json.setSqlDateFormat(dateFormat); + return this; + } + + {{#joda}} + public ApiClient setDateTimeFormat(DateTimeFormatter dateFormat) { + this.json.setDateTimeFormat(dateFormat); + return this; + } + + public ApiClient setLocalDateFormat(DateTimeFormatter dateFormat) { + this.json.setLocalDateFormat(dateFormat); + return this; + } + + {{/joda}} + {{#jsr310}} + public ApiClient setOffsetDateTimeFormat(DateTimeFormatter dateFormat) { + this.json.setOffsetDateTimeFormat(dateFormat); + return this; + } + + public ApiClient setLocalDateFormat(DateTimeFormatter dateFormat) { + this.json.setLocalDateFormat(dateFormat); + return this; + } + + {{/jsr310}} + + /** + * Helper method to configure the first api key found + * @param apiKey API key + * @return ApiClient + */ + public ApiClient setApiKey(String apiKey) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof ApiKeyAuth) { + ApiKeyAuth keyAuth = (ApiKeyAuth) apiAuthorization; + keyAuth.setApiKey(apiKey); + return this; + } + } + return this; + } + + /** + * Helper method to configure the username/password for basic auth or password oauth + * @param username Username + * @param password Password + * @return ApiClient + */ + public ApiClient setCredentials(String username, String password) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof HttpBasicAuth) { + HttpBasicAuth basicAuth = (HttpBasicAuth) apiAuthorization; + basicAuth.setCredentials(username, password); + return this; + } + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.getTokenRequestBuilder().setUsername(username).setPassword(password); + return this; + } + } + return this; + } + + /** + * Helper method to configure the token endpoint of the first oauth found in the apiAuthorizations (there should be only one) + * @return Token request builder + */ + public TokenRequestBuilder getTokenEndPoint() { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + return oauth.getTokenRequestBuilder(); + } + } + return null; + } + + /** + * Helper method to configure authorization endpoint of the first oauth found in the apiAuthorizations (there should be only one) + * @return Authentication request builder + */ + public AuthenticationRequestBuilder getAuthorizationEndPoint() { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + return oauth.getAuthenticationRequestBuilder(); + } + } + return null; + } + + /** + * Helper method to pre-set the oauth access token of the first oauth found in the apiAuthorizations (there should be only one) + * @param accessToken Access token + * @return ApiClient + */ + public ApiClient setAccessToken(String accessToken) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.setAccessToken(accessToken); + return this; + } + } + return this; + } + + /** + * Helper method to configure the oauth accessCode/implicit flow parameters + * @param clientId Client ID + * @param clientSecret Client secret + * @param redirectURI Redirect URI + * @return ApiClient + */ + public ApiClient configureAuthorizationFlow(String clientId, String clientSecret, String redirectURI) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.getTokenRequestBuilder() + .setClientId(clientId) + .setClientSecret(clientSecret) + .setRedirectURI(redirectURI); + oauth.getAuthenticationRequestBuilder() + .setClientId(clientId) + .setRedirectURI(redirectURI); + return this; + } + } + return this; + } + + /** + * Configures a listener which is notified when a new access token is received. + * @param accessTokenListener Access token listener + * @return ApiClient + */ + public ApiClient registerAccessTokenListener(AccessTokenListener accessTokenListener) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof OAuth) { + OAuth oauth = (OAuth) apiAuthorization; + oauth.registerAccessTokenListener(accessTokenListener); + return this; + } + } + return this; + } + + /** + * Adds an authorization to be used by the client + * @param authName Authentication name + * @param authorization Authorization interceptor + * @return ApiClient + */ + public ApiClient addAuthorization(String authName, Interceptor authorization) { + if (apiAuthorizations.containsKey(authName)) { + throw new RuntimeException("auth name \"" + authName + "\" already in api authorizations"); + } + apiAuthorizations.put(authName, authorization); + okBuilder.addInterceptor(authorization); + return this; + } + + public Map getApiAuthorizations() { + return apiAuthorizations; + } + + public ApiClient setApiAuthorizations(Map apiAuthorizations) { + this.apiAuthorizations = apiAuthorizations; + return this; + } + + public Retrofit.Builder getAdapterBuilder() { + return adapterBuilder; + } + + public ApiClient setAdapterBuilder(Retrofit.Builder adapterBuilder) { + this.adapterBuilder = adapterBuilder; + return this; + } + + public OkHttpClient.Builder getOkBuilder() { + return okBuilder; + } + + public void addAuthsToOkBuilder(OkHttpClient.Builder okBuilder) { + for(Interceptor apiAuthorization : apiAuthorizations.values()) { + okBuilder.addInterceptor(apiAuthorization); + } + } + + /** + * Clones the okBuilder given in parameter, adds the auth interceptors and uses it to configure the Retrofit + * @param okClient An instance of OK HTTP client + */ + public void configureFromOkclient(OkHttpClient okClient) { + this.okBuilder = okClient.newBuilder(); + addAuthsToOkBuilder(this.okBuilder); + } +} + +/** + * This wrapper is to take care of this case: + * when the deserialization fails due to JsonParseException and the + * expected type is String, then just return the body string. + */ +class GsonResponseBodyConverterToString implements Converter { + private final Gson gson; + private final Type type; + + GsonResponseBodyConverterToString(Gson gson, Type type) { + this.gson = gson; + this.type = type; + } + + @Override public T convert(ResponseBody value) throws IOException { + String returned = value.string(); + try { + return gson.fromJson(returned, type); + } + catch (JsonParseException e) { + return (T) returned; + } + } +} + +class GsonCustomConverterFactory extends Converter.Factory +{ + private final Gson gson; + private final GsonConverterFactory gsonConverterFactory; + + public static GsonCustomConverterFactory create(Gson gson) { + return new GsonCustomConverterFactory(gson); + } + + private GsonCustomConverterFactory(Gson gson) { + if (gson == null) + throw new NullPointerException("gson == null"); + this.gson = gson; + this.gsonConverterFactory = GsonConverterFactory.create(gson); + } + + @Override + public Converter responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { + if (type.equals(String.class)) + return new GsonResponseBodyConverterToString(gson, type); + else + return gsonConverterFactory.responseBodyConverter(type, annotations, retrofit); + } + + @Override + public Converter requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { + return gsonConverterFactory.requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit); + } +} diff --git a/libraries/retrofit2/CollectionFormats.mustache b/libraries/retrofit2/CollectionFormats.mustache new file mode 100644 index 00000000000..8c91c335dfc --- /dev/null +++ b/libraries/retrofit2/CollectionFormats.mustache @@ -0,0 +1,95 @@ +package {{invokerPackage}}; + +import java.util.Arrays; +import java.util.List; + +public class CollectionFormats { + + public static class CSVParams { + + protected List params; + + public CSVParams() { + } + + public CSVParams(List params) { + this.params = params; + } + + public CSVParams(String... params) { + this.params = Arrays.asList(params); + } + + public List getParams() { + return params; + } + + public void setParams(List params) { + this.params = params; + } + + @Override + public String toString() { + return StringUtil.join(params.toArray(new String[0]), ","); + } + + } + + public static class SSVParams extends CSVParams { + + public SSVParams() { + } + + public SSVParams(List params) { + super(params); + } + + public SSVParams(String... params) { + super(params); + } + + @Override + public String toString() { + return StringUtil.join(params.toArray(new String[0]), " "); + } + } + + public static class TSVParams extends CSVParams { + + public TSVParams() { + } + + public TSVParams(List params) { + super(params); + } + + public TSVParams(String... params) { + super(params); + } + + @Override + public String toString() { + return StringUtil.join( params.toArray(new String[0]), "\t"); + } + } + + public static class PIPESParams extends CSVParams { + + public PIPESParams() { + } + + public PIPESParams(List params) { + super(params); + } + + public PIPESParams(String... params) { + super(params); + } + + @Override + public String toString() { + return StringUtil.join(params.toArray(new String[0]), "|"); + } + } + +} diff --git a/libraries/retrofit2/JSON.mustache b/libraries/retrofit2/JSON.mustache new file mode 100644 index 00000000000..abab9159d79 --- /dev/null +++ b/libraries/retrofit2/JSON.mustache @@ -0,0 +1,446 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonParseException; +import com.google.gson.TypeAdapter; +import com.google.gson.internal.bind.util.ISO8601Utils; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import com.google.gson.JsonElement; +import io.gsonfire.GsonFireBuilder; +import io.gsonfire.TypeSelector; +{{#joda}} +import org.joda.time.DateTime; +import org.joda.time.LocalDate; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.DateTimeFormatterBuilder; +import org.joda.time.format.ISODateTimeFormat; +{{/joda}} +{{#threetenbp}} +import org.threeten.bp.LocalDate; +import org.threeten.bp.OffsetDateTime; +import org.threeten.bp.format.DateTimeFormatter; +{{/threetenbp}} + +import {{modelPackage}}.*; + +import java.io.IOException; +import java.io.StringReader; +import java.lang.reflect.Type; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.ParsePosition; +{{#java8}} +import java.time.LocalDate; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +{{/java8}} +import java.util.Date; +import java.util.Map; +import java.util.HashMap; + +public class JSON { + private Gson gson; + private DateTypeAdapter dateTypeAdapter = new DateTypeAdapter(); + private SqlDateTypeAdapter sqlDateTypeAdapter = new SqlDateTypeAdapter(); + {{#joda}} + private DateTimeTypeAdapter dateTimeTypeAdapter = new DateTimeTypeAdapter(); + private LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter(); + {{/joda}} + {{#jsr310}} + private OffsetDateTimeTypeAdapter offsetDateTimeTypeAdapter = new OffsetDateTimeTypeAdapter(); + private LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter(); + {{/jsr310}} + + public static GsonBuilder createGson() { + GsonFireBuilder fireBuilder = new GsonFireBuilder() + {{#parent}} + .registerTypeSelector({{classname}}.class, new TypeSelector() { + @Override + public Class getClassForElement(JsonElement readElement) { + Map classByDiscriminatorValue = new HashMap(); + {{#children}} + classByDiscriminatorValue.put("{{name}}".toUpperCase(), {{classname}}.class); + {{/children}} + classByDiscriminatorValue.put("{{classname}}".toUpperCase(), {{classname}}.class); + return getClassByDiscriminator( + classByDiscriminatorValue, + getDiscriminatorValue(readElement, "{{discriminator}}")); + } + }) + {{/parent}} + ; + return fireBuilder.createGsonBuilder(); + } + + private static String getDiscriminatorValue(JsonElement readElement, String discriminatorField) { + JsonElement element = readElement.getAsJsonObject().get(discriminatorField); + if(null == element) { + throw new IllegalArgumentException("missing discriminator field: <" + discriminatorField + ">"); + } + return element.getAsString(); + } + + private static Class getClassByDiscriminator(Map classByDiscriminatorValue, String discriminatorValue) { + Class clazz = (Class) classByDiscriminatorValue.get(discriminatorValue.toUpperCase()); + if(null == clazz) { + throw new IllegalArgumentException("cannot determine model class of name: <" + discriminatorValue + ">"); + } + return clazz; + } + + public JSON() { + gson = createGson() + .registerTypeAdapter(Date.class, dateTypeAdapter) + .registerTypeAdapter(java.sql.Date.class, sqlDateTypeAdapter) + {{#joda}} + .registerTypeAdapter(DateTime.class, dateTimeTypeAdapter) + .registerTypeAdapter(LocalDate.class, localDateTypeAdapter) + {{/joda}} + {{#jsr310}} + .registerTypeAdapter(OffsetDateTime.class, offsetDateTimeTypeAdapter) + .registerTypeAdapter(LocalDate.class, localDateTypeAdapter) + {{/jsr310}} + .create(); + } + + /** + * Get Gson. + * + * @return Gson + */ + public Gson getGson() { + return gson; + } + + /** + * Set Gson. + * + * @param gson Gson + * @return JSON + */ + public JSON setGson(Gson gson) { + this.gson = gson; + return this; + } + + {{#joda}} + /** + * Gson TypeAdapter for Joda DateTime type + */ + public static class DateTimeTypeAdapter extends TypeAdapter { + + private DateTimeFormatter formatter; + + public DateTimeTypeAdapter() { + this(new DateTimeFormatterBuilder() + .append(ISODateTimeFormat.dateTime().getPrinter(), ISODateTimeFormat.dateOptionalTimeParser().getParser()) + .toFormatter()); + } + + public DateTimeTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } + + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } + + @Override + public void write(JsonWriter out, DateTime date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.print(date)); + } + } + + @Override + public DateTime read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + return formatter.parseDateTime(date); + } + } + } + + /** + * Gson TypeAdapter for Joda LocalDate type + */ + public class LocalDateTypeAdapter extends TypeAdapter { + + private DateTimeFormatter formatter; + + public LocalDateTypeAdapter() { + this(ISODateTimeFormat.date()); + } + + public LocalDateTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } + + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } + + @Override + public void write(JsonWriter out, LocalDate date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.print(date)); + } + } + + @Override + public LocalDate read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + return formatter.parseLocalDate(date); + } + } + } + + public JSON setDateTimeFormat(DateTimeFormatter dateFormat) { + dateTimeTypeAdapter.setFormat(dateFormat); + return this; + } + + public JSON setLocalDateFormat(DateTimeFormatter dateFormat) { + localDateTypeAdapter.setFormat(dateFormat); + return this; + } + + {{/joda}} + {{#jsr310}} + /** + * Gson TypeAdapter for JSR310 OffsetDateTime type + */ + public static class OffsetDateTimeTypeAdapter extends TypeAdapter { + + private DateTimeFormatter formatter; + + public OffsetDateTimeTypeAdapter() { + this(DateTimeFormatter.ISO_OFFSET_DATE_TIME); + } + + public OffsetDateTimeTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } + + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } + + @Override + public void write(JsonWriter out, OffsetDateTime date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.format(date)); + } + } + + @Override + public OffsetDateTime read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + if (date.endsWith("+0000")) { + date = date.substring(0, date.length()-5) + "Z"; + } + return OffsetDateTime.parse(date, formatter); + } + } + } + + /** + * Gson TypeAdapter for JSR310 LocalDate type + */ + public class LocalDateTypeAdapter extends TypeAdapter { + + private DateTimeFormatter formatter; + + public LocalDateTypeAdapter() { + this(DateTimeFormatter.ISO_LOCAL_DATE); + } + + public LocalDateTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } + + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } + + @Override + public void write(JsonWriter out, LocalDate date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.format(date)); + } + } + + @Override + public LocalDate read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + return LocalDate.parse(date, formatter); + } + } + } + + public JSON setOffsetDateTimeFormat(DateTimeFormatter dateFormat) { + offsetDateTimeTypeAdapter.setFormat(dateFormat); + return this; + } + + public JSON setLocalDateFormat(DateTimeFormatter dateFormat) { + localDateTypeAdapter.setFormat(dateFormat); + return this; + } + + {{/jsr310}} + /** + * Gson TypeAdapter for java.sql.Date type + * If the dateFormat is null, a simple "yyyy-MM-dd" format will be used + * (more efficient than SimpleDateFormat). + */ + public static class SqlDateTypeAdapter extends TypeAdapter { + + private DateFormat dateFormat; + + public SqlDateTypeAdapter() { + } + + public SqlDateTypeAdapter(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + public void setFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + @Override + public void write(JsonWriter out, java.sql.Date date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + String value; + if (dateFormat != null) { + value = dateFormat.format(date); + } else { + value = date.toString(); + } + out.value(value); + } + } + + @Override + public java.sql.Date read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + try { + if (dateFormat != null) { + return new java.sql.Date(dateFormat.parse(date).getTime()); + } + return new java.sql.Date(ISO8601Utils.parse(date, new ParsePosition(0)).getTime()); + } catch (ParseException e) { + throw new JsonParseException(e); + } + } + } + } + + /** + * Gson TypeAdapter for java.util.Date type + * If the dateFormat is null, ISO8601Utils will be used. + */ + public static class DateTypeAdapter extends TypeAdapter { + + private DateFormat dateFormat; + + public DateTypeAdapter() { + } + + public DateTypeAdapter(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + public void setFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + @Override + public void write(JsonWriter out, Date date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + String value; + if (dateFormat != null) { + value = dateFormat.format(date); + } else { + value = ISO8601Utils.format(date, true); + } + out.value(value); + } + } + + @Override + public Date read(JsonReader in) throws IOException { + try { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + try { + if (dateFormat != null) { + return dateFormat.parse(date); + } + return ISO8601Utils.parse(date, new ParsePosition(0)); + } catch (ParseException e) { + throw new JsonParseException(e); + } + } + } catch (IllegalArgumentException e) { + throw new JsonParseException(e); + } + } + } + + public JSON setDateFormat(DateFormat dateFormat) { + dateTypeAdapter.setFormat(dateFormat); + return this; + } + + public JSON setSqlDateFormat(DateFormat dateFormat) { + sqlDateTypeAdapter.setFormat(dateFormat); + return this; + } + +} diff --git a/libraries/retrofit2/README.mustache b/libraries/retrofit2/README.mustache new file mode 100644 index 00000000000..9d744b8589e --- /dev/null +++ b/libraries/retrofit2/README.mustache @@ -0,0 +1,39 @@ +# {{artifactId}} + +## Requirements + +Building the API client library requires [Maven](https://maven.apache.org/) to be installed. + +## Installation & Usage + +To install the API client library to your local Maven repository, simply execute: + +```shell +mvn install +``` + +To deploy it to a remote Maven repository instead, configure the settings of the repository and execute: + +```shell +mvn deploy +``` + +Refer to the [official documentation](https://maven.apache.org/plugins/maven-deploy-plugin/usage.html) for more information. + +After the client library is installed/deployed, you can use it in your Maven project by adding the following to your *pom.xml*: + +```xml + + {{groupId}} + {{artifactId}} + {{artifactVersion}} + compile + + +``` + +## Author + +{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} +{{/hasMore}}{{/apis}}{{/apiInfo}} + diff --git a/libraries/retrofit2/api.mustache b/libraries/retrofit2/api.mustache new file mode 100644 index 00000000000..f6eb4c2dd07 --- /dev/null +++ b/libraries/retrofit2/api.mustache @@ -0,0 +1,77 @@ +package {{package}}; + +import {{invokerPackage}}.CollectionFormats.*; + +{{#useRxJava}} +import rx.Observable; +{{/useRxJava}} +{{#useRxJava2}} +import io.reactivex.Observable; +{{/useRxJava2}} +{{^returnType}} +{{#useRxJava2}} +import io.reactivex.Completable; +{{/useRxJava2}} +{{/returnType}} +{{#doNotUseRx}} +import retrofit2.Call; +{{/doNotUseRx}} +import retrofit2.http.*; + +import okhttp3.RequestBody; +import okhttp3.ResponseBody; +import okhttp3.MultipartBody; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +{{#operations}} +public interface {{classname}} { + {{#operation}} + /** + * {{summary}} + * {{notes}} +{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} +{{/allParams}} + * @return {{^doNotUseRx}}{{#useRxJava}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/useRxJava}}{{#useRxJava2}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{returnType}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{/doNotUseRx}}{{#doNotUseRx}}Call<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/doNotUseRx}} +{{#isDeprecated}} + * @deprecated +{{/isDeprecated}} +{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation +{{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + {{#formParams}} + {{#-first}} + {{#isMultipart}}@retrofit2.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit2.http.FormUrlEncoded{{/isMultipart}} + {{/-first}} + {{/formParams}} + {{^formParams}} + {{#prioritizedContentTypes}} + {{#-first}} + @Headers({ + "Content-Type:{{{mediaType}}}" + }) + {{/-first}} + {{/prioritizedContentTypes}} + {{/formParams}} + @{{httpMethod}}("{{{path}}}") + {{^doNotUseRx}}{{#useRxJava}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/useRxJava}}{{#useRxJava2}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{{returnType}}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{/doNotUseRx}}{{#doNotUseRx}}Call<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/doNotUseRx}} {{operationId}}({{^allParams}});{{/allParams}} + {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{#hasMore}}, {{/hasMore}}{{^hasMore}} + );{{/hasMore}}{{/allParams}} + + {{/operation}} +} +{{/operations}} diff --git a/libraries/retrofit2/api_test.mustache b/libraries/retrofit2/api_test.mustache new file mode 100644 index 00000000000..0a85ef5095c --- /dev/null +++ b/libraries/retrofit2/api_test.mustache @@ -0,0 +1,46 @@ +package {{package}}; + +import {{invokerPackage}}.ApiClient; +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Before; +import org.junit.Test; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +public class {{classname}}Test { + + private {{classname}} api; + + @Before + public void setup() { + api = new ApiClient().createService({{classname}}.class); + } + + {{#operations}} + {{#operation}} + /** + * {{summary}} + * + * {{notes}} + */ + @Test + public void {{operationId}}Test() { + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + // {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + + // TODO: test validations + } + {{/operation}} + {{/operations}} +} diff --git a/libraries/retrofit2/auth/ApiKeyAuth.mustache b/libraries/retrofit2/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..2f4bae3dd02 --- /dev/null +++ b/libraries/retrofit2/auth/ApiKeyAuth.mustache @@ -0,0 +1,68 @@ +package {{invokerPackage}}.auth; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +public class ApiKeyAuth implements Interceptor { + private final String location; + private final String paramName; + + private String apiKey; + + public ApiKeyAuth(String location, String paramName) { + this.location = location; + this.paramName = paramName; + } + + public String getLocation() { + return location; + } + + public String getParamName() { + return paramName; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + @Override + public Response intercept(Chain chain) throws IOException { + String paramValue; + Request request = chain.request(); + + if ("query".equals(location)) { + String newQuery = request.url().uri().getQuery(); + paramValue = paramName + "=" + apiKey; + if (newQuery == null) { + newQuery = paramValue; + } else { + newQuery += "&" + paramValue; + } + + URI newUri; + try { + newUri = new URI(request.url().uri().getScheme(), request.url().uri().getAuthority(), + request.url().uri().getPath(), newQuery, request.url().uri().getFragment()); + } catch (URISyntaxException e) { + throw new IOException(e); + } + + request = request.newBuilder().url(newUri.toURL()).build(); + } else if ("header".equals(location)) { + request = request.newBuilder() + .addHeader(paramName, apiKey) + .build(); + } + return chain.proceed(request); + } +} diff --git a/libraries/retrofit2/auth/HttpBasicAuth.mustache b/libraries/retrofit2/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..d4588426662 --- /dev/null +++ b/libraries/retrofit2/auth/HttpBasicAuth.mustache @@ -0,0 +1,50 @@ +package {{invokerPackage}}.auth; + +import java.io.IOException; + +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.Credentials; + +public class HttpBasicAuth implements Interceptor { + + private String username; + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public void setCredentials(String username, String password) { + this.username = username; + this.password = password; + } + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + + // If the request already have an authorization (eg. Basic auth), do nothing + if (request.header("Authorization") == null) { + String credentials = Credentials.basic(username, password); + request = request.newBuilder() + .addHeader("Authorization", credentials) + .build(); + } + return chain.proceed(request); + } +} diff --git a/libraries/retrofit2/auth/OAuth.mustache b/libraries/retrofit2/auth/OAuth.mustache new file mode 100644 index 00000000000..80ec7b3946c --- /dev/null +++ b/libraries/retrofit2/auth/OAuth.mustache @@ -0,0 +1,185 @@ +package {{invokerPackage}}.auth; + +import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; +import static java.net.HttpURLConnection.HTTP_FORBIDDEN; + +import java.io.IOException; +import java.util.Map; + +import org.apache.oltu.oauth2.client.OAuthClient; +import org.apache.oltu.oauth2.client.request.OAuthBearerClientRequest; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; +import org.apache.oltu.oauth2.client.response.OAuthJSONAccessTokenResponse; +import org.apache.oltu.oauth2.common.exception.OAuthProblemException; +import org.apache.oltu.oauth2.common.exception.OAuthSystemException; +import org.apache.oltu.oauth2.common.message.types.GrantType; +import org.apache.oltu.oauth2.common.token.BasicOAuthToken; + +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Request.Builder; +import okhttp3.Response; + +public class OAuth implements Interceptor { + + public interface AccessTokenListener { + public void notify(BasicOAuthToken token); + } + + private volatile String accessToken; + private OAuthClient oauthClient; + + private TokenRequestBuilder tokenRequestBuilder; + private AuthenticationRequestBuilder authenticationRequestBuilder; + + private AccessTokenListener accessTokenListener; + + public OAuth( OkHttpClient client, TokenRequestBuilder requestBuilder ) { + this.oauthClient = new OAuthClient(new OAuthOkHttpClient(client)); + this.tokenRequestBuilder = requestBuilder; + } + + public OAuth(TokenRequestBuilder requestBuilder ) { + this(new OkHttpClient(), requestBuilder); + } + + public OAuth(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { + this(OAuthClientRequest.tokenLocation(tokenUrl).setScope(scopes)); + setFlow(flow); + authenticationRequestBuilder = OAuthClientRequest.authorizationLocation(authorizationUrl); + } + + public void setFlow(OAuthFlow flow) { + switch(flow) { + case accessCode: + case implicit: + tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE); + break; + case password: + tokenRequestBuilder.setGrantType(GrantType.PASSWORD); + break; + case application: + tokenRequestBuilder.setGrantType(GrantType.CLIENT_CREDENTIALS); + break; + default: + break; + } + } + + @Override + public Response intercept(Chain chain) + throws IOException { + + return retryingIntercept(chain, true); + } + + private Response retryingIntercept(Chain chain, boolean updateTokenAndRetryOnAuthorizationFailure) throws IOException { + Request request = chain.request(); + + // If the request already have an authorization (eg. Basic auth), do nothing + if (request.header("Authorization") != null) { + return chain.proceed(request); + } + + // If first time, get the token + OAuthClientRequest oAuthRequest; + if (getAccessToken() == null) { + updateAccessToken(null); + } + + if (getAccessToken() != null) { + // Build the request + Builder rb = request.newBuilder(); + + String requestAccessToken = new String(getAccessToken()); + try { + oAuthRequest = new OAuthBearerClientRequest(request.url().toString()) + .setAccessToken(requestAccessToken) + .buildHeaderMessage(); + } catch (OAuthSystemException e) { + throw new IOException(e); + } + + for ( Map.Entry header : oAuthRequest.getHeaders().entrySet() ) { + rb.addHeader(header.getKey(), header.getValue()); + } + rb.url( oAuthRequest.getLocationUri()); + + //Execute the request + Response response = chain.proceed(rb.build()); + + // 401/403 most likely indicates that access token has expired. Unless it happens two times in a row. + if ( response != null && (response.code() == HTTP_UNAUTHORIZED || response.code() == HTTP_FORBIDDEN) && updateTokenAndRetryOnAuthorizationFailure ) { + try { + if (updateAccessToken(requestAccessToken)) { + response.body().close(); + return retryingIntercept( chain, false ); + } + } catch (Exception e) { + response.body().close(); + throw e; + } + } + return response; + } else { + return chain.proceed(chain.request()); + } + } + + /* + * Returns true if the access token has been updated + */ + public synchronized boolean updateAccessToken(String requestAccessToken) throws IOException { + if (getAccessToken() == null || getAccessToken().equals(requestAccessToken)) { + try { + OAuthJSONAccessTokenResponse accessTokenResponse = oauthClient.accessToken(this.tokenRequestBuilder.buildBodyMessage()); + if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { + setAccessToken(accessTokenResponse.getAccessToken()); + if (accessTokenListener != null) { + accessTokenListener.notify((BasicOAuthToken) accessTokenResponse.getOAuthToken()); + } + return !getAccessToken().equals(requestAccessToken); + } else { + return false; + } + } catch (OAuthSystemException e) { + throw new IOException(e); + } catch (OAuthProblemException e) { + throw new IOException(e); + } + } + return true; + } + + public void registerAccessTokenListener(AccessTokenListener accessTokenListener) { + this.accessTokenListener = accessTokenListener; + } + + public synchronized String getAccessToken() { + return accessToken; + } + + public synchronized void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + public TokenRequestBuilder getTokenRequestBuilder() { + return tokenRequestBuilder; + } + + public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) { + this.tokenRequestBuilder = tokenRequestBuilder; + } + + public AuthenticationRequestBuilder getAuthenticationRequestBuilder() { + return authenticationRequestBuilder; + } + + public void setAuthenticationRequestBuilder(AuthenticationRequestBuilder authenticationRequestBuilder) { + this.authenticationRequestBuilder = authenticationRequestBuilder; + } + +} diff --git a/libraries/retrofit2/auth/OAuthOkHttpClient.mustache b/libraries/retrofit2/auth/OAuthOkHttpClient.mustache new file mode 100644 index 00000000000..423fa1ba0e5 --- /dev/null +++ b/libraries/retrofit2/auth/OAuthOkHttpClient.mustache @@ -0,0 +1,72 @@ +package {{invokerPackage}}.auth; + +import java.io.IOException; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.oltu.oauth2.client.HttpClient; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest; +import org.apache.oltu.oauth2.client.response.OAuthClientResponse; +import org.apache.oltu.oauth2.client.response.OAuthClientResponseFactory; +import org.apache.oltu.oauth2.common.exception.OAuthProblemException; +import org.apache.oltu.oauth2.common.exception.OAuthSystemException; + + +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Request.Builder; +import okhttp3.Response; +import okhttp3.MediaType; +import okhttp3.RequestBody; + + +public class OAuthOkHttpClient implements HttpClient { + + private OkHttpClient client; + + public OAuthOkHttpClient() { + this.client = new OkHttpClient(); + } + + public OAuthOkHttpClient(OkHttpClient client) { + this.client = client; + } + + public T execute(OAuthClientRequest request, Map headers, + String requestMethod, Class responseClass) + throws OAuthSystemException, OAuthProblemException { + + MediaType mediaType = MediaType.parse("application/json"); + Request.Builder requestBuilder = new Request.Builder().url(request.getLocationUri()); + + if(headers != null) { + for (Entry entry : headers.entrySet()) { + if (entry.getKey().equalsIgnoreCase("Content-Type")) { + mediaType = MediaType.parse(entry.getValue()); + } else { + requestBuilder.addHeader(entry.getKey(), entry.getValue()); + } + } + } + + RequestBody body = request.getBody() != null ? RequestBody.create(mediaType, request.getBody()) : null; + requestBuilder.method(requestMethod, body); + + try { + Response response = client.newCall(requestBuilder.build()).execute(); + return OAuthClientResponseFactory.createCustomResponse( + response.body().string(), + response.body().contentType().toString(), + response.code(), + responseClass); + } catch (IOException e) { + throw new OAuthSystemException(e); + } + } + + public void shutdown() { + // Nothing to do here + } + +} diff --git a/libraries/retrofit2/bodyParams.mustache b/libraries/retrofit2/bodyParams.mustache new file mode 100644 index 00000000000..97b03fcb717 --- /dev/null +++ b/libraries/retrofit2/bodyParams.mustache @@ -0,0 +1 @@ +{{#isBodyParam}}@retrofit2.http.Body {{{dataType}}} {{paramName}}{{/isBodyParam}} \ No newline at end of file diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache new file mode 100644 index 00000000000..f341375f821 --- /dev/null +++ b/libraries/retrofit2/build.gradle.mustache @@ -0,0 +1,164 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + } + compileOptions { + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + sourceCompatibility = JavaVersion.VERSION_{{^java8}}1_7{{/java8}}{{#java8}}1_8{{/java8}} + targetCompatibility = JavaVersion.VERSION_{{^java8}}1_7{{/java8}}{{#java8}}1_8{{/java8}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + oltu_version = "1.0.1" + retrofit_version = "2.3.0" + {{#usePlayWS}} + {{#play24}} + jackson_version = "2.6.6" + play_version = "2.4.11" + {{/play24}} + {{#play25}} + jackson_version = "2.7.8" + play_version = "2.5.14" + {{/play25}} + {{/usePlayWS}} + swagger_annotations_version = "1.5.17" + junit_version = "4.12" + {{#useRxJava}} + rx_java_version = "1.3.0" + {{/useRxJava}} + {{#useRxJava2}} + rx_java_version = "2.1.1" + {{/useRxJava2}} + {{#joda}} + jodatime_version = "2.9.9" + {{/joda}} + {{#threetenbp}} + threetenbp_version = "1.3.5" + {{/threetenbp}} + json_fire_version = "1.8.0" +} + +dependencies { + compile "com.squareup.retrofit2:retrofit:$retrofit_version" + compile "com.squareup.retrofit2:converter-scalars:$retrofit_version" + compile "com.squareup.retrofit2:converter-gson:$retrofit_version" + {{#useRxJava}} + compile "com.squareup.retrofit2:adapter-rxjava:$retrofit_version" + compile "io.reactivex:rxjava:$rx_java_version" + {{/useRxJava}} + {{#useRxJava2}} + compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' + compile "io.reactivex.rxjava2:rxjava:$rx_java_version" + {{/useRxJava2}} + compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile ("org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version"){ + exclude group:'org.apache.oltu.oauth2' , module: 'org.apache.oltu.oauth2.common' + } + compile "io.gsonfire:gson-fire:$json_fire_version" + {{#joda}} + compile "joda-time:joda-time:$jodatime_version" + {{/joda}} + {{#threetenbp}} + compile "org.threeten:threetenbp:$threetenbp_version" + {{/threetenbp}} + {{#usePlayWS}} + compile "com.typesafe.play:play-java-ws_2.11:$play_version" + compile "com.squareup.retrofit2:converter-jackson:$retrofit_version" + compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + compile "com.fasterxml.jackson.datatype:jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}:$jackson_version" + {{/usePlayWS}} + + testCompile "junit:junit:$junit_version" +} diff --git a/libraries/retrofit2/build.sbt.mustache b/libraries/retrofit2/build.sbt.mustache new file mode 100644 index 00000000000..66635daa973 --- /dev/null +++ b/libraries/retrofit2/build.sbt.mustache @@ -0,0 +1,52 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "com.squareup.retrofit2" % "retrofit" % "2.3.0" % "compile", + "com.squareup.retrofit2" % "converter-scalars" % "2.3.0" % "compile", + {{^usePlayWS}} + "com.squareup.retrofit2" % "converter-gson" % "2.3.0" % "compile", + {{/usePlayWS}} + {{#usePlayWS}} + {{#play24}} + "com.typesafe.play" % "play-java-ws_2.11" % "2.4.11" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.6.6" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.6.6" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.6.6" % "compile", + {{/play24}} + {{#play25}} + "com.typesafe.play" % "play-java-ws_2.11" % "2.5.15" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.7.8" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.7.8" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.7.8" % "compile", + {{/play25}} + "com.squareup.retrofit2" % "converter-jackson" % "2.3.0" % "compile", + {{/usePlayWS}} + {{#useRxJava}} + "com.squareup.retrofit2" % "adapter-rxjava" % "2.3.0" % "compile", + "io.reactivex" % "rxjava" % "1.3.0" % "compile", + {{/useRxJava}} + {{#useRxJava2}} + "com.squareup.retrofit2" % "adapter-rxjava2" % "2.3.0" % "compile", + "io.reactivex.rxjava2" % "rxjava" % "2.1.1" % "compile", + {{/useRxJava2}} + "io.swagger" % "swagger-annotations" % "1.5.17" % "compile", + "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", + {{#joda}} + "joda-time" % "joda-time" % "2.9.9" % "compile", + {{/joda}} + {{#threetenbp}} + "org.threeten" % "threetenbp" % "1.3.5" % "compile", + {{/threetenbp}} + "io.gsonfire" % "gson-fire" % "1.8.0" % "compile", + "junit" % "junit" % "4.12" % "test", + "com.novocode" % "junit-interface" % "0.11" % "test" + ) + ) diff --git a/libraries/retrofit2/formParams.mustache b/libraries/retrofit2/formParams.mustache new file mode 100644 index 00000000000..b3f54cc4ddb --- /dev/null +++ b/libraries/retrofit2/formParams.mustache @@ -0,0 +1 @@ +{{#isFormParam}}{{#notFile}}{{#isMultipart}}@retrofit2.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit2.http.Field{{/isMultipart}}("{{baseName}}") {{{dataType}}} {{paramName}}{{/notFile}}{{#isFile}}{{#isMultipart}}@retrofit2.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit2.http.Field{{/isMultipart}} MultipartBody.Part {{paramName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file diff --git a/libraries/retrofit2/formParams.mustache.save b/libraries/retrofit2/formParams.mustache.save new file mode 100644 index 00000000000..84c4704432a --- /dev/null +++ b/libraries/retrofit2/formParams.mustache.save @@ -0,0 +1 @@ +{{#isFormParam}}{{#notFile}}{{#isMultipart}}retrofit.http@retrofit2.http.Part{{/isMultipart}}{{^isMultipart}}@Field{{/isMultipart}}("{{baseName}}") {{{dataType}}} {{paramName}}{{/notFile}}{{#isFile}}{{#isMultipart}}@Part{{/isMultipart}}{{^isMultipart}}@Field{{/isMultipart}} okhttp3.MultipartBody.Part {{paramName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file diff --git a/libraries/retrofit2/headerParams.mustache b/libraries/retrofit2/headerParams.mustache new file mode 100644 index 00000000000..c7748f3bf27 --- /dev/null +++ b/libraries/retrofit2/headerParams.mustache @@ -0,0 +1 @@ +{{#isHeaderParam}}@retrofit2.http.Header("{{baseName}}") {{{dataType}}} {{paramName}}{{/isHeaderParam}} \ No newline at end of file diff --git a/libraries/retrofit2/pathParams.mustache b/libraries/retrofit2/pathParams.mustache new file mode 100644 index 00000000000..8fe7c380c41 --- /dev/null +++ b/libraries/retrofit2/pathParams.mustache @@ -0,0 +1 @@ +{{#isPathParam}}@retrofit2.http.Path("{{baseName}}") {{{dataType}}} {{paramName}}{{/isPathParam}} \ No newline at end of file diff --git a/libraries/retrofit2/play-common/auth/ApiKeyAuth.mustache b/libraries/retrofit2/play-common/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..5652db326b5 --- /dev/null +++ b/libraries/retrofit2/play-common/auth/ApiKeyAuth.mustache @@ -0,0 +1,67 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; + +import java.util.Map; +import java.util.List; + +/** + * Holds ApiKey auth info + */ +{{>generatedAnnotation}} +public class ApiKeyAuth implements Authentication { + private final String location; + private final String paramName; + + private String apiKey; + private String apiKeyPrefix; + + public ApiKeyAuth(String location, String paramName) { + this.location = location; + this.paramName = paramName; + } + + public String getLocation() { + return location; + } + + public String getParamName() { + return paramName; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + public String getApiKeyPrefix() { + return apiKeyPrefix; + } + + public void setApiKeyPrefix(String apiKeyPrefix) { + this.apiKeyPrefix = apiKeyPrefix; + } + + @Override + public void applyToParams(List queryParams, Map headerParams) { + if (apiKey == null) { + return; + } + String value; + if (apiKeyPrefix != null) { + value = apiKeyPrefix + " " + apiKey; + } else { + value = apiKey; + } + if ("query".equals(location)) { + queryParams.add(new Pair(paramName, value)); + } else if ("header".equals(location)) { + headerParams.put(paramName, value); + } + } +} diff --git a/libraries/retrofit2/play24/ApiClient.mustache b/libraries/retrofit2/play24/ApiClient.mustache new file mode 100644 index 00000000000..5c871c62073 --- /dev/null +++ b/libraries/retrofit2/play24/ApiClient.mustache @@ -0,0 +1,136 @@ +package {{invokerPackage}}; + +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.*; + +import retrofit2.Retrofit; +import retrofit2.converter.scalars.ScalarsConverterFactory; +import retrofit2.converter.jackson.JacksonConverterFactory; + +import play.libs.Json; +import play.libs.ws.WSClient; + +import {{invokerPackage}}.Play24CallAdapterFactory; +import {{invokerPackage}}.Play24CallFactory; + +import okhttp3.Interceptor; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.Authentication; + +/** + * API client + */ +public class ApiClient { + + /** Underlying HTTP-client */ + private WSClient wsClient; + + /** Supported auths */ + private Map authentications; + + /** API base path */ + private String basePath = "{{{basePath}}}"; + + public ApiClient(WSClient wsClient) { + this(); + this.wsClient = wsClient; + } + + public ApiClient() { + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap<>();{{#authMethods}}{{#isBasic}} + // authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + // authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + + } + + /** + * Creates a retrofit2 client for given API interface + */ + public S createService(Class serviceClass) { + if(!basePath.endsWith("/")) { + basePath = basePath + "/"; + } + + Map extraHeaders = new HashMap<>(); + List extraQueryParams = new ArrayList<>(); + + for (String authName : authentications.keySet()) { + Authentication auth = authentications.get(authName); + if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + + auth.applyToParams(extraQueryParams, extraHeaders); + } + + return new Retrofit.Builder() + .baseUrl(basePath) + .addConverterFactory(ScalarsConverterFactory.create()) + .addConverterFactory(JacksonConverterFactory.create(Json.mapper())) + .callFactory(new Play24CallFactory(wsClient, extraHeaders, extraQueryParams)) + .addCallAdapterFactory(new Play24CallAdapterFactory()) + .build() + .create(serviceClass); + } + + /** + * Helper method to set API base path + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Get authentications (key: authentication name, value: authentication). + */ + public Map getAuthentications() { + return authentications; + } + + /** + * Get authentication for the given name. + * + * @param authName The authentication name + * @return The authentication, null if not found + */ + public Authentication getAuthentication(String authName) { + return authentications.get(authName); + } + + /** + * Helper method to set API key value for the first API key authentication. + */ + public ApiClient setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return this; + } + } + + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + */ + public ApiClient setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return this; + } + } + + throw new RuntimeException("No API key authentication configured!"); + } + + +} + + diff --git a/libraries/retrofit2/play24/Play24CallAdapterFactory.mustache b/libraries/retrofit2/play24/Play24CallAdapterFactory.mustache new file mode 100644 index 00000000000..be7cac4a0d5 --- /dev/null +++ b/libraries/retrofit2/play24/Play24CallAdapterFactory.mustache @@ -0,0 +1,100 @@ +package {{invokerPackage}}; + +import play.libs.F; +import retrofit2.*; + +import java.lang.annotation.Annotation; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.WildcardType; + +/** + * Creates {@link CallAdapter} instances that convert {@link Call} into {@link play.libs.F.Promise} + */ +public class Play24CallAdapterFactory extends CallAdapter.Factory { + + @Override + public CallAdapter get(Type returnType, Annotation[] annotations, Retrofit retrofit) { + if (!(returnType instanceof ParameterizedType)) { + return null; + } + + ParameterizedType type = (ParameterizedType) returnType; + if (type.getRawType() != F.Promise.class) { + return null; + } + + return createAdapter((ParameterizedType) returnType); + } + + private CallAdapter> createAdapter(ParameterizedType returnType) { + Type[] types = returnType.getActualTypeArguments(); + if (types.length != 1) { + throw new IllegalStateException("Must be exactly one type parameter"); + } + + Type resultType = types[0]; + Class rawTypeParam = getRawType(resultType); + + boolean includeResponse = false; + if (rawTypeParam == Response.class) { + if (!(resultType instanceof ParameterizedType)) { + throw new IllegalStateException("Response must be parameterized" + + " as Response"); + } + resultType = ((ParameterizedType) resultType).getActualTypeArguments()[0]; + includeResponse = true; + } + + return new ValueAdapter(resultType, includeResponse); + } + + /** + * Adapter that coverts values returned by API interface into CompletionStage + */ + private static final class ValueAdapter implements CallAdapter> { + + private final Type responseType; + private final boolean includeResponse; + + ValueAdapter(Type responseType, boolean includeResponse) { + this.responseType = responseType; + this.includeResponse = includeResponse; + } + + @Override + public Type responseType() { + return responseType; + } + + @Override + public F.Promise adapt(final Call call) { + final F.RedeemablePromise promise = F.RedeemablePromise.empty(); + + call.enqueue(new Callback() { + + @Override + public void onResponse(Call call, Response response) { + if (response.isSuccessful()) { + if (includeResponse) { + promise.success((R) response); + } else { + promise.success(response.body()); + } + } else { + promise.failure(new HttpException(response)); + } + } + + @Override + public void onFailure(Call call, Throwable t) { + promise.failure(t); + } + + }); + + return promise; + } + } + +} diff --git a/libraries/retrofit2/play24/Play24CallFactory.mustache b/libraries/retrofit2/play24/Play24CallFactory.mustache new file mode 100644 index 00000000000..5572ac47619 --- /dev/null +++ b/libraries/retrofit2/play24/Play24CallFactory.mustache @@ -0,0 +1,219 @@ +package {{invokerPackage}}; + +import okhttp3.*; +import okio.Buffer; +import okio.BufferedSource; +import play.libs.F; +import play.libs.ws.WSClient; +import play.libs.ws.WSRequest; +import play.libs.ws.WSResponse; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * Creates {@link Call} instances that invoke underlying {@link WSClient} + */ +public class Play24CallFactory implements okhttp3.Call.Factory { + + /** PlayWS http client */ + private final WSClient wsClient; + + /** Extra headers to add to request */ + private Map extraHeaders = new HashMap<>(); + + /** Extra query parameters to add to request */ + private List extraQueryParams = new ArrayList<>(); + + public Play24CallFactory(WSClient wsClient) { + this.wsClient = wsClient; + } + + public Play24CallFactory(WSClient wsClient, Map extraHeaders, + List extraQueryParams) { + this.wsClient = wsClient; + + this.extraHeaders.putAll(extraHeaders); + this.extraQueryParams.addAll(extraQueryParams); + } + + @Override + public Call newCall(Request request) { + // add extra headers + Request.Builder rb = request.newBuilder(); + for (Map.Entry header : this.extraHeaders.entrySet()) { + rb.addHeader(header.getKey(), header.getValue()); + } + + // add extra query params + if (!this.extraQueryParams.isEmpty()) { + String newQuery = request.url().uri().getQuery(); + for (Pair queryParam : this.extraQueryParams) { + String param = String.format("%s=%s", queryParam.getName(), queryParam.getValue()); + if (newQuery == null) { + newQuery = param; + } else { + newQuery += "&" + param; + } + } + + URI newUri; + try { + newUri = new URI(request.url().uri().getScheme(), request.url().uri().getAuthority(), + request.url().uri().getPath(), newQuery, request.url().uri().getFragment()); + rb.url(newUri.toURL()); + } catch (MalformedURLException | URISyntaxException e) { + throw new RuntimeException("Error while updating an url", e); + } + } + + return new PlayWSCall(wsClient, rb.build()); + } + + /** + * Call implementation that delegates to Play WS Client + */ + static class PlayWSCall implements Call { + + private final WSClient wsClient; + private WSRequest wsRequest; + + private final Request request; + + public PlayWSCall(WSClient wsClient, Request request) { + this.wsClient = wsClient; + this.request = request; + } + + @Override + public Request request() { + return request; + } + + @Override + public void enqueue(final okhttp3.Callback responseCallback) { + final Call call = this; + final F.Promise promise = executeAsync(); + + promise.onRedeem(new F.Callback() { + + @Override + public void invoke(WSResponse wsResponse) throws Throwable { + responseCallback.onResponse(call, PlayWSCall.this.toWSResponse(wsResponse)); + } + + }); + + promise.onFailure(new F.Callback() { + + @Override + public void invoke(Throwable throwable) throws Throwable { + if (throwable instanceof IOException) { + responseCallback.onFailure(call, (IOException) throwable); + } else { + responseCallback.onFailure(call, new IOException(throwable)); + } + } + + }); + + } + + F.Promise executeAsync() { + try { + wsRequest = wsClient.url(request.url().uri().toString()); + addHeaders(wsRequest); + if (request.body() != null) { + addBody(wsRequest); + } + + return wsRequest.execute(request.method()); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + private void addHeaders(WSRequest wsRequest) { + for(Map.Entry> entry : request.headers().toMultimap().entrySet()) { + List values = entry.getValue(); + for (String value : values) { + wsRequest.setHeader(entry.getKey(), value); + } + } + } + + private void addBody(WSRequest wsRequest) throws IOException { + Buffer buffer = new Buffer(); + request.body().writeTo(buffer); + wsRequest.setBody(buffer.inputStream()); + wsRequest.setContentType(request.body().contentType().toString()); + } + + private Response toWSResponse(final WSResponse r) { + final Response.Builder builder = new Response.Builder(); + builder.request(request) + .code(r.getStatus()) + .body(new ResponseBody() { + + @Override + public MediaType contentType() { + return Optional.ofNullable(r.getHeader("Content-Type")) + .map(MediaType::parse) + .orElse(null); + } + + @Override + public long contentLength() { + return r.asByteArray().length; + } + + @Override + public BufferedSource source() { + return new Buffer().write(r.asByteArray()); + } + + }); + + for (Map.Entry> entry : r.getAllHeaders().entrySet()) { + for (String value : entry.getValue()) { + builder.addHeader(entry.getKey(), value); + } + } + + builder.protocol(Protocol.HTTP_1_1); + return builder.build(); + } + + @Override + public Response execute() throws IOException { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public void cancel() { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public PlayWSCall clone() { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public boolean isExecuted() { + return false; + } + + @Override + public boolean isCanceled() { + return false; + } + } +} diff --git a/libraries/retrofit2/play24/api.mustache b/libraries/retrofit2/play24/api.mustache new file mode 100644 index 00000000000..6538ed53d2f --- /dev/null +++ b/libraries/retrofit2/play24/api.mustache @@ -0,0 +1,57 @@ +package {{package}}; + +import {{invokerPackage}}.CollectionFormats.*; + +{{#useRxJava}}import rx.Observable;{{/useRxJava}} +{{#useRxJava2}}import io.reactivex.Observable;{{/useRxJava2}} +{{#doNotUseRx}}import retrofit2.Call;{{/doNotUseRx}} +import retrofit2.http.*; + +import okhttp3.RequestBody; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +import play.libs.F; +import retrofit2.Response; + +{{#operations}} +public interface {{classname}} { + {{#operation}} + /** + * {{summary}} + * {{notes}} +{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} +{{/allParams}} + * @return Call<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + */ + {{#formParams}} + {{#-first}} + {{#isMultipart}}@retrofit2.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit2.http.FormUrlEncoded{{/isMultipart}} + {{/-first}} + {{/formParams}} + {{^formParams}} + {{#prioritizedContentTypes}} + {{#-first}} + @Headers({ + "Content-Type:{{{mediaType}}}" + }) + {{/-first}} + {{/prioritizedContentTypes}} + {{/formParams}} + @{{httpMethod}}("{{{path}}}") + F.Promise> {{operationId}}({{^allParams}});{{/allParams}} + {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{#hasMore}}, {{/hasMore}}{{^hasMore}} + );{{/hasMore}}{{/allParams}} + + {{/operation}} +} +{{/operations}} diff --git a/libraries/retrofit2/play25/ApiClient.mustache b/libraries/retrofit2/play25/ApiClient.mustache new file mode 100644 index 00000000000..163afd670c1 --- /dev/null +++ b/libraries/retrofit2/play25/ApiClient.mustache @@ -0,0 +1,136 @@ +package {{invokerPackage}}; + +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.*; + +import retrofit2.Retrofit; +import retrofit2.converter.scalars.ScalarsConverterFactory; +import retrofit2.converter.jackson.JacksonConverterFactory; + +import play.libs.Json; +import play.libs.ws.WSClient; + +import {{invokerPackage}}.Play25CallAdapterFactory; +import {{invokerPackage}}.Play25CallFactory; + +import okhttp3.Interceptor; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.Authentication; + +/** + * API client + */ +public class ApiClient { + + /** Underlying HTTP-client */ + private WSClient wsClient; + + /** Supported auths */ + private Map authentications; + + /** API base path */ + private String basePath = "{{{basePath}}}"; + + public ApiClient(WSClient wsClient) { + this(); + this.wsClient = wsClient; + } + + public ApiClient() { + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap<>();{{#authMethods}}{{#isBasic}} + // authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + // authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + + } + + /** + * Creates a retrofit2 client for given API interface + */ + public S createService(Class serviceClass) { + if(!basePath.endsWith("/")) { + basePath = basePath + "/"; + } + + Map extraHeaders = new HashMap<>(); + List extraQueryParams = new ArrayList<>(); + + for (String authName : authentications.keySet()) { + Authentication auth = authentications.get(authName); + if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + + auth.applyToParams(extraQueryParams, extraHeaders); + } + + return new Retrofit.Builder() + .baseUrl(basePath) + .addConverterFactory(ScalarsConverterFactory.create()) + .addConverterFactory(JacksonConverterFactory.create(Json.mapper())) + .callFactory(new Play25CallFactory(wsClient, extraHeaders, extraQueryParams)) + .addCallAdapterFactory(new Play25CallAdapterFactory()) + .build() + .create(serviceClass); + } + + /** + * Helper method to set API base path + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Get authentications (key: authentication name, value: authentication). + */ + public Map getAuthentications() { + return authentications; + } + + /** + * Get authentication for the given name. + * + * @param authName The authentication name + * @return The authentication, null if not found + */ + public Authentication getAuthentication(String authName) { + return authentications.get(authName); + } + + /** + * Helper method to set API key value for the first API key authentication. + */ + public ApiClient setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return this; + } + } + + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + */ + public ApiClient setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return this; + } + } + + throw new RuntimeException("No API key authentication configured!"); + } + + +} + + diff --git a/libraries/retrofit2/play25/Play25CallAdapterFactory.mustache b/libraries/retrofit2/play25/Play25CallAdapterFactory.mustache new file mode 100644 index 00000000000..088c10b160a --- /dev/null +++ b/libraries/retrofit2/play25/Play25CallAdapterFactory.mustache @@ -0,0 +1,117 @@ +package {{invokerPackage}}; + +import java.util.concurrent.CompletionStage; +import retrofit2.*; + +import java.lang.annotation.Annotation; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.WildcardType; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.function.Function; + +/** + * Creates {@link CallAdapter} instances that convert {@link Call} into {@link java.util.concurrent.CompletionStage} + */ +public class Play25CallAdapterFactory extends CallAdapter.Factory { + + private Function exceptionConverter = Function.identity(); + + public Play25CallAdapterFactory() { + } + + public Play25CallAdapterFactory( + Function exceptionConverter) { + this.exceptionConverter = exceptionConverter; + } + + @Override + public CallAdapter get(Type returnType, Annotation[] annotations, Retrofit retrofit) { + if (!(returnType instanceof ParameterizedType)) { + return null; + } + + ParameterizedType type = (ParameterizedType) returnType; + if (type.getRawType() != CompletionStage.class) { + return null; + } + + return createAdapter((ParameterizedType) returnType); + } + + private CallAdapter> createAdapter(ParameterizedType returnType) { + // Get CompletionStage type argument + Type[] types = returnType.getActualTypeArguments(); + if (types.length != 1) { + throw new IllegalStateException("Must be exactly one type parameter"); + } + + Type resultType = types[0]; + Class rawTypeParam = getRawType(resultType); + + boolean includeResponse = false; + if (rawTypeParam == Response.class) { + if (!(resultType instanceof ParameterizedType)) { + throw new IllegalStateException("Response must be parameterized" + + " as Response"); + } + resultType = ((ParameterizedType) resultType).getActualTypeArguments()[0]; + includeResponse = true; + } + + return new ValueAdapter(resultType, includeResponse, exceptionConverter); + } + + /** + * Adapter that coverts values returned by API interface into CompletionStage + */ + private static final class ValueAdapter implements CallAdapter> { + + private final Type responseType; + private final boolean includeResponse; + private Function exceptionConverter; + + ValueAdapter(Type responseType, boolean includeResponse, + Function exceptionConverter) { + this.responseType = responseType; + this.includeResponse = includeResponse; + this.exceptionConverter = exceptionConverter; + } + + @Override + public Type responseType() { + return responseType; + } + + @Override + public CompletionStage adapt(final Call call) { + final CompletableFuture promise = new CompletableFuture(); + + call.enqueue(new Callback() { + + @Override + public void onResponse(Call call, Response response) { + if (response.isSuccessful()) { + if (includeResponse) { + promise.complete((R) response); + } else { + promise.complete(response.body()); + } + } else { + promise.completeExceptionally(exceptionConverter.apply(new HttpException(response))); + } + } + + @Override + public void onFailure(Call call, Throwable t) { + promise.completeExceptionally(t); + } + + }); + + return promise; + } + } +} + diff --git a/libraries/retrofit2/play25/Play25CallFactory.mustache b/libraries/retrofit2/play25/Play25CallFactory.mustache new file mode 100644 index 00000000000..93df7a2718d --- /dev/null +++ b/libraries/retrofit2/play25/Play25CallFactory.mustache @@ -0,0 +1,228 @@ +package {{invokerPackage}}; + +import okhttp3.*; +import okio.Buffer; +import okio.BufferedSource; +import play.libs.ws.WSClient; +import play.libs.ws.WSRequest; +import play.libs.ws.WSResponse; +import play.libs.ws.WSRequestFilter; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.CompletionStage; + +/** + * Creates {@link Call} instances that invoke underlying {@link WSClient} + */ +public class Play25CallFactory implements okhttp3.Call.Factory { + + /** PlayWS http client */ + private final WSClient wsClient; + + /** Extra headers to add to request */ + private Map extraHeaders = new HashMap<>(); + + /** Extra query parameters to add to request */ + private List extraQueryParams = new ArrayList<>(); + + /** Filters (interceptors) */ + private List filters = new ArrayList<>(); + + public Play25CallFactory(WSClient wsClient) { + this.wsClient = wsClient; + } + + public Play25CallFactory(WSClient wsClient, List filters) { + this.wsClient = wsClient; + this.filters.addAll(filters); + } + + public Play25CallFactory(WSClient wsClient, Map extraHeaders, + List extraQueryParams) { + this.wsClient = wsClient; + + this.extraHeaders.putAll(extraHeaders); + this.extraQueryParams.addAll(extraQueryParams); + } + + @Override + public Call newCall(Request request) { + // add extra headers + Request.Builder rb = request.newBuilder(); + for (Map.Entry header : this.extraHeaders.entrySet()) { + rb.addHeader(header.getKey(), header.getValue()); + } + + // add extra query params + if (!this.extraQueryParams.isEmpty()) { + String newQuery = request.url().uri().getQuery(); + for (Pair queryParam : this.extraQueryParams) { + String param = String.format("%s=%s", queryParam.getName(), queryParam.getValue()); + if (newQuery == null) { + newQuery = param; + } else { + newQuery += "&" + param; + } + } + + URI newUri; + try { + newUri = new URI(request.url().uri().getScheme(), request.url().uri().getAuthority(), + request.url().uri().getPath(), newQuery, request.url().uri().getFragment()); + rb.url(newUri.toURL()); + } catch (MalformedURLException | URISyntaxException e) { + throw new RuntimeException("Error while updating an url", e); + } + } + + return new PlayWSCall(wsClient, this.filters, rb.build()); + } + + /** + * Call implementation that delegates to Play WS Client + */ + static class PlayWSCall implements Call { + + private final WSClient wsClient; + private WSRequest wsRequest; + private List filters; + + private final Request request; + + public PlayWSCall(WSClient wsClient, List filters, Request request) { + this.wsClient = wsClient; + this.request = request; + this.filters = filters; + } + + @Override + public Request request() { + return request; + } + + @Override + public void enqueue(final okhttp3.Callback responseCallback) { + final Call call = this; + final CompletionStage promise = executeAsync(); + + promise.whenCompleteAsync((v, t) -> { + if (t != null) { + if (t instanceof IOException) { + responseCallback.onFailure(call, (IOException) t); + } else { + responseCallback.onFailure(call, new IOException(t)); + } + } else { + try { + responseCallback.onResponse(call, PlayWSCall.this.toWSResponse(v)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }, play.libs.concurrent.HttpExecution.defaultContext()); + } + + CompletionStage executeAsync() { + try { + wsRequest = wsClient.url(request.url().uri().toString()); + addHeaders(wsRequest); + if (request.body() != null) { + addBody(wsRequest); + } + filters.stream().forEach(f -> wsRequest.withRequestFilter(f)); + + return wsRequest.execute(request.method()); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + private void addHeaders(WSRequest wsRequest) { + for(Map.Entry> entry : request.headers().toMultimap().entrySet()) { + List values = entry.getValue(); + for (String value : values) { + wsRequest.setHeader(entry.getKey(), value); + } + } + } + + private void addBody(WSRequest wsRequest) throws IOException { + Buffer buffer = new Buffer(); + request.body().writeTo(buffer); + wsRequest.setBody(buffer.inputStream()); + + MediaType mediaType = request.body().contentType(); + if (mediaType != null) { + wsRequest.setContentType(mediaType.toString()); + } + } + + private Response toWSResponse(final WSResponse r) { + final Response.Builder builder = new Response.Builder(); + builder.request(request) + .code(r.getStatus()) + .body(new ResponseBody() { + + @Override + public MediaType contentType() { + return Optional.ofNullable(r.getHeader("Content-Type")) + .map(MediaType::parse) + .orElse(null); + } + + @Override + public long contentLength() { + return r.asByteArray().length; + } + + @Override + public BufferedSource source() { + return new Buffer().write(r.asByteArray()); + } + + }); + + for (Map.Entry> entry : r.getAllHeaders().entrySet()) { + for (String value : entry.getValue()) { + builder.addHeader(entry.getKey(), value); + } + } + + builder.protocol(Protocol.HTTP_1_1); + return builder.build(); + } + + @Override + public Response execute() throws IOException { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public void cancel() { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public PlayWSCall clone() { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public boolean isExecuted() { + return false; + } + + @Override + public boolean isCanceled() { + return false; + } + } +} diff --git a/libraries/retrofit2/play25/api.mustache b/libraries/retrofit2/play25/api.mustache new file mode 100644 index 00000000000..51b1812b49e --- /dev/null +++ b/libraries/retrofit2/play25/api.mustache @@ -0,0 +1,57 @@ +package {{package}}; + +import {{invokerPackage}}.CollectionFormats.*; + +{{#useRxJava}}import rx.Observable;{{/useRxJava}} +{{#useRxJava2}}import io.reactivex.Observable;{{/useRxJava2}} +{{#doNotUseRx}}import retrofit2.Call;{{/doNotUseRx}} +import retrofit2.http.*; + +import okhttp3.RequestBody; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +import java.util.concurrent.*; +import retrofit2.Response; + +{{#operations}} +public interface {{classname}} { + {{#operation}} + /** + * {{summary}} + * {{notes}} +{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} +{{/allParams}} + * @return Call<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + */ + {{#formParams}} + {{#-first}} + {{#isMultipart}}@retrofit2.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit2.http.FormUrlEncoded{{/isMultipart}} + {{/-first}} + {{/formParams}} + {{^formParams}} + {{#prioritizedContentTypes}} + {{#-first}} + @Headers({ + "Content-Type:{{{mediaType}}}" + }) + {{/-first}} + {{/prioritizedContentTypes}} + {{/formParams}} + @{{httpMethod}}("{{{path}}}") + CompletionStage> {{operationId}}({{^allParams}});{{/allParams}} + {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{#hasMore}}, {{/hasMore}}{{^hasMore}} + );{{/hasMore}}{{/allParams}} + + {{/operation}} +} +{{/operations}} diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache new file mode 100644 index 00000000000..3adfab68fe7 --- /dev/null +++ b/libraries/retrofit2/pom.mustache @@ -0,0 +1,361 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{artifactUrl}} + {{artifactDescription}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-core-version} + + + com.squareup.retrofit2 + converter-gson + ${retrofit-version} + + + com.squareup.retrofit2 + retrofit + ${retrofit-version} + + + com.squareup.retrofit2 + converter-scalars + ${retrofit-version} + + + org.apache.oltu.oauth2 + org.apache.oltu.oauth2.client + ${oltu-version} + + + org.apache.oltu.oauth2 + common + + + + + io.gsonfire + gson-fire + ${gson-fire-version} + + {{#joda}} + + joda-time + joda-time + ${jodatime-version} + + {{/joda}} + {{#threetenbp}} + + org.threeten + threetenbp + ${threetenbp-version} + + {{/threetenbp}} + {{#useRxJava}} + + io.reactivex + rxjava + ${rxjava-version} + + + com.squareup.retrofit2 + adapter-rxjava + ${retrofit-version} + + {{/useRxJava}} + {{#useRxJava2}} + + io.reactivex.rxjava2 + rxjava + ${rxjava-version} + + + com.squareup.retrofit2 + adapter-rxjava2 + ${retrofit-version} + + {{/useRxJava2}} + + {{#usePlayWS}} + + + com.squareup.retrofit2 + converter-jackson + ${retrofit-version} + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-version} + + + com.fasterxml.jackson.datatype + jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}} + ${jackson-version} + + {{#withXml}} + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson-version} + + + {{/withXml}} + + com.typesafe.play + play-java-ws_2.11 + ${play-version} + + {{/usePlayWS}} + + {{#parcelableModel}} + + + com.google.android + android + 4.1.1.4 + provided + + {{/parcelableModel}} + + + + junit + junit + ${junit-version} + test + + + + UTF-8 + {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}} + ${java.version} + ${java.version} + 1.8.0 + 1.5.18 + {{#usePlayWS}} + {{#play24}} + 2.6.6 + 2.4.11 + {{/play24}} + {{#play25}} + 2.7.8 + 2.5.15 + {{/play25}} + {{/usePlayWS}} + 2.3.0 + {{#useRxJava}} + 1.3.0 + {{/useRxJava}} + {{#useRxJava2}} + 2.1.1 + {{/useRxJava2}} + {{#joda}} + 2.9.9 + {{/joda}} + {{#threetenbp}} + 1.3.5 + {{/threetenbp}} + 1.0.1 + 4.12 + + diff --git a/libraries/retrofit2/queryParams.mustache b/libraries/retrofit2/queryParams.mustache new file mode 100644 index 00000000000..abb87510ecf --- /dev/null +++ b/libraries/retrofit2/queryParams.mustache @@ -0,0 +1 @@ +{{#isQueryParam}}@retrofit2.http.Query("{{baseName}}") {{#collectionFormat}}{{#isCollectionFormatMulti}}{{{dataType}}}{{/isCollectionFormatMulti}}{{^isCollectionFormatMulti}}{{{collectionFormat.toUpperCase}}}Params{{/isCollectionFormatMulti}}{{/collectionFormat}}{{^collectionFormat}}{{{dataType}}}{{/collectionFormat}} {{paramName}}{{/isQueryParam}} \ No newline at end of file diff --git a/libraries/vertx/ApiClient.mustache b/libraries/vertx/ApiClient.mustache new file mode 100644 index 00000000000..1de56ec9ca9 --- /dev/null +++ b/libraries/vertx/ApiClient.mustache @@ -0,0 +1,600 @@ +package {{invokerPackage}}; + +import {{invokerPackage}}.auth.Authentication; +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.OAuth; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import io.vertx.core.*; +import io.vertx.core.buffer.Buffer; +import io.vertx.core.file.AsyncFile; +import io.vertx.core.file.FileSystem; +import io.vertx.core.file.OpenOptions; +import io.vertx.core.http.HttpHeaders; +import io.vertx.core.http.HttpMethod; +import io.vertx.core.json.Json; +import io.vertx.core.json.JsonObject; +import io.vertx.ext.web.client.HttpRequest; +import io.vertx.ext.web.client.HttpResponse; +import io.vertx.ext.web.client.WebClient; +import io.vertx.ext.web.client.WebClientOptions; + +import java.text.DateFormat; +import java.util.*; +import java.util.function.Consumer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static java.util.stream.Collectors.toMap; + +{{>generatedAnnotation}} +public class ApiClient { + + private static final Pattern CONTENT_DISPOSITION_PATTERN = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?"); + private static final OpenOptions FILE_DOWNLOAD_OPTIONS = new OpenOptions().setCreate(true).setTruncateExisting(true); + + private final Vertx vertx; + private final JsonObject config; + private final String identifier; + + private MultiMap defaultHeaders = MultiMap.caseInsensitiveMultiMap(); + private Map authentications; + private String basePath = "{{{basePath}}}"; + private DateFormat dateFormat; + private ObjectMapper objectMapper; + private String downloadsDir = ""; + + public ApiClient(Vertx vertx, JsonObject config) { + Objects.requireNonNull(vertx, "Vertx must not be null"); + Objects.requireNonNull(config, "Config must not be null"); + + this.vertx = vertx; + + // Use RFC3339 format for date and datetime. + // See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14 + this.dateFormat = new RFC3339DateFormat(); + + // Use UTC as the default time zone. + this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + + // Build object mapper + this.objectMapper = new ObjectMapper(); + this.objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + this.objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + this.objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + this.objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + this.objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + this.objectMapper.registerModule(new JavaTimeModule()); + this.objectMapper.setDateFormat(dateFormat); + + // Setup authentications (key: authentication name, value: authentication). + this.authentications = new HashMap<>();{{#authMethods}}{{#isBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + this.authentications = Collections.unmodifiableMap(authentications); + + // Configurations + this.basePath = config.getString("basePath", this.basePath); + this.downloadsDir = config.getString("downloadsDir", this.downloadsDir); + this.config = config; + this.identifier = UUID.randomUUID().toString(); + } + + public Vertx getVertx() { + return vertx; + } + + public ObjectMapper getObjectMapper() { + return objectMapper; + } + + public ApiClient setObjectMapper(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + return this; + } + + public synchronized WebClient getWebClient() { + String webClientIdentifier = "web-client-" + identifier; + WebClient webClient = Vertx.currentContext().get(webClientIdentifier); + if (webClient == null) { + webClient = buildWebClient(vertx, config); + Vertx.currentContext().put(webClientIdentifier, webClient); + } + return webClient; + } + + public String getBasePath() { + return basePath; + } + + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + public String getDownloadsDir() { + return downloadsDir; + } + + public ApiClient setDownloadsDir(String downloadsDir) { + this.downloadsDir = downloadsDir; + return this; + } + + public MultiMap getDefaultHeaders() { + return defaultHeaders; + } + + public ApiClient addDefaultHeader(String key, String value) { + defaultHeaders.add(key, value); + return this; + } + + /** + * Get authentications (key: authentication name, value: authentication). + * + * @return Map of authentication object + */ + public Map getAuthentications() { + return authentications; + } + + /** + * Get authentication for the given name. + * + * @param authName The authentication name + * @return The authentication, null if not found + */ + public Authentication getAuthentication(String authName) { + return authentications.get(authName); + } + + /** + * Helper method to set username for the first HTTP basic authentication. + * + * @param username Username + */ + public ApiClient setUsername(String username) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setUsername(username); + return this; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set password for the first HTTP basic authentication. + * + * @param password Password + */ + public ApiClient setPassword(String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setPassword(password); + return this; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set API key value for the first API key authentication. + * + * @param apiKey API key + */ + public ApiClient setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return this; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + * + * @param apiKeyPrefix API key prefix + */ + public ApiClient setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return this; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set access token for the first OAuth2 authentication. + * + * @param accessToken Access token + */ + public ApiClient setAccessToken(String accessToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setAccessToken(accessToken); + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Format the given Date object into string. + * + * @param date Date + * @return Date in string format + */ + public String formatDate(Date date) { + return dateFormat.format(date); + } + + /** + * Format the given parameter object into string. + * + * @param param Object + * @return Object in string format + */ + public String parameterToString(Object param) { + if (param == null) { + return ""; + } else if (param instanceof Date) { + return formatDate((Date) param); + } else if (param instanceof Collection) { + StringBuilder b = new StringBuilder(); + for (Object o : (Collection) param) { + if (b.length() > 0) { + b.append(','); + } + b.append(String.valueOf(o)); + } + return b.toString(); + } else { + return String.valueOf(param); + } + } + + /* + * Format to {@code Pair} objects. + * @param collectionFormat Collection format + * @param name Name + * @param value Value + * @return List of pairs + */ + public List parameterToPairs(String collectionFormat, String name, Object value) { + List params = new ArrayList(); + + // preconditions + if (name == null || name.isEmpty() || value == null) return params; + + Collection valueCollection; + if (value instanceof Collection) { + valueCollection = (Collection) value; + } else { + params.add(new Pair(name, parameterToString(value))); + return params; + } + + if (valueCollection.isEmpty()) { + return params; + } + + // get the collection format (default: csv) + String format = (collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat); + + // create the params based on the collection format + if ("multi".equals(format)) { + for (Object item : valueCollection) { + params.add(new Pair(name, parameterToString(item))); + } + return params; + } + + String delimiter = ","; + if ("csv".equals(format)) { + delimiter = ","; + } else if ("ssv".equals(format)) { + delimiter = " "; + } else if ("tsv".equals(format)) { + delimiter = "\t"; + } else if ("pipes".equals(format)) { + delimiter = "|"; + } + + StringBuilder sb = new StringBuilder(); + for (Object item : valueCollection) { + sb.append(delimiter); + sb.append(parameterToString(item)); + } + + params.add(new Pair(name, sb.substring(1))); + + return params; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * application/vnd.company+json + * + * @param mime MIME + * @return True if the MIME type is JSON + */ + private boolean isJsonMime(String mime) { + String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$"; + return mime != null && (mime.matches(jsonMime) || mime.equalsIgnoreCase("application/json-patch+json")); + } + + /** + * Select the Accept header's value from the given accepts array: + * if JSON exists in the given array, use it; + * otherwise use all of them (joining into a string) + * + * @param accepts The accepts array to select from + * @return The Accept header to use. If the given array is empty, + * null will be returned (not to set the Accept header explicitly). + */ + protected String selectHeaderAccept(String[] accepts) { + if (accepts.length == 0) { + return null; + } + for (String accept : accepts) { + if (isJsonMime(accept)) { + return accept; + } + } + return StringUtil.join(accepts, ","); + } + + /** + * Select the Content-Type header's value from the given array: + * if JSON exists in the given array, use it; + * otherwise use the first one of the array. + * + * @param contentTypes The Content-Type array to select from + * @return The Content-Type header to use. If the given array is empty, + * JSON will be used. + */ + protected String selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0) { + return "application/json"; + } + for (String contentType : contentTypes) { + if (isJsonMime(contentType)) { + return contentType; + } + } + return contentTypes[0]; + } + + public void sendBody(HttpRequest request, + Handler>> responseHandler, + Object body) { + if (body instanceof byte[]) { + Buffer buffer = Buffer.buffer((byte[]) body); + request.sendBuffer(buffer, responseHandler); + } else if (body instanceof AsyncFile) { + AsyncFile file = (AsyncFile) body; + request.sendStream(file, responseHandler); + } else { + request.sendJson(body, responseHandler); + } + } + + /** + * Invoke API by sending HTTP request with the given options. + * + * @param Type + * @param path The sub-path of the HTTP URL + * @param method The request method, one of "GET", "POST", "PUT", "HEAD" and "DELETE" + * @param queryParams The query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param formParams The form parameters + * @param accepts The request's Accept headers + * @param contentTypes The request's Content-Type headers + * @param authNames The authentications to apply + * @param returnType The return type into which to deserialize the response + * @param resultHandler The asynchronous response handler + */ + public void invokeAPI(String path, String method, List queryParams, Object body, MultiMap headerParams, + Map formParams, String[] accepts, String[] contentTypes, String[] authNames, + TypeReference returnType, Handler> resultHandler) { + + updateParamsForAuth(authNames, queryParams, headerParams); + + if (accepts != null) { + headerParams.add(HttpHeaders.ACCEPT, selectHeaderAccept(accepts)); + } + + if (contentTypes != null) { + headerParams.add(HttpHeaders.CONTENT_TYPE, selectHeaderContentType(contentTypes)); + } + + HttpMethod httpMethod = HttpMethod.valueOf(method); + HttpRequest request = getWebClient().requestAbs(httpMethod, basePath + path); + + if (httpMethod == HttpMethod.PATCH) { + request.putHeader("X-HTTP-Method-Override", "PATCH"); + } + + queryParams.forEach(entry -> { + if (entry.getValue() != null) { + request.addQueryParam(entry.getName(), entry.getValue()); + } + }); + + headerParams.forEach(entry -> { + if (entry.getValue() != null) { + request.putHeader(entry.getKey(), entry.getValue()); + } + }); + + defaultHeaders.forEach(entry -> { + if (entry.getValue() != null) { + request.putHeader(entry.getKey(), entry.getValue()); + } + }); + + Handler>> responseHandler = buildResponseHandler(returnType, resultHandler); + if (body != null) { + sendBody(request, responseHandler, body); + } else if (formParams != null && !formParams.isEmpty()) { + Map formMap = formParams.entrySet().stream().collect(toMap(Map.Entry::getKey, entry -> parameterToString(entry.getValue()))); + MultiMap form = MultiMap.caseInsensitiveMultiMap().addAll(formMap); + request.sendForm(form, responseHandler); + } else { + request.send(responseHandler); + } + } + + /** + * Sanitize filename by removing path. + * e.g. ../../sun.gif becomes sun.gif + * + * @param filename The filename to be sanitized + * @return The sanitized filename + */ + protected String sanitizeFilename(String filename) { + return filename.replaceAll(".*[/\\\\]", ""); + } + + /** + * Create a filename from the given headers. + * When the headers have no "Content-Disposition" information, a random UUID name is generated. + * + * @param headers The HTTP response headers + * @return The filename + */ + protected String generateFilename(MultiMap headers) { + String filename = UUID.randomUUID().toString(); + String contentDisposition = headers.get("Content-Disposition"); + if (contentDisposition != null && !contentDisposition.isEmpty()) { + Matcher matcher = CONTENT_DISPOSITION_PATTERN.matcher(contentDisposition); + if (matcher.find()) { + filename = sanitizeFilename(matcher.group(1)); + } + } + return filename; + } + + /** + * File Download handling. + * + * @param response The HTTP response + * @param handler The response handler + */ + protected void handleFileDownload(HttpResponse response, Handler> handler) { + FileSystem fs = getVertx().fileSystem(); + + String filename = generateFilename(response.headers()); + Consumer fileHandler = directory -> { + fs.open(directory + filename, FILE_DOWNLOAD_OPTIONS, asyncFileResult -> { + if (asyncFileResult.succeeded()) { + AsyncFile asyncFile = asyncFileResult.result(); + asyncFile.write(response.bodyAsBuffer()); + //noinspection unchecked + handler.handle(Future.succeededFuture((T) asyncFile)); + } else { + handler.handle(ApiException.fail(asyncFileResult.cause())); + } + }); + }; + + String dir = getDownloadsDir(); + if (dir != null && !dir.isEmpty()) { + fs.mkdirs(dir, mkdirResult -> { + String sanitizedFolder = dir.endsWith("/") ? dir : dir + "/"; + fileHandler.accept(sanitizedFolder); + }); + } else { + fileHandler.accept(""); + } + } + + /** + * Build a response handler for the HttpResponse. + * + * @param returnType The return type + * @param handler The response handler + * @return The HTTP response handler + */ + protected Handler>> buildResponseHandler(TypeReference returnType, + Handler> handler) { + return response -> { + AsyncResult result; + if (response.succeeded()) { + HttpResponse httpResponse = response.result(); + if (httpResponse.statusCode() / 100 == 2) { + if (httpResponse.statusCode() == 204 || returnType == null) { + result = Future.succeededFuture(null); + } else { + T resultContent; + if ("byte[]".equals(returnType.getType().toString())) { + resultContent = (T) httpResponse.body().getBytes(); + } else if (AsyncFile.class.equals(returnType.getType())) { + handleFileDownload(httpResponse, handler); + return; + } else { + resultContent = Json.decodeValue(httpResponse.body(), returnType); + } + result = Future.succeededFuture(resultContent); + } + } else { + result = ApiException.fail(httpResponse.statusMessage(), httpResponse.statusCode(), httpResponse.headers(), httpResponse.bodyAsString()); + } + } else if (response.cause() instanceof ApiException) { + result = Future.failedFuture(response.cause()); + } else { + result = ApiException.fail(500, response.cause() != null ? response.cause().getMessage() : null); + } + handler.handle(result); + }; + } + + /** + * Build the WebClient used to make HTTP requests. + * + * @param vertx Vertx + * @return WebClient + */ + protected WebClient buildWebClient(Vertx vertx, JsonObject config) { + + if (!config.containsKey("userAgent")) { + config.put("userAgent", "{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}Swagger-Codegen/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + } + + return WebClient.create(vertx, new WebClientOptions(config)); + } + + + /** + * Update query and header parameters based on authentication settings. + * + * @param authNames The authentications to apply + */ + protected void updateParamsForAuth(String[] authNames, List queryParams, MultiMap headerParams) { + for (String authName : authNames) { + Authentication auth = authentications.get(authName); + if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + auth.applyToParams(queryParams, headerParams); + } + } +} \ No newline at end of file diff --git a/libraries/vertx/Configuration.mustache b/libraries/vertx/Configuration.mustache new file mode 100644 index 00000000000..17710ae1600 --- /dev/null +++ b/libraries/vertx/Configuration.mustache @@ -0,0 +1,42 @@ +package {{invokerPackage}}; + +import io.vertx.core.Vertx; +import io.vertx.core.json.JsonObject; + +import java.util.Objects; + +public class Configuration { + + private static ApiClient defaultApiClient = null; + + /** + * Setup the default API client. + * Will be used by API instances when a client is not provided. + * + * @return Default API client + */ + public synchronized static ApiClient setupDefaultApiClient(Vertx vertx, JsonObject config) { + defaultApiClient = new ApiClient(vertx, config); + return defaultApiClient; + } + + /** + * Get the default API client, which would be used when creating API + * instances without providing an API client. + * + * @return Default API client + */ + public synchronized static ApiClient getDefaultApiClient() { + return defaultApiClient; + } + + /** + * Set the default API client, which would be used when creating API + * instances without providing an API client. + * + * @param apiClient API client + */ + public synchronized static void setDefaultApiClient(ApiClient apiClient) { + defaultApiClient = apiClient; + } +} diff --git a/libraries/vertx/api.mustache b/libraries/vertx/api.mustache new file mode 100644 index 00000000000..dcf9df4cc70 --- /dev/null +++ b/libraries/vertx/api.mustache @@ -0,0 +1,19 @@ +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} +import io.vertx.core.AsyncResult; +import io.vertx.core.Handler; +import io.vertx.core.json.JsonObject; + +import java.util.*; + +public interface {{classname}} { + + {{#operations}} + {{#operation}} + void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}Handler> handler); + + {{/operation}} + {{/operations}} +} diff --git a/libraries/vertx/apiException.mustache b/libraries/vertx/apiException.mustache new file mode 100644 index 00000000000..6e9bbdbb88d --- /dev/null +++ b/libraries/vertx/apiException.mustache @@ -0,0 +1,110 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import io.vertx.core.AsyncResult; +import io.vertx.core.Future; +import io.vertx.core.MultiMap; + +{{>generatedAnnotation}} +public class ApiException extends{{#useRuntimeException}} RuntimeException {{/useRuntimeException}}{{^useRuntimeException}} Exception {{/useRuntimeException}}{ + private int code = 0; + private MultiMap responseHeaders = null; + private String responseBody = null; + + + public static AsyncResult fail(int failureCode, String message) { + return Future.failedFuture(new ApiException(failureCode, message)); + } + + public static AsyncResult fail(Throwable throwable) { + return Future.failedFuture(new ApiException(throwable)); + } + + public static AsyncResult fail(String message) { + return Future.failedFuture(new ApiException(message)); + } + + public static AsyncResult fail(String message, Throwable throwable, int code, MultiMap responseHeaders) { + return Future.failedFuture(new ApiException(message, throwable, code, responseHeaders, null)); + } + + public static AsyncResult fail(String message, Throwable throwable, int code, MultiMap responseHeaders, String responseBody) { + return Future.failedFuture(new ApiException(message, throwable, code, responseHeaders, responseBody)); + } + + public static AsyncResult fail(String message, int code, MultiMap responseHeaders, String responseBody) { + return Future.failedFuture(new ApiException(message, (Throwable) null, code, responseHeaders, responseBody)); + } + + public static AsyncResult fail(int code, MultiMap responseHeaders, String responseBody) { + return Future.failedFuture(new ApiException((String) null, (Throwable) null, code, responseHeaders, responseBody)); + } + + public ApiException() {} + + public ApiException(Throwable throwable) { + super(throwable); + } + + public ApiException(String message) { + super(message); + } + + public ApiException(String message, Throwable throwable, int code, MultiMap responseHeaders, String responseBody) { + super(message, throwable); + this.code = code; + this.responseHeaders = responseHeaders; + this.responseBody = responseBody; + } + + public ApiException(String message, int code, MultiMap responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(String message, Throwable throwable, int code, MultiMap responseHeaders) { + this(message, throwable, code, responseHeaders, null); + } + + public ApiException(int code, MultiMap responseHeaders, String responseBody) { + this((String) null, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(int code, String message) { + super(message); + this.code = code; + } + + public ApiException(int code, String message, MultiMap responseHeaders, String responseBody) { + this(code, message); + this.responseHeaders = responseHeaders; + this.responseBody = responseBody; + } + + /** + * Get the HTTP status code. + * + * @return HTTP status code + */ + public int getCode() { + return code; + } + + /** + * Get the HTTP response headers. + * + * @return A map of list of string + */ + public MultiMap getResponseHeaders() { + return responseHeaders; + } + + /** + * Get the HTTP response body. + * + * @return Response body in the form of string + */ + public String getResponseBody() { + return responseBody; + } +} diff --git a/libraries/vertx/apiImpl.mustache b/libraries/vertx/apiImpl.mustache new file mode 100644 index 00000000000..f4b5a723922 --- /dev/null +++ b/libraries/vertx/apiImpl.mustache @@ -0,0 +1,91 @@ +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} + +import io.vertx.core.AsyncResult; +import io.vertx.core.Handler; +import io.vertx.core.MultiMap; +import io.vertx.core.json.JsonObject; + +import com.fasterxml.jackson.core.type.TypeReference; + +import java.util.*; + +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.Configuration; +import {{invokerPackage}}.Pair; + +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}}Impl implements {{classname}} { + + private ApiClient {{localVariablePrefix}}apiClient; + + public {{classname}}Impl() { + this(null); + } + + public {{classname}}Impl(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient != null ? apiClient : Configuration.getDefaultApiClient(); + } + + public ApiClient getApiClient() { + return {{localVariablePrefix}}apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + {{#operation}} + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @param resultHandler Asynchronous result handler + */ + public void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}Handler> resultHandler) { + Object {{localVariablePrefix}}localVarBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + resultHandler.handle(ApiException.fail(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}")); + return; + } + {{/required}}{{/allParams}} + // create path and map variables + String {{localVariablePrefix}}localVarPath = "{{{path}}}"{{#pathParams}}.replaceAll("\\{" + "{{baseName}}" + "\\}", {{{paramName}}}.toString()){{/pathParams}}; + + // query params + List {{localVariablePrefix}}localVarQueryParams = new ArrayList<>(); + {{#queryParams}} + {{localVariablePrefix}}localVarQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); + {{/queryParams}} + + // header params + MultiMap {{localVariablePrefix}}localVarHeaderParams = MultiMap.caseInsensitiveMultiMap(); + {{#headerParams}}if ({{paramName}} != null) + {{localVariablePrefix}}localVarHeaderParams.add("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}})); + {{/headerParams}} + + // form params + // TODO: sending files within multipart/form-data is not supported yet (because of vertx web-client) + Map {{localVariablePrefix}}localVarFormParams = new HashMap<>(); + {{#formParams}}if ({{paramName}} != null) {{localVariablePrefix}}localVarFormParams.put("{{baseName}}", {{paramName}}); + {{/formParams}} + + String[] {{localVariablePrefix}}localVarAccepts = { {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }; + String[] {{localVariablePrefix}}localVarContentTypes = { {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} }; + String[] {{localVariablePrefix}}localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + {{#returnType}} + TypeReference<{{{returnType}}}> {{localVariablePrefix}}localVarReturnType = new TypeReference<{{{returnType}}}>() {}; + {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccepts, {{localVariablePrefix}}localVarContentTypes, {{localVariablePrefix}}localVarAuthNames, {{localVariablePrefix}}localVarReturnType, resultHandler);{{/returnType}}{{^returnType}} + {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccepts, {{localVariablePrefix}}localVarContentTypes, {{localVariablePrefix}}localVarAuthNames, null, resultHandler);{{/returnType}} + } + {{/operation}} +} +{{/operations}} diff --git a/libraries/vertx/api_test.mustache b/libraries/vertx/api_test.mustache new file mode 100644 index 00000000000..753df13cd1d --- /dev/null +++ b/libraries/vertx/api_test.mustache @@ -0,0 +1,70 @@ +{{>licenseInfo}} +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} + +import {{invokerPackage}}.Configuration; + +import org.junit.Test; +import org.junit.Ignore; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.runner.RunWith; + +import io.vertx.core.AsyncResult; +import io.vertx.core.Handler; +import io.vertx.core.json.JsonObject; +import io.vertx.core.Vertx; +import io.vertx.ext.unit.junit.VertxUnitRunner; +import io.vertx.ext.unit.junit.RunTestOnContext; +import io.vertx.ext.unit.TestContext; +import io.vertx.ext.unit.Async; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +@RunWith(VertxUnitRunner.class) +@Ignore +public class {{classname}}Test { + + private {{classname}} api; + + @Rule + public RunTestOnContext rule = new RunTestOnContext(); + + @BeforeClass + public void setupApiClient() { + JsonObject config = new JsonObject(); + Vertx vertx = rule.vertx(); + Configuration.setupDefaultApiClient(vertx, config); + + api = new {{classname}}Impl(); + } + {{#operations}}{{#operation}} + /** + * {{summary}} + * {{notes}} + * + * @param context Vertx test context for doing assertions + */ + @Test + public void {{operationId}}Test(TestContext context) { + Async async = context.async(); + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + api.{{operationId}}({{#allParams}}{{paramName}}, {{/allParams}}result -> { + // TODO: test validations + async.complete(); + }); + } + {{/operation}}{{/operations}} +} \ No newline at end of file diff --git a/libraries/vertx/auth/ApiKeyAuth.mustache b/libraries/vertx/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..43b1866e460 --- /dev/null +++ b/libraries/vertx/auth/ApiKeyAuth.mustache @@ -0,0 +1,64 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import io.vertx.core.MultiMap; + +import java.util.List; + +{{>generatedAnnotation}} +public class ApiKeyAuth implements Authentication { + private final String location; + private final String paramName; + + private String apiKey; + private String apiKeyPrefix; + + public ApiKeyAuth(String location, String paramName) { + this.location = location; + this.paramName = paramName; + } + + public String getLocation() { + return location; + } + + public String getParamName() { + return paramName; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + public String getApiKeyPrefix() { + return apiKeyPrefix; + } + + public void setApiKeyPrefix(String apiKeyPrefix) { + this.apiKeyPrefix = apiKeyPrefix; + } + + @Override + public void applyToParams(List queryParams, MultiMap headerParams) { + if (apiKey == null) { + return; + } + String value; + if (apiKeyPrefix != null) { + value = apiKeyPrefix + " " + apiKey; + } else { + value = apiKey; + } + if ("query".equals(location)) { + queryParams.add(new Pair(paramName, value)); + } else if ("header".equals(location)) { + headerParams.add(paramName, value); + } + } +} diff --git a/libraries/vertx/auth/Authentication.mustache b/libraries/vertx/auth/Authentication.mustache new file mode 100644 index 00000000000..5dccb93f2ac --- /dev/null +++ b/libraries/vertx/auth/Authentication.mustache @@ -0,0 +1,18 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import io.vertx.core.MultiMap; + +import java.util.List; + +public interface Authentication { + /** + * Apply authentication settings to header and query params. + * + * @param queryParams List of query parameters + * @param headerParams Map of header parameters + */ + void applyToParams(List queryParams, MultiMap headerParams); +} diff --git a/libraries/vertx/auth/HttpBasicAuth.mustache b/libraries/vertx/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..43862b508b6 --- /dev/null +++ b/libraries/vertx/auth/HttpBasicAuth.mustache @@ -0,0 +1,40 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import io.vertx.core.MultiMap; +import java.util.Base64; +import java.nio.charset.StandardCharsets; +import java.util.List; + +{{>generatedAnnotation}} +public class HttpBasicAuth implements Authentication { + private String username; + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public void applyToParams(List queryParams, MultiMap headerParams) { + if (username == null && password == null) { + return; + } + String str = (username == null ? "" : username) + ":" + (password == null ? "" : password); + headerParams.add("Authorization", "Basic " + Base64.getEncoder().encodeToString(str.getBytes(StandardCharsets.UTF_8))); + } +} diff --git a/libraries/vertx/auth/OAuth.mustache b/libraries/vertx/auth/OAuth.mustache new file mode 100644 index 00000000000..f3c5b34ee11 --- /dev/null +++ b/libraries/vertx/auth/OAuth.mustache @@ -0,0 +1,28 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import io.vertx.core.MultiMap; + +import java.util.List; + +{{>generatedAnnotation}} +public class OAuth implements Authentication { + private String accessToken; + + public String getAccessToken() { + return accessToken; + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + @Override + public void applyToParams(List queryParams, MultiMap headerParams) { + if (accessToken != null) { + headerParams.add("Authorization", "Bearer " + accessToken); + } + } +} diff --git a/libraries/vertx/auth/OAuthFlow.mustache b/libraries/vertx/auth/OAuthFlow.mustache new file mode 100644 index 00000000000..002e9572f33 --- /dev/null +++ b/libraries/vertx/auth/OAuthFlow.mustache @@ -0,0 +1,7 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +public enum OAuthFlow { + accessCode, implicit, password, application +} diff --git a/libraries/vertx/build.gradle.mustache b/libraries/vertx/build.gradle.mustache new file mode 100644 index 00000000000..e1c956d5f72 --- /dev/null +++ b/libraries/vertx/build.gradle.mustache @@ -0,0 +1,53 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +repositories { + jcenter() +} + +apply plugin: 'java' +apply plugin: 'maven' + +sourceCompatibility = JavaVersion.VERSION_1_8 +targetCompatibility = JavaVersion.VERSION_1_8 + +install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } +} + +task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath +} + +ext { + swagger_annotations_version = "1.5.17" + jackson_version = "{{^threetenbp}}2.8.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" + vertx_version = "3.4.2" + junit_version = "4.12" +} + +dependencies { + compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "io.vertx:vertx-web-client:$vertx_version" + compile "io.vertx:vertx-rx-java:$vertx_version" + compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + {{#joda}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + {{/joda}} + {{#java8}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{/java8}} + {{#threetenbp}} + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_version" + {{/threetenbp}} + testCompile "junit:junit:$junit_version" + testCompile "io.vertx:vertx-unit:$vertx_version" +} diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache new file mode 100644 index 00000000000..d524edeaa94 --- /dev/null +++ b/libraries/vertx/pom.mustache @@ -0,0 +1,279 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{artifactUrl}} + {{artifactDescription}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.6 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.0.0 + + + add_sources + generate-sources + + add-source + + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-core-version} + + + + + io.vertx + vertx-rx-java + ${vertx-version} + + + io.vertx + vertx-web-client + ${vertx-version} + + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-version} + + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + {{/joda}} + {{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{/java8}} + {{#threetenbp}} + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${jackson-version} + + {{/threetenbp}} + + + + junit + junit + ${junit-version} + test + + + io.vertx + vertx-unit + ${vertx-version} + test + + + + + UTF-8 + 3.4.2 + 1.5.18 + {{^threetenbp}}2.8.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} + 4.12 + + diff --git a/libraries/vertx/rxApiImpl.mustache b/libraries/vertx/rxApiImpl.mustache new file mode 100644 index 00000000000..09ca96895d6 --- /dev/null +++ b/libraries/vertx/rxApiImpl.mustache @@ -0,0 +1,58 @@ +package {{package}}.rxjava; + +{{#imports}}import {{import}}; +{{/imports}} + +import java.util.*; + +import rx.Single; +import io.vertx.core.AsyncResult; +import io.vertx.core.Handler; + +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}} { + + private final {{package}}.{{classname}} delegate; + + public {{classname}}({{package}}.{{classname}} delegate) { + this.delegate = delegate; + } + + public {{package}}.{{classname}} getDelegate() { + return delegate; + } + + {{#operation}} + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @param resultHandler Asynchronous result handler + */ + public void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}Handler> resultHandler) { + delegate.{{operationId}}({{#allParams}}{{paramName}}, {{/allParams}}resultHandler); + } + + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @return Asynchronous result handler (RxJava Single) + */ + public Single<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> rx{{operationIdCamelCase}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) { + return Single.create(new io.vertx.rx.java.SingleOnSubscribeAdapter<>(fut -> { + delegate.{{operationId}}({{#allParams}}{{paramName}}, {{/allParams}}fut); + })); + } + {{/operation}} + + public static {{classname}} newInstance({{package}}.{{classname}} arg) { + return arg != null ? new {{classname}}(arg) : null; + } +} +{{/operations}} diff --git a/licenseInfo.mustache b/licenseInfo.mustache new file mode 100644 index 00000000000..94c36dda3af --- /dev/null +++ b/licenseInfo.mustache @@ -0,0 +1,11 @@ +/* + * {{{appName}}} + * {{{appDescription}}} + * + * {{#version}}OpenAPI spec version: {{{version}}}{{/version}} + * {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}} + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ diff --git a/manifest.mustache b/manifest.mustache new file mode 100644 index 00000000000..f44bd07d0a0 --- /dev/null +++ b/manifest.mustache @@ -0,0 +1,3 @@ + + + diff --git a/model.mustache b/model.mustache new file mode 100644 index 00000000000..a42a1359e4d --- /dev/null +++ b/model.mustache @@ -0,0 +1,39 @@ +{{>licenseInfo}} + +package {{package}}; + +{{^supportJava6}} +import java.util.Objects; +import java.util.Arrays; +{{/supportJava6}} +{{#supportJava6}} +import org.apache.commons.lang3.ObjectUtils; +{{/supportJava6}} +{{#imports}} +import {{import}}; +{{/imports}} +{{#serializableModel}} +import java.io.Serializable; +{{/serializableModel}} +{{#jackson}} +{{#withXml}} +import com.fasterxml.jackson.dataformat.xml.annotation.*; +{{/withXml}} +{{/jackson}} +{{#withXml}} +import javax.xml.bind.annotation.*; +{{/withXml}} +{{#parcelableModel}} +import android.os.Parcelable; +import android.os.Parcel; +{{/parcelableModel}} +{{#useBeanValidation}} +import javax.validation.constraints.*; +import javax.validation.Valid; +{{/useBeanValidation}} + +{{#models}} +{{#model}} +{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{>pojo}}{{/isEnum}} +{{/model}} +{{/models}} diff --git a/modelEnum.mustache b/modelEnum.mustache new file mode 100644 index 00000000000..209d310172b --- /dev/null +++ b/modelEnum.mustache @@ -0,0 +1,68 @@ +{{#jackson}} +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +{{/jackson}} +{{#gson}} +import java.io.IOException; +import com.google.gson.TypeAdapter; +import com.google.gson.annotations.JsonAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +{{/gson}} + +/** + * {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}} + */ +{{#gson}} +@JsonAdapter({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.Adapter.class) +{{/gson}} +public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} { + {{#allowableValues}}{{#enumVars}} + {{{name}}}({{{value}}}){{^-last}}, + {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}} + + private {{{dataType}}} value; + + {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}({{{dataType}}} value) { + this.value = value; + } + +{{#jackson}} + @JsonValue +{{/jackson}} + public {{{dataType}}} getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + +{{#jackson}} + @JsonCreator +{{/jackson}} + public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue(String text) { + for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + if (String.valueOf(b.value).equals(text)) { + return b; + } + } + return null; + } +{{#gson}} + + public static class Adapter extends TypeAdapter<{{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}> { + @Override + public void write(final JsonWriter jsonWriter, final {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} enumeration) throws IOException { + jsonWriter.value(enumeration.getValue()); + } + + @Override + public {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException { + {{{dataType}}} value = jsonReader.{{#isInteger}}nextInt(){{/isInteger}}{{^isInteger}}next{{{dataType}}}(){{/isInteger}}; + return {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue(String.valueOf(value)); + } + } +{{/gson}} +} diff --git a/modelInnerEnum.mustache b/modelInnerEnum.mustache new file mode 100644 index 00000000000..e7ffa65d130 --- /dev/null +++ b/modelInnerEnum.mustache @@ -0,0 +1,59 @@ + /** + * {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}} + */ +{{#gson}} + @JsonAdapter({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.Adapter.class) +{{/gson}} + public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} { + {{#allowableValues}} + {{#enumVars}} + {{{name}}}({{{value}}}){{^-last}}, + {{/-last}}{{#-last}};{{/-last}} + {{/enumVars}} + {{/allowableValues}} + + private {{{datatype}}} value; + + {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}({{{datatype}}} value) { + this.value = value; + } + +{{#jackson}} + @JsonValue +{{/jackson}} + public {{{datatype}}} getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + +{{#jackson}} + @JsonCreator +{{/jackson}} + public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue(String text) { + for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + if (String.valueOf(b.value).equals(text)) { + return b; + } + } + return null; + } +{{#gson}} + + public static class Adapter extends TypeAdapter<{{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}> { + @Override + public void write(final JsonWriter jsonWriter, final {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} enumeration) throws IOException { + jsonWriter.value(enumeration.getValue()); + } + + @Override + public {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException { + {{{datatype}}} value = jsonReader.{{#isInteger}}nextInt(){{/isInteger}}{{^isInteger}}next{{{datatype}}}(){{/isInteger}}; + return {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue(String.valueOf(value)); + } + } +{{/gson}} + } diff --git a/model_doc.mustache b/model_doc.mustache new file mode 100644 index 00000000000..658df8d5322 --- /dev/null +++ b/model_doc.mustache @@ -0,0 +1,3 @@ +{{#models}}{{#model}} +{{#isEnum}}{{>enum_outer_doc}}{{/isEnum}}{{^isEnum}}{{>pojo_doc}}{{/isEnum}} +{{/model}}{{/models}} diff --git a/pojo.mustache b/pojo.mustache new file mode 100644 index 00000000000..03b0f666d3e --- /dev/null +++ b/pojo.mustache @@ -0,0 +1,279 @@ +/** + * {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}} + */{{#description}} +@ApiModel(description = "{{{description}}}"){{/description}} +{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} +public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcelableModel}}implements Parcelable {{#serializableModel}}, Serializable {{/serializableModel}}{{/parcelableModel}}{{^parcelableModel}}{{#serializableModel}}implements Serializable {{/serializableModel}}{{/parcelableModel}}{ +{{#serializableModel}} + private static final long serialVersionUID = 1L; + +{{/serializableModel}} + {{#vars}} + {{#isEnum}} + {{^isContainer}} +{{>modelInnerEnum}} + {{/isContainer}} + {{/isEnum}} + {{#items.isEnum}} + {{#items}} + {{^isContainer}} +{{>modelInnerEnum}} + {{/isContainer}} + {{/items}} + {{/items.isEnum}} + {{#jackson}} + @JsonProperty("{{baseName}}") + {{#withXml}} + {{^isContainer}} + @JacksonXmlProperty({{#isXmlAttribute}}isAttribute = true, {{/isXmlAttribute}}{{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}localName = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isContainer}} + {{#isContainer}} + {{#isXmlWrapped}} + // items.xmlName={{items.xmlName}} + @JacksonXmlElementWrapper(useWrapping = {{isXmlWrapped}}, {{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}localName = "{{#items.xmlName}}{{items.xmlName}}{{/items.xmlName}}{{^items.xmlName}}{{items.baseName}}{{/items.xmlName}}") + {{/isXmlWrapped}} + {{/isContainer}} + {{/withXml}} + {{/jackson}} + {{#withXml}} + {{#isXmlAttribute}} + @XmlAttribute(name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlAttribute}} + {{^isXmlAttribute}} + {{^isContainer}} + @XmlElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isContainer}} + {{#isContainer}} + // Is a container wrapped={{isXmlWrapped}} + {{#items}} + // items.name={{name}} items.baseName={{baseName}} items.xmlName={{xmlName}} items.xmlNamespace={{xmlNamespace}} + // items.example={{example}} items.type={{datatype}} + @XmlElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/items}} + {{#isXmlWrapped}} + @XmlElementWrapper({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlWrapped}} + {{/isContainer}} + {{/isXmlAttribute}} + {{/withXml}} + {{#gson}} + @SerializedName("{{baseName}}") + {{/gson}} + {{#isContainer}} + private {{{datatypeWithEnum}}} {{name}}{{#required}} = {{{defaultValue}}}{{/required}}{{^required}} = null{{/required}}; + {{/isContainer}} + {{^isContainer}} + private {{{datatypeWithEnum}}} {{name}} = {{{defaultValue}}}; + {{/isContainer}} + + {{/vars}} + {{#parcelableModel}} + public {{classname}}() { + {{#parent}} + super(); + {{/parent}} + {{#gson}} + {{#discriminator}} + this.{{discriminator}} = this.getClass().getSimpleName(); + {{/discriminator}} + {{/gson}} + } + {{/parcelableModel}} + {{^parcelableModel}} + {{#gson}} + {{#discriminator}} + public {{classname}}() { + this.{{discriminator}} = this.getClass().getSimpleName(); + } + {{/discriminator}} + {{/gson}} + {{/parcelableModel}} + {{#vars}} + {{^isReadOnly}} + public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { + this.{{name}} = {{name}}; + return this; + } + {{#isListContainer}} + + public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.add({{name}}Item); + return this; + } + {{/isListContainer}} + {{#isMapContainer}} + + public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.put(key, {{name}}Item); + return this; + } + {{/isMapContainer}} + + {{/isReadOnly}} + /** + {{#description}} + * {{description}} + {{/description}} + {{^description}} + * Get {{name}} + {{/description}} + {{#minimum}} + * minimum: {{minimum}} + {{/minimum}} + {{#maximum}} + * maximum: {{maximum}} + {{/maximum}} + * @return {{name}} + **/ +{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} @ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") +{{#vendorExtensions.extraAnnotation}} + {{{vendorExtensions.extraAnnotation}}} +{{/vendorExtensions.extraAnnotation}} + public {{{datatypeWithEnum}}} {{#isBoolean}}is{{/isBoolean}}{{getter}}() { + return {{name}}; + } + {{^isReadOnly}} + + public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { + this.{{name}} = {{name}}; + } + {{/isReadOnly}} + + {{/vars}} + +{{^supportJava6}} + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + }{{#hasVars}} + {{classname}} {{classVarName}} = ({{classname}}) o; + return {{#vars}}{{#isByteArray}}Arrays{{/isByteArray}}{{#isBinary}}Arrays{{/isBinary}}{{^isByteArray}}{{^isBinary}}Objects{{/isBinary}}{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{#hasMore}} && + {{/hasMore}}{{/vars}}{{#parent}} && + super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} + return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}} + } + + @Override + public int hashCode() { + return Objects.hash({{#vars}}{{^isByteArray}}{{^isBinary}}{{name}}{{/isBinary}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{#isBinary}}Arrays.hashCode({{name}}){{/isBinary}}{{#hasMore}}, {{/hasMore}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); + } + +{{/supportJava6}} +{{#supportJava6}} + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + }{{#hasVars}} + {{classname}} {{classVarName}} = ({{classname}}) o; + return {{#vars}}ObjectUtils.equals(this.{{name}}, {{classVarName}}.{{name}}){{#hasMore}} && + {{/hasMore}}{{/vars}}{{#parent}} && + super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} + return true;{{/hasVars}} + } + + @Override + public int hashCode() { + return ObjectUtils.hashCodeMulti({{#vars}}{{name}}{{#hasMore}}, {{/hasMore}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); + } + +{{/supportJava6}} + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class {{classname}} {\n"); + {{#parent}}sb.append(" ").append(toIndentedString(super.toString())).append("\n");{{/parent}} + {{#vars}}sb.append(" {{name}}: ").append(toIndentedString({{name}})).append("\n"); + {{/vars}}sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + +{{#parcelableModel}} + + public void writeToParcel(Parcel out, int flags) { +{{#model}} +{{#isArrayModel}} + out.writeList(this); +{{/isArrayModel}} +{{^isArrayModel}} +{{#parent}} + super.writeToParcel(out, flags); +{{/parent}} +{{#vars}} + out.writeValue({{name}}); +{{/vars}} +{{/isArrayModel}} +{{/model}} + } + + {{classname}}(Parcel in) { +{{#isArrayModel}} + in.readTypedList(this, {{arrayModelType}}.CREATOR); +{{/isArrayModel}} +{{^isArrayModel}} +{{#parent}} + super(in); +{{/parent}} +{{#vars}} +{{#isPrimitiveType}} + {{name}} = ({{{datatypeWithEnum}}})in.readValue(null); +{{/isPrimitiveType}} +{{^isPrimitiveType}} + {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader()); +{{/isPrimitiveType}} +{{/vars}} +{{/isArrayModel}} + } + + public int describeContents() { + return 0; + } + + public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() { + public {{classname}} createFromParcel(Parcel in) { +{{#model}} +{{#isArrayModel}} + {{classname}} result = new {{classname}}(); + result.addAll(in.readArrayList({{arrayModelType}}.class.getClassLoader())); + return result; +{{/isArrayModel}} +{{^isArrayModel}} + return new {{classname}}(in); +{{/isArrayModel}} +{{/model}} + } + public {{classname}}[] newArray(int size) { + return new {{classname}}[size]; + } + }; +{{/parcelableModel}} +} diff --git a/pojo_doc.mustache b/pojo_doc.mustache new file mode 100644 index 00000000000..0e4c0749866 --- /dev/null +++ b/pojo_doc.mustache @@ -0,0 +1,15 @@ +# {{classname}} + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +{{#vars}}**{{name}}** | {{#isEnum}}[**{{datatypeWithEnum}}**](#{{datatypeWithEnum}}){{/isEnum}}{{^isEnum}}{{#isPrimitiveType}}**{{datatype}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{datatype}}**]({{complexType}}.md){{/isPrimitiveType}}{{/isEnum}} | {{description}} | {{^required}} [optional]{{/required}}{{#readOnly}} [readonly]{{/readOnly}} +{{/vars}} +{{#vars}}{{#isEnum}} + + +## Enum: {{datatypeWithEnum}} +Name | Value +---- | -----{{#allowableValues}}{{#enumVars}} +{{name}} | {{value}}{{/enumVars}}{{/allowableValues}} +{{/isEnum}}{{/vars}} diff --git a/pom.mustache b/pom.mustache new file mode 100644 index 00000000000..3de31865335 --- /dev/null +++ b/pom.mustache @@ -0,0 +1,336 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{artifactUrl}} + {{artifactDescription}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + {{#java8}} + + 1.8 + 1.8 + {{/java8}} + {{^java8}} + + 1.7 + 1.7 + {{/java8}} + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-annotations-version} + + + + + com.sun.jersey + jersey-client + ${jersey-version} + + + com.sun.jersey.contribs + jersey-multipart + ${jersey-version} + + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-version} + + + com.fasterxml.jackson.jaxrs + jackson-jaxrs-json-provider + ${jackson-version} + + {{#withXml}} + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson-version} + + + {{/withXml}} + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + {{/joda}} + {{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{/java8}} + {{#threetenbp}} + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${jackson-version} + + {{/threetenbp}} + {{^java8}} + + + com.brsanthu + migbase64 + 2.2 + + {{/java8}} + {{#supportJava6}} + + org.apache.commons + commons-lang3 + ${commons_lang3_version} + + + commons-io + commons-io + ${commons_io_version} + + {{/supportJava6}} + {{#useBeanValidation}} + + + javax.validation + validation-api + 1.1.0.Final + provided + + {{/useBeanValidation}} + {{#parcelableModel}} + + + com.google.android + android + 4.1.1.4 + provided + + {{/parcelableModel}} + + + junit + junit + ${junit-version} + test + + + + UTF-8 + 1.5.17 + 1.19.4 + {{#supportJava6}} + 2.5 + 3.6 + {{/supportJava6}} + {{^threetenbp}}2.7.5{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} + 1.0.0 + 4.12 + + diff --git a/settings.gradle.mustache b/settings.gradle.mustache new file mode 100644 index 00000000000..b8fd6c4c41f --- /dev/null +++ b/settings.gradle.mustache @@ -0,0 +1 @@ +rootProject.name = "{{artifactId}}" \ No newline at end of file diff --git a/travis.mustache b/travis.mustache new file mode 100644 index 00000000000..70cb81a67c2 --- /dev/null +++ b/travis.mustache @@ -0,0 +1,17 @@ +# +# Generated by: https://github.com/swagger-api/swagger-codegen.git +# +language: java +jdk: + - oraclejdk8 + - oraclejdk7 +before_install: + # ensure gradlew has proper permission + - chmod a+x ./gradlew +script: + # test using maven + - mvn test + # uncomment below to test using gradle + # - gradle test + # uncomment below to test using sbt + # - sbt test diff --git a/typeInfoAnnotation.mustache b/typeInfoAnnotation.mustache new file mode 100644 index 00000000000..2d7983d0101 --- /dev/null +++ b/typeInfoAnnotation.mustache @@ -0,0 +1,7 @@ +{{#jackson}} +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "{{discriminator}}", visible = true ) +@JsonSubTypes({ + {{#children}} + @JsonSubTypes.Type(value = {{classname}}.class, name = "{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}"), + {{/children}} +}){{/jackson}} diff --git a/xmlAnnotation.mustache b/xmlAnnotation.mustache new file mode 100644 index 00000000000..04566fa1167 --- /dev/null +++ b/xmlAnnotation.mustache @@ -0,0 +1,6 @@ +{{#withXml}} + +@XmlRootElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{classname}}{{/xmlName}}") +@XmlAccessorType(XmlAccessType.FIELD) +{{#jackson}} +@JacksonXmlRootElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}localName = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{classname}}{{/xmlName}}"){{/jackson}}{{/withXml}} \ No newline at end of file From 8fbbee88bc1baa324878b7ca33778d4bb6309530 Mon Sep 17 00:00:00 2001 From: Jeremie Bresson Date: Tue, 17 Apr 2018 09:19:10 +0200 Subject: [PATCH 005/370] Add OpenAPI spec 3.0 support (beta) Co-authored-by: Akihito Nakano Co-authored-by: Jeremie Bresson Co-authored-by: Jim Schubert Co-authored-by: Martin Delille Co-authored-by: Tomasz Prus Co-authored-by: William Cheng --- build.gradle.mustache | 6 +- libraries/retrofit/formParams.mustache | 2 +- libraries/retrofit2/formParams.mustache | 2 +- libraries/retrofit2/formParams.mustache.save | 2 +- pojo.mustache | 67 +++++++++++++++----- 5 files changed, 58 insertions(+), 21 deletions(-) diff --git a/build.gradle.mustache b/build.gradle.mustache index cbc39ce3aca..af0d3d55d85 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -122,13 +122,13 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" {{#joda}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version", + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} {{#java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version", + compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_version", + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_version" {{/threetenbp}} {{^java8}} compile "com.brsanthu:migbase64:2.2" diff --git a/libraries/retrofit/formParams.mustache b/libraries/retrofit/formParams.mustache index f1f9027ae51..851072b3f65 100644 --- a/libraries/retrofit/formParams.mustache +++ b/libraries/retrofit/formParams.mustache @@ -1 +1 @@ -{{#isFormParam}}{{#notFile}}{{#isMultipart}}@retrofit.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit.http.Field{{/isMultipart}}("{{baseName}}") {{{dataType}}} {{paramName}}{{/notFile}}{{#isFile}}{{#isMultipart}}@retrofit.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit.http.Field{{/isMultipart}}("{{baseName}}") TypedFile {{paramName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file +{{#isFormParam}}{{^isFile}}{{#isMultipart}}@retrofit.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit.http.Field{{/isMultipart}}("{{baseName}}") {{{dataType}}} {{paramName}}{{/isFile}}{{#isFile}}{{#isMultipart}}@retrofit.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit.http.Field{{/isMultipart}}("{{baseName}}") TypedFile {{paramName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file diff --git a/libraries/retrofit2/formParams.mustache b/libraries/retrofit2/formParams.mustache index b3f54cc4ddb..f85b028870c 100644 --- a/libraries/retrofit2/formParams.mustache +++ b/libraries/retrofit2/formParams.mustache @@ -1 +1 @@ -{{#isFormParam}}{{#notFile}}{{#isMultipart}}@retrofit2.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit2.http.Field{{/isMultipart}}("{{baseName}}") {{{dataType}}} {{paramName}}{{/notFile}}{{#isFile}}{{#isMultipart}}@retrofit2.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit2.http.Field{{/isMultipart}} MultipartBody.Part {{paramName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file +{{#isFormParam}}{{^isFile}}{{#isMultipart}}@retrofit2.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit2.http.Field{{/isMultipart}}("{{baseName}}") {{{dataType}}} {{paramName}}{{/isFile}}{{#isFile}}{{#isMultipart}}@retrofit2.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit2.http.Field{{/isMultipart}} MultipartBody.Part {{paramName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file diff --git a/libraries/retrofit2/formParams.mustache.save b/libraries/retrofit2/formParams.mustache.save index 84c4704432a..a3a3c16f1c0 100644 --- a/libraries/retrofit2/formParams.mustache.save +++ b/libraries/retrofit2/formParams.mustache.save @@ -1 +1 @@ -{{#isFormParam}}{{#notFile}}{{#isMultipart}}retrofit.http@retrofit2.http.Part{{/isMultipart}}{{^isMultipart}}@Field{{/isMultipart}}("{{baseName}}") {{{dataType}}} {{paramName}}{{/notFile}}{{#isFile}}{{#isMultipart}}@Part{{/isMultipart}}{{^isMultipart}}@Field{{/isMultipart}} okhttp3.MultipartBody.Part {{paramName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file +{{#isFormParam}}{{^isFile}}{{#isMultipart}}retrofit.http@retrofit2.http.Part{{/isMultipart}}{{^isMultipart}}@Field{{/isMultipart}}("{{baseName}}") {{{dataType}}} {{paramName}}{{/isFile}}{{#isFile}}{{#isMultipart}}@Part{{/isMultipart}}{{^isMultipart}}@Field{{/isMultipart}} okhttp3.MultipartBody.Part {{paramName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file diff --git a/pojo.mustache b/pojo.mustache index 5bbeef075ba..03b0f666d3e 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -67,6 +67,19 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela {{/isContainer}} {{/vars}} + {{#parcelableModel}} + public {{classname}}() { + {{#parent}} + super(); + {{/parent}} + {{#gson}} + {{#discriminator}} + this.{{discriminator}} = this.getClass().getSimpleName(); + {{/discriminator}} + {{/gson}} + } + {{/parcelableModel}} + {{^parcelableModel}} {{#gson}} {{#discriminator}} public {{classname}}() { @@ -74,6 +87,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela } {{/discriminator}} {{/gson}} + {{/parcelableModel}} {{#vars}} {{^isReadOnly}} public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { @@ -203,27 +217,41 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela return o.toString().replace("\n", "\n "); } - {{#parcelableModel}} +{{#parcelableModel}} + public void writeToParcel(Parcel out, int flags) { - {{#parent}} super.writeToParcel(out, flags); {{/parent}} {{#vars}} +{{#model}} +{{#isArrayModel}} + out.writeList(this); +{{/isArrayModel}} +{{^isArrayModel}} +{{#parent}} + super.writeToParcel(out, flags); +{{/parent}} +{{#vars}} out.writeValue({{name}}); - {{/vars}} - } - - public {{classname}}() { - super(); +{{/vars}} +{{/isArrayModel}} +{{/model}} } {{classname}}(Parcel in) { - {{#parent}} super(in); {{/parent}} - {{#vars}} - {{#isPrimitiveType}} +{{#isArrayModel}} + in.readTypedList(this, {{arrayModelType}}.CREATOR); +{{/isArrayModel}} +{{^isArrayModel}} +{{#parent}} + super(in); +{{/parent}} +{{#vars}} +{{#isPrimitiveType}} {{name}} = ({{{datatypeWithEnum}}})in.readValue(null); - {{/isPrimitiveType}} - {{^isPrimitiveType}} +{{/isPrimitiveType}} +{{^isPrimitiveType}} {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader()); - {{/isPrimitiveType}} - {{/vars}} +{{/isPrimitiveType}} +{{/vars}} +{{/isArrayModel}} } public int describeContents() { @@ -232,11 +260,20 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() { public {{classname}} createFromParcel(Parcel in) { +{{#model}} +{{#isArrayModel}} + {{classname}} result = new {{classname}}(); + result.addAll(in.readArrayList({{arrayModelType}}.class.getClassLoader())); + return result; +{{/isArrayModel}} +{{^isArrayModel}} return new {{classname}}(in); +{{/isArrayModel}} +{{/model}} } public {{classname}}[] newArray(int size) { return new {{classname}}[size]; } }; - {{/parcelableModel}} +{{/parcelableModel}} } From 27a5faa113c9b2ab3563ab3ed4fd8fc261c0c8ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Wed, 18 Apr 2018 09:19:40 +0200 Subject: [PATCH 006/370] Format mustache pom template (#125) --- libraries/google-api-client/pom.mustache | 6 ++---- libraries/jersey2/pom.mustache | 6 ++---- libraries/resteasy/pom.mustache | 6 ++---- libraries/resttemplate/pom.mustache | 6 ++---- libraries/vertx/pom.mustache | 3 +-- pom.mustache | 6 ++---- 6 files changed, 11 insertions(+), 22 deletions(-) diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index fb2d2bdfab7..e8605bbac61 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -140,13 +140,11 @@ 3.6.1 {{#java8}} - - 1.8 + 1.8 1.8 {{/java8}} {{^java8}} - - 1.7 + 1.7 1.7 {{/java8}} diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 2dff93306a0..85f38605dd8 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -140,13 +140,11 @@ 3.6.1 {{#java8}} - - 1.8 + 1.8 1.8 {{/java8}} {{^java8}} - - 1.7 + 1.7 1.7 {{/java8}} diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index 2b4a9aa5537..456bee18137 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -121,13 +121,11 @@ 2.5.1 {{#java8}} - - 1.8 + 1.8 1.8 {{/java8}} {{^java8}} - - 1.7 + 1.7 1.7 {{/java8}} diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache index e2bdc3a8b68..01abe39efb5 100644 --- a/libraries/resttemplate/pom.mustache +++ b/libraries/resttemplate/pom.mustache @@ -140,13 +140,11 @@ 3.6.1 {{#java8}} - - 1.8 + 1.8 1.8 {{/java8}} {{^java8}} - - 1.7 + 1.7 1.7 {{/java8}} diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache index d524edeaa94..32f94b62639 100644 --- a/libraries/vertx/pom.mustache +++ b/libraries/vertx/pom.mustache @@ -139,8 +139,7 @@ maven-compiler-plugin 3.6.1 - - 1.8 + 1.8 1.8 diff --git a/pom.mustache b/pom.mustache index 3de31865335..7e61c4c05ad 100644 --- a/pom.mustache +++ b/pom.mustache @@ -140,13 +140,11 @@ 3.6.1 {{#java8}} - - 1.8 + 1.8 1.8 {{/java8}} {{^java8}} - - 1.7 + 1.7 1.7 {{/java8}} From c7aaa7983ab66e3b6a5607f3956a934597d1533e Mon Sep 17 00:00:00 2001 From: William Cheng Date: Thu, 19 Apr 2018 15:02:22 +0800 Subject: [PATCH 007/370] update discriminator to discriminatorName (#142) --- JSON.mustache | 2 +- libraries/retrofit2/JSON.mustache | 2 +- pojo.mustache | 4 ++-- typeInfoAnnotation.mustache | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/JSON.mustache b/JSON.mustache index 63814a361fc..a717df178e3 100644 --- a/JSON.mustache +++ b/JSON.mustache @@ -71,7 +71,7 @@ public class JSON { classByDiscriminatorValue.put("{{classname}}".toUpperCase(), {{classname}}.class); return getClassByDiscriminator( classByDiscriminatorValue, - getDiscriminatorValue(readElement, "{{discriminator}}")); + getDiscriminatorValue(readElement, "{{{discriminatorName}}}")); } }) {{/parent}} diff --git a/libraries/retrofit2/JSON.mustache b/libraries/retrofit2/JSON.mustache index abab9159d79..3dcea989c19 100644 --- a/libraries/retrofit2/JSON.mustache +++ b/libraries/retrofit2/JSON.mustache @@ -68,7 +68,7 @@ public class JSON { classByDiscriminatorValue.put("{{classname}}".toUpperCase(), {{classname}}.class); return getClassByDiscriminator( classByDiscriminatorValue, - getDiscriminatorValue(readElement, "{{discriminator}}")); + getDiscriminatorValue(readElement, "{{{discriminatorName}}}")); } }) {{/parent}} diff --git a/pojo.mustache b/pojo.mustache index 03b0f666d3e..351430dbe74 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -74,7 +74,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela {{/parent}} {{#gson}} {{#discriminator}} - this.{{discriminator}} = this.getClass().getSimpleName(); + this.{{{discriminatorName}}} = this.getClass().getSimpleName(); {{/discriminator}} {{/gson}} } @@ -83,7 +83,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela {{#gson}} {{#discriminator}} public {{classname}}() { - this.{{discriminator}} = this.getClass().getSimpleName(); + this.{{{discriminatorName}}} = this.getClass().getSimpleName(); } {{/discriminator}} {{/gson}} diff --git a/typeInfoAnnotation.mustache b/typeInfoAnnotation.mustache index 2d7983d0101..1e2d5134b34 100644 --- a/typeInfoAnnotation.mustache +++ b/typeInfoAnnotation.mustache @@ -1,5 +1,5 @@ {{#jackson}} -@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "{{discriminator}}", visible = true ) +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "{{{discriminatorName}}}", visible = true ) @JsonSubTypes({ {{#children}} @JsonSubTypes.Type(value = {{classname}}.class, name = "{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}"), From 48840c02433feb345a48758e7baa27e1ea417209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Thu, 19 Apr 2018 19:11:27 +0200 Subject: [PATCH 008/370] Improve getter name handling for boolean properties (#141) * Handle java boolean getter at codegen level instead of template. * {{#isBoolean}}is{{/isBoolean}}{{getter}} is no longer necessary in templates. * Use 'toBooleanGetter' instead of replace in PhpSymfonyServerCodegen --- pojo.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pojo.mustache b/pojo.mustache index 351430dbe74..26f1e2df379 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -139,7 +139,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela {{#vendorExtensions.extraAnnotation}} {{{vendorExtensions.extraAnnotation}}} {{/vendorExtensions.extraAnnotation}} - public {{{datatypeWithEnum}}} {{#isBoolean}}is{{/isBoolean}}{{getter}}() { + public {{{datatypeWithEnum}}} {{getter}}() { return {{name}}; } {{^isReadOnly}} From dcbf871e9fb48d9a60d53609a0e77513216331cf Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 20 Apr 2018 14:20:13 +0800 Subject: [PATCH 009/370] fix java binary mapping (#158) --- pojo.mustache | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pojo.mustache b/pojo.mustache index 26f1e2df379..3224cb256dd 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -161,7 +161,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela return false; }{{#hasVars}} {{classname}} {{classVarName}} = ({{classname}}) o; - return {{#vars}}{{#isByteArray}}Arrays{{/isByteArray}}{{#isBinary}}Arrays{{/isBinary}}{{^isByteArray}}{{^isBinary}}Objects{{/isBinary}}{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{#hasMore}} && + return {{#vars}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{#hasMore}} && {{/hasMore}}{{/vars}}{{#parent}} && super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}} @@ -169,7 +169,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela @Override public int hashCode() { - return Objects.hash({{#vars}}{{^isByteArray}}{{^isBinary}}{{name}}{{/isBinary}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{#isBinary}}Arrays.hashCode({{name}}){{/isBinary}}{{#hasMore}}, {{/hasMore}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); + return Objects.hash({{#vars}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{#hasMore}}, {{/hasMore}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); } {{/supportJava6}} From cc0080e91df1841a16dea85b85ebc26197e94c10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Sun, 22 Apr 2018 10:32:30 +0200 Subject: [PATCH 010/370] Merge branch 'swagger-codegen_renamed' into 'master' (#183) * Added vendorExtensions.x-isPrimitive. (#7991) * Added vendorExtensions.x-isPrimitive. Switch template for constructFromObject. * Reflect review indication. * [typescript-angular] AOT-compatible API client (via ng-packagr and ngc) (#7984) * typescript-angular: uses ng-packagr for the build see https://github.com/swagger-api/swagger-codegen/issues/6722 see https://github.com/swagger-api/swagger-codegen/pull/6735/ * this should make everybody happy: Angular 2/4/5 AOT support - uses ngc when targeting Angular 2 (as seen in https://github.com/swagger-api/swagger-codegen/pull/6735) - uses ng-packagr 1 when targeting Angular 4 - uses ng-packagr 2 when targeting Angular 5 * removes bogus import * cleans / updates Petstore samples, adds a new sample for Angular 5 * typo in README * fixes broken travis build. adds pom.xml files again This reverts commit 471d248a2e9b5d8eed10c71644c222c053e007b0. * makes usage of `dist` more clear and i feel generally better when `npm run build` is called explicitly. - for ng-packagr 2 is doesn't matter, since the final package.json does not have any scripts - for old ng-packagr 1 it matters, scripts are copied to the final package.json which breaks installation via `npm install {{npmName}} --save` (it runs `npm run build` again) * typescript-angular: small improvements as suggested by @macjohnny * angular-typescript: updated petstore samples, 3rd try * Issue 5542, always generate pom and readme (#7977) * Issue 5542, generate pom.xml with separate parameter. InterfaceOnly=true for not generating pom.xml not works in every situation. * Issue 5542, generate pom.xml with separate parameter. InterfaceOnly=true for not generating pom.xml not works in every situation. * Issue #5542 Always generate pom.xml and README.md * [TypeScript][Angular] fix date path parameters (#7476, #7302) (#7479) * #7476, #7302: [TypeScript][Angular] fix date path parameters, fix path parameters with :.+ in it * #7476, #7302: [TypeScript][Angular] fix date path parameters, fix path parameters with :.+ in it * #7476, #7302: [TypeScript][Angular] fix date path parameters, fix path parameters with :.+ in it * #7476: generate samples * code cleanup * #7476: improve variable description * #7302: revert character skipping, since it will now have the same parameter name in the method signature and in the api path * #7302: generate samples * typescript-angular: added Interfaces to api exports if withInterfaces is selected (#7975) * added Interfaces to api exports if withInterfaces is selected * removed import of interface classes * added gererated petstore example api.ts * Fix Issue 8014 * Adapted to work with Angular2 Http and Angular 4.3+ HttpClient * removed unnecessary (others) for ng HttpClient from Interface * Golang Client Refactor (body and model in errors, typed optional parameters) (#7987) * Return abstracted errors with model data if available. * update tests with error models. * Return error models on the abstract type. * dont leak FH * duplicate of PR #7752 for issue #7511 * Change optional parameters to structs. * update documentation * fix circleCI failure * [typescript][angular] query parameter with null value should not be set (#8033) * #7893: [typescript][angular] fix optional query parameter null value * #7893: [typescript][angular] generate samples * #7893: [typescript][angular] generate samples * Version rest-assured has been updated to 3.1.0 (#8052) * [Dart] Fixes TypeError in Dart 2 mode (#7959) * Properly convert lists to dart types * Updated sample petstore client * Fixed maps in Dart strong mode Fixed list parsing for null-elements * change parseDate in es6/APIClient (#7973) * [PHP] Improve duplicated validation logic (#7954) * Improve duplicated validation logic * Update the samples --- libraries/rest-assured/api.mustache | 27 ++------------------ libraries/rest-assured/build.gradle.mustache | 2 +- libraries/rest-assured/build.sbt.mustache | 2 +- libraries/rest-assured/pom.mustache | 2 +- 4 files changed, 5 insertions(+), 28 deletions(-) diff --git a/libraries/rest-assured/api.mustache b/libraries/rest-assured/api.mustache index 1d1a5d9ae54..4e784645989 100644 --- a/libraries/rest-assured/api.mustache +++ b/libraries/rest-assured/api.mustache @@ -30,11 +30,8 @@ public class {{classname}} { private RequestSpecBuilder reqSpec; - private JSON json; - private {{classname}}(RequestSpecBuilder reqSpec) { this.reqSpec = reqSpec; - this.json = new JSON(); } public static {{classname}} {{classVarName}}(RequestSpecBuilder reqSpec) { @@ -53,26 +50,6 @@ public class {{classname}} { {{/operation}} {{/operations}} - /** - * Get JSON - * - * @return JSON object - */ - public JSON getJSON() { - return json; - } - - /** - * Set JSON - * - * @param json JSON object - * @return {{classname}} - */ - public {{classname}} setJSON(JSON json) { - this.json = json; - return this; - } - /** * Customise request specification */ @@ -152,7 +129,7 @@ public class {{classname}} { */ public {{{returnType}}} executeAs(Function handler) { Type type = new TypeToken<{{{returnType}}}>(){}.getType(); - return getJSON().deserialize(execute(handler).asString(), type); + return execute(handler).as(type); } {{/returnType}} {{#bodyParams}} @@ -161,7 +138,7 @@ public class {{classname}} { * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} */ public {{operationIdCamelCase}}Oper body({{{dataType}}} {{paramName}}) { - reqSpec.setBody(getJSON().serialize({{paramName}})); + reqSpec.setBody({{paramName}}); return this; } {{/bodyParams}} diff --git a/libraries/rest-assured/build.gradle.mustache b/libraries/rest-assured/build.gradle.mustache index fc67b62d13e..54b90483f4c 100644 --- a/libraries/rest-assured/build.gradle.mustache +++ b/libraries/rest-assured/build.gradle.mustache @@ -95,7 +95,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.15" - rest_assured_version = "3.0.6" + rest_assured_version = "3.1.0" junit_version = "4.12" gson_version = "2.6.1" gson_fire_version = "1.8.2" diff --git a/libraries/rest-assured/build.sbt.mustache b/libraries/rest-assured/build.sbt.mustache index 289345c3a0a..68f3eff08d0 100644 --- a/libraries/rest-assured/build.sbt.mustache +++ b/libraries/rest-assured/build.sbt.mustache @@ -10,7 +10,7 @@ lazy val root = (project in file(".")). resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( "io.swagger" % "swagger-annotations" % "1.5.15", - "io.rest-assured" % "scala-support" % "3.0.6", + "io.rest-assured" % "scala-support" % "3.1.0", "com.google.code.gson" % "gson" % "2.6.1", "io.gsonfire" % "gson-fire" % "1.8.2" % "compile", {{#joda}} diff --git a/libraries/rest-assured/pom.mustache b/libraries/rest-assured/pom.mustache index 80f043340c2..1d0c1711389 100644 --- a/libraries/rest-assured/pom.mustache +++ b/libraries/rest-assured/pom.mustache @@ -246,7 +246,7 @@ UTF-8 1.5.15 - 3.0.6 + 3.1.0 2.6.1 1.8.2 1.0.0 From 6e46c736f3fdc89bcaa4d7f66657f56ee2fd4ed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Mon, 23 Apr 2018 20:39:30 +0200 Subject: [PATCH 011/370] java rest-assured: fix javadoc in templates (#207) --- libraries/rest-assured/ApiClient.mustache | 2 ++ libraries/rest-assured/api.mustache | 38 ++++++++++++++++------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/libraries/rest-assured/ApiClient.mustache b/libraries/rest-assured/ApiClient.mustache index 2b269854872..184dc13e05c 100644 --- a/libraries/rest-assured/ApiClient.mustache +++ b/libraries/rest-assured/ApiClient.mustache @@ -46,6 +46,8 @@ public class ApiClient { /** * Use common specification for all operations + * @param supplier supplier + * @return configuration */ public Config reqSpecSupplier(Supplier supplier) { this.baseReqSpec = supplier; diff --git a/libraries/rest-assured/api.mustache b/libraries/rest-assured/api.mustache index 4e784645989..8d90f195764 100644 --- a/libraries/rest-assured/api.mustache +++ b/libraries/rest-assured/api.mustache @@ -51,8 +51,10 @@ public class {{classname}} { {{/operations}} /** - * Customise request specification - */ + * Customise request specification + * @param consumer consumer + * @return api + */ public {{classname}} reqSpec(Consumer consumer) { consumer.accept(reqSpec); return this; @@ -68,7 +70,7 @@ public class {{classname}} { * @see #{{#isPathParam}}{{paramName}}Path{{/isPathParam}}{{#isQueryParam}}{{paramName}}Query{{/isQueryParam}}{{#isFormParam}}{{^isFile}}{{paramName}}Form{{/isFile}}{{#isFile}}{{paramName}}MultiPart{{/isFile}}{{/isFormParam}}{{#isHeaderParam}}{{paramName}}Header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} {{/allParams}} {{#returnType}} - * return {{{returnType}}} + * return {{returnType}} {{/returnType}} {{#isDeprecated}} * @deprecated @@ -117,6 +119,9 @@ public class {{classname}} { /** * {{httpMethod}} {{path}} + * @param handler handler + * @param type + * @return type */ public T execute(Function handler) { return handler.apply(RestAssured.given().spec(reqSpec.build()).expect().spec(respSpec.build()).when().request({{httpMethod}}, REQ_URI)); @@ -125,7 +130,8 @@ public class {{classname}} { /** * {{httpMethod}} {{path}} - * @return {{{returnType}}} + * @param handler handler + * @return {{returnType}} */ public {{{returnType}}} executeAs(Function handler) { Type type = new TypeToken<{{{returnType}}}>(){}.getType(); @@ -135,7 +141,8 @@ public class {{classname}} { {{#bodyParams}} /** - * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @return operation */ public {{operationIdCamelCase}}Oper body({{{dataType}}} {{paramName}}) { reqSpec.setBody({{paramName}}); @@ -145,7 +152,8 @@ public class {{classname}} { {{#headerParams}} /** - * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @return operation */ public {{operationIdCamelCase}}Oper {{paramName}}Header(String {{paramName}}) { reqSpec.addHeader("{{baseName}}", {{paramName}}); @@ -155,7 +163,8 @@ public class {{classname}} { {{#pathParams}} /** - * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @return operation */ public {{operationIdCamelCase}}Oper {{paramName}}Path(Object {{paramName}}) { reqSpec.addPathParam("{{baseName}}", {{paramName}}); @@ -165,7 +174,8 @@ public class {{classname}} { {{#queryParams}} /** - * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @return operation */ public {{operationIdCamelCase}}Oper {{paramName}}Query(Object... {{paramName}}) { reqSpec.addQueryParam("{{baseName}}", {{paramName}}); @@ -176,7 +186,8 @@ public class {{classname}} { {{^isFile}} /** - * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @return operation */ public {{operationIdCamelCase}}Oper {{paramName}}Form(Object... {{paramName}}) { reqSpec.addFormParam("{{baseName}}", {{paramName}}); @@ -188,9 +199,10 @@ public class {{classname}} { {{#isFile}} /** - * It will assume that the control name is file and the is + * It will assume that the control name is file and the <content-type> is <application/octet-stream> * @see #reqSpec for customise - * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @return operation */ public {{operationIdCamelCase}}Oper {{paramName}}MultiPart({{{dataType}}} {{paramName}}) { reqSpec.addMultiPart({{paramName}}); @@ -201,6 +213,8 @@ public class {{classname}} { /** * Customise request specification + * @param consumer consumer + * @return operation */ public {{operationIdCamelCase}}Oper reqSpec(Consumer consumer) { consumer.accept(reqSpec); @@ -209,6 +223,8 @@ public class {{classname}} { /** * Customise response specification + * @param consumer consumer + * @return operation */ public {{operationIdCamelCase}}Oper respSpec(Consumer consumer) { consumer.accept(respSpec); From 210164287806b936d38df60dd0ca8d329386181d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Tue, 24 Apr 2018 07:20:44 +0200 Subject: [PATCH 012/370] Fixes for retrofit (#213) * Add org.threeten as dependency * Mandatory parameter for @retrofit2.http.Field/Part --- libraries/retrofit/build.gradle.mustache | 6 ++++++ libraries/retrofit/build.sbt.mustache | 3 +++ libraries/retrofit/pom.mustache | 10 ++++++++++ libraries/retrofit2/formParams.mustache | 2 +- 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/libraries/retrofit/build.gradle.mustache b/libraries/retrofit/build.gradle.mustache index 60dec7e1260..6befe74db7c 100644 --- a/libraries/retrofit/build.gradle.mustache +++ b/libraries/retrofit/build.gradle.mustache @@ -106,6 +106,9 @@ ext { swagger_annotations_version = "1.5.8" junit_version = "4.12" jodatime_version = "2.9.3" + {{#threetenbp}} + threetenbp_version = "1.3.5" + {{/threetenbp}} } dependencies { @@ -114,5 +117,8 @@ dependencies { compile "io.swagger:swagger-annotations:$swagger_annotations_version" compile "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version" compile "joda-time:joda-time:$jodatime_version" + {{#threetenbp}} + compile "org.threeten:threetenbp:$threetenbp_version" + {{/threetenbp}} testCompile "junit:junit:$junit_version" } diff --git a/libraries/retrofit/build.sbt.mustache b/libraries/retrofit/build.sbt.mustache index 56f6cee13ab..ffa308d528a 100644 --- a/libraries/retrofit/build.sbt.mustache +++ b/libraries/retrofit/build.sbt.mustache @@ -14,6 +14,9 @@ lazy val root = (project in file(".")). "io.swagger" % "swagger-annotations" % "1.5.8" % "compile", "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", "joda-time" % "joda-time" % "2.9.3" % "compile", + {{#threetenbp}} + "org.threeten" % "threetenbp" % "1.3.5" % "compile", + {{/threetenbp}} "junit" % "junit" % "4.12" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) diff --git a/libraries/retrofit/pom.mustache b/libraries/retrofit/pom.mustache index b4ceff3aac0..0921ab21ac4 100644 --- a/libraries/retrofit/pom.mustache +++ b/libraries/retrofit/pom.mustache @@ -222,6 +222,13 @@ joda-time ${jodatime-version} + {{#threetenbp}} + + org.threeten + threetenbp + ${threetenbp-version} + + {{/threetenbp}} {{#parcelableModel}} @@ -247,6 +254,9 @@ 1.9.0 2.7.5 2.9.9 + {{#threetenbp}} + 1.3.5 + {{/threetenbp}} 1.0.1 1.0.0 4.12 diff --git a/libraries/retrofit2/formParams.mustache b/libraries/retrofit2/formParams.mustache index f85b028870c..af65a37bc36 100644 --- a/libraries/retrofit2/formParams.mustache +++ b/libraries/retrofit2/formParams.mustache @@ -1 +1 @@ -{{#isFormParam}}{{^isFile}}{{#isMultipart}}@retrofit2.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit2.http.Field{{/isMultipart}}("{{baseName}}") {{{dataType}}} {{paramName}}{{/isFile}}{{#isFile}}{{#isMultipart}}@retrofit2.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit2.http.Field{{/isMultipart}} MultipartBody.Part {{paramName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file +{{#isFormParam}}{{^isFile}}{{#isMultipart}}@retrofit2.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit2.http.Field{{/isMultipart}}("{{baseName}}") {{{dataType}}} {{paramName}}{{/isFile}}{{#isFile}}{{#isMultipart}}@retrofit2.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit2.http.Field{{/isMultipart}}("{{baseName}}") MultipartBody.Part {{paramName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file From b762c5e287e141c1c5e68bc73c292b18e36ac775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Tue, 24 Apr 2018 09:51:50 +0200 Subject: [PATCH 013/370] Update java client samples OAS2 (#140) * Update java client examples * Rename artifactId in json config files * Add imports in api.mustache for play24 and play25 --- libraries/retrofit2/play24/api.mustache | 2 ++ libraries/retrofit2/play25/api.mustache | 2 ++ 2 files changed, 4 insertions(+) diff --git a/libraries/retrofit2/play24/api.mustache b/libraries/retrofit2/play24/api.mustache index 6538ed53d2f..9d43d64d78a 100644 --- a/libraries/retrofit2/play24/api.mustache +++ b/libraries/retrofit2/play24/api.mustache @@ -8,6 +8,8 @@ import {{invokerPackage}}.CollectionFormats.*; import retrofit2.http.*; import okhttp3.RequestBody; +import okhttp3.ResponseBody; +import okhttp3.MultipartBody; {{#imports}}import {{import}}; {{/imports}} diff --git a/libraries/retrofit2/play25/api.mustache b/libraries/retrofit2/play25/api.mustache index 51b1812b49e..32de090e435 100644 --- a/libraries/retrofit2/play25/api.mustache +++ b/libraries/retrofit2/play25/api.mustache @@ -8,6 +8,8 @@ import {{invokerPackage}}.CollectionFormats.*; import retrofit2.http.*; import okhttp3.RequestBody; +import okhttp3.ResponseBody; +import okhttp3.MultipartBody; {{#imports}}import {{import}}; {{/imports}} From d4ab554610ea8a89801f292362e64701d5b207fd Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 2 May 2018 01:12:32 +0800 Subject: [PATCH 014/370] update default user agent (#284) --- ApiClient.mustache | 2 +- libraries/jersey2/ApiClient.mustache | 2 +- libraries/okhttp-gson/ApiClient.mustache | 2 +- libraries/resteasy/ApiClient.mustache | 2 +- libraries/vertx/ApiClient.mustache | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ApiClient.mustache b/ApiClient.mustache index f99ea1dade7..544d05e3c74 100644 --- a/ApiClient.mustache +++ b/ApiClient.mustache @@ -97,7 +97,7 @@ public class ApiClient { dateFormat = ApiClient.buildDefaultDateFormat(); // Set default User-Agent. - setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}Swagger-Codegen/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); // Setup authentications (key: authentication name, value: authentication). authentications = new HashMap();{{#authMethods}}{{#isBasic}} diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index a699e001f17..e70b34ad0dc 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -79,7 +79,7 @@ public class ApiClient { this.dateFormat = new RFC3339DateFormat(); // Set default User-Agent. - setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}Swagger-Codegen/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); // Setup authentications (key: authentication name, value: authentication). authentications = new HashMap();{{#authMethods}}{{#isBasic}} diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index 0ae00335726..0c7bbed5315 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -90,7 +90,7 @@ public class ApiClient { json = new JSON(); // Set default User-Agent. - setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}Swagger-Codegen/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); // Setup authentications (key: authentication name, value: authentication). authentications = new HashMap();{{#authMethods}}{{#isBasic}} diff --git a/libraries/resteasy/ApiClient.mustache b/libraries/resteasy/ApiClient.mustache index a8b3ca6f5b8..7144ed07221 100644 --- a/libraries/resteasy/ApiClient.mustache +++ b/libraries/resteasy/ApiClient.mustache @@ -72,7 +72,7 @@ public class ApiClient { this.json.setDateFormat((DateFormat) dateFormat.clone()); // Set default User-Agent. - setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}Swagger-Codegen/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); // Setup authentications (key: authentication name, value: authentication). authentications = new HashMap();{{#authMethods}}{{#isBasic}} diff --git a/libraries/vertx/ApiClient.mustache b/libraries/vertx/ApiClient.mustache index 1de56ec9ca9..fb80f0d2dba 100644 --- a/libraries/vertx/ApiClient.mustache +++ b/libraries/vertx/ApiClient.mustache @@ -578,7 +578,7 @@ public class ApiClient { protected WebClient buildWebClient(Vertx vertx, JsonObject config) { if (!config.containsKey("userAgent")) { - config.put("userAgent", "{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}Swagger-Codegen/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + config.put("userAgent", "{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); } return WebClient.create(vertx, new WebClientOptions(config)); From aec7efb3940f90338681223f26c5ac68e828b077 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Thu, 3 May 2018 20:12:24 +0800 Subject: [PATCH 015/370] Update wordings (#301) * update wordings * update git_push wordings * update git clone * update homepage url * update meta-codegen sample --- README.mustache | 2 +- git_push.sh.mustache | 2 +- libraries/feign/EncodingUtils.mustache | 2 +- libraries/resteasy/pom.mustache | 6 +++--- licenseInfo.mustache | 4 ++-- travis.mustache | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.mustache b/README.mustache index 6ec3efff471..888992bc914 100644 --- a/README.mustache +++ b/README.mustache @@ -12,7 +12,7 @@ For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) {{/infoUrl}} -*Automatically generated by the [Swagger Codegen](https://github.com/swagger-api/swagger-codegen)* +*Automatically generated by the [OpenAPI Generator](https://openapi-generator.tech)* ## Requirements diff --git a/git_push.sh.mustache b/git_push.sh.mustache index a2d75234837..8a32e53995d 100755 --- a/git_push.sh.mustache +++ b/git_push.sh.mustache @@ -1,7 +1,7 @@ #!/bin/sh # ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ # -# Usage example: /bin/sh ./git_push.sh wing328 swagger-petstore-perl "minor update" +# Usage example: /bin/sh ./git_push.sh wing328 openapi-pestore-perl "minor update" git_user_id=$1 git_repo_id=$2 diff --git a/libraries/feign/EncodingUtils.mustache b/libraries/feign/EncodingUtils.mustache index 6f43e1c3c2a..6bf2a0e4bfb 100644 --- a/libraries/feign/EncodingUtils.mustache +++ b/libraries/feign/EncodingUtils.mustache @@ -31,7 +31,7 @@ public final class EncodingUtils { * @param collectionFormat The Swagger collection format (eg, "csv", "tsv", * "pipes"). See the * - * Swagger Spec for more details. + * OpenAPI Spec for more details. * @return An object that will be correctly formatted by Feign. */ public static Object encodeCollection(Collection parameters, diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index 456bee18137..26d2431919a 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -7,9 +7,9 @@ {{artifactId}} {{artifactVersion}} - scm:git:git@github.com:swagger-api/swagger-mustache.git - scm:git:git@github.com:swagger-api/swagger-codegen.git - https://github.com/swagger-api/swagger-codegen + scm:git:git@github.com:openapitools/openapi-generator.git + scm:git:git@github.com:openapitools/openapi-generator.git + https://openapi-generator.tech diff --git a/licenseInfo.mustache b/licenseInfo.mustache index 94c36dda3af..335db1c5938 100644 --- a/licenseInfo.mustache +++ b/licenseInfo.mustache @@ -5,7 +5,7 @@ * {{#version}}OpenAPI spec version: {{{version}}}{{/version}} * {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}} * - * NOTE: This class is auto generated by the swagger code generator program. - * https://github.com/swagger-api/swagger-codegen.git + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech * Do not edit the class manually. */ diff --git a/travis.mustache b/travis.mustache index 70cb81a67c2..80a7f2fc66c 100644 --- a/travis.mustache +++ b/travis.mustache @@ -1,5 +1,5 @@ # -# Generated by: https://github.com/swagger-api/swagger-codegen.git +# Generated by: https://openapi-generator.tech # language: java jdk: From 747614745d6872c4deacb56a73d312b89650ecb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Fri, 11 May 2018 14:35:56 +0200 Subject: [PATCH 016/370] Merge 'master' branch of 'swagger-codegen' into 'master' (#422) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Corresponding commit swagger-codegen: cccd0930368dd4c54d04bdfcaa3496685c3ed9b8 Co-authored-by: Andreas Müller Co-authored-by: Geoff Brown Co-authored-by: Raphael Ochsenbein --- build.gradle.mustache | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/build.gradle.mustache b/build.gradle.mustache index af0d3d55d85..575811da812 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -18,7 +18,6 @@ repositories { jcenter() } - if(hasProperty('target') && target == 'android') { apply plugin: 'com.android.library' @@ -103,6 +102,21 @@ if(hasProperty('target') && target == 'android') { main = System.getProperty('mainClass') classpath = sourceSets.main.runtimeClasspath } + + task sourcesJar(type: Jar, dependsOn: classes) { + classifier = 'sources' + from sourceSets.main.allSource + } + + task javadocJar(type: Jar, dependsOn: javadoc) { + classifier = 'javadoc' + from javadoc.destinationDir + } + + artifacts { + archives sourcesJar + archives javadocJar + } } ext { @@ -135,3 +149,4 @@ dependencies { {{/java8}} testCompile "junit:junit:$junit_version" } + From 2aae9d747c55cdb8fc1ed54f862b796e9932772e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Sun, 13 May 2018 13:58:46 +0200 Subject: [PATCH 017/370] Java gson: add @SerializedName value as constant (#22) * Java gson: add @SerializedName value as constant Fix #21 * Run bin/java-petstore-all.sh --- pojo.mustache | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pojo.mustache b/pojo.mustache index 3224cb256dd..52dccb3c095 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -57,7 +57,8 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela {{/isXmlAttribute}} {{/withXml}} {{#gson}} - @SerializedName("{{baseName}}") + public static final String SERIALIZED_NAME_{{nameInCamelCase}} = "{{baseName}}"; + @SerializedName(SERIALIZED_NAME_{{nameInCamelCase}}) {{/gson}} {{#isContainer}} private {{{datatypeWithEnum}}} {{name}}{{#required}} = {{{defaultValue}}}{{/required}}{{^required}} = null{{/required}}; From 952fe1d3500a9ed3b28f8d65ef2c0fdfac85d522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Tue, 15 May 2018 13:17:04 +0200 Subject: [PATCH 018/370] Add CodegenProperty.nameInSnakeCase (#42) --- pojo.mustache | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pojo.mustache b/pojo.mustache index 52dccb3c095..3329e8f98b7 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -57,8 +57,8 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela {{/isXmlAttribute}} {{/withXml}} {{#gson}} - public static final String SERIALIZED_NAME_{{nameInCamelCase}} = "{{baseName}}"; - @SerializedName(SERIALIZED_NAME_{{nameInCamelCase}}) + public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}"; + @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}}) {{/gson}} {{#isContainer}} private {{{datatypeWithEnum}}} {{name}}{{#required}} = {{{defaultValue}}}{{/required}}{{^required}} = null{{/required}}; From 7d24c3c3e3e91bd6f4d4f402ccbefc620182d815 Mon Sep 17 00:00:00 2001 From: Victor Orlovsky Date: Fri, 18 May 2018 13:49:34 +0300 Subject: [PATCH 019/370] CaseFormatLambda has been added, params for Rest-assured client has been refactored (#91) --- libraries/rest-assured/api.mustache | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/libraries/rest-assured/api.mustache b/libraries/rest-assured/api.mustache index 8d90f195764..cd481e61af9 100644 --- a/libraries/rest-assured/api.mustache +++ b/libraries/rest-assured/api.mustache @@ -151,46 +151,54 @@ public class {{classname}} { {{/bodyParams}} {{#headerParams}} + public static final String {{#convert}}{{paramName}}{{/convert}}_HEADER = "{{baseName}}"; + /** * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} * @return operation */ public {{operationIdCamelCase}}Oper {{paramName}}Header(String {{paramName}}) { - reqSpec.addHeader("{{baseName}}", {{paramName}}); + reqSpec.addHeader({{#convert}}{{paramName}}{{/convert}}_HEADER, {{paramName}}); return this; } {{/headerParams}} {{#pathParams}} + public static final String {{#convert}}{{paramName}}{{/convert}}_PATH = "{{baseName}}"; + /** * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} * @return operation */ public {{operationIdCamelCase}}Oper {{paramName}}Path(Object {{paramName}}) { - reqSpec.addPathParam("{{baseName}}", {{paramName}}); + reqSpec.addPathParam({{#convert}}{{paramName}}{{/convert}}_PATH, {{paramName}}); return this; } {{/pathParams}} {{#queryParams}} + public static final String {{#convert}}{{paramName}}{{/convert}}_QUERY = "{{baseName}}"; + /** * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} * @return operation */ public {{operationIdCamelCase}}Oper {{paramName}}Query(Object... {{paramName}}) { - reqSpec.addQueryParam("{{baseName}}", {{paramName}}); + reqSpec.addQueryParam({{#convert}}{{paramName}}{{/convert}}_QUERY, {{paramName}}); return this; } {{/queryParams}} {{#formParams}} {{^isFile}} + public static final String {{#convert}}{{paramName}}{{/convert}}_FORM = "{{baseName}}"; + /** * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} * @return operation */ public {{operationIdCamelCase}}Oper {{paramName}}Form(Object... {{paramName}}) { - reqSpec.addFormParam("{{baseName}}", {{paramName}}); + reqSpec.addFormParam({{#convert}}{{paramName}}{{/convert}}_FORM, {{paramName}}); return this; } {{/isFile}} From 1083dfbfc940ca5522f99a725710225edb4f69a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Fri, 18 May 2018 18:06:37 +0200 Subject: [PATCH 020/370] Rename datatype to dataType in CodegenProperty (#69) --- modelInnerEnum.mustache | 8 ++++---- pojo.mustache | 2 +- pojo_doc.mustache | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modelInnerEnum.mustache b/modelInnerEnum.mustache index e7ffa65d130..bcd6908950a 100644 --- a/modelInnerEnum.mustache +++ b/modelInnerEnum.mustache @@ -12,16 +12,16 @@ {{/enumVars}} {{/allowableValues}} - private {{{datatype}}} value; + private {{{dataType}}} value; - {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}({{{datatype}}} value) { + {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}({{{dataType}}} value) { this.value = value; } {{#jackson}} @JsonValue {{/jackson}} - public {{{datatype}}} getValue() { + public {{{dataType}}} getValue() { return value; } @@ -51,7 +51,7 @@ @Override public {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException { - {{{datatype}}} value = jsonReader.{{#isInteger}}nextInt(){{/isInteger}}{{^isInteger}}next{{{datatype}}}(){{/isInteger}}; + {{{dataType}}} value = jsonReader.{{#isInteger}}nextInt(){{/isInteger}}{{^isInteger}}next{{{dataType}}}(){{/isInteger}}; return {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue(String.valueOf(value)); } } diff --git a/pojo.mustache b/pojo.mustache index 3329e8f98b7..93e02e86633 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -47,7 +47,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela // Is a container wrapped={{isXmlWrapped}} {{#items}} // items.name={{name}} items.baseName={{baseName}} items.xmlName={{xmlName}} items.xmlNamespace={{xmlNamespace}} - // items.example={{example}} items.type={{datatype}} + // items.example={{example}} items.type={{dataType}} @XmlElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") {{/items}} {{#isXmlWrapped}} diff --git a/pojo_doc.mustache b/pojo_doc.mustache index 0e4c0749866..07b73cc6f5f 100644 --- a/pojo_doc.mustache +++ b/pojo_doc.mustache @@ -3,7 +3,7 @@ ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -{{#vars}}**{{name}}** | {{#isEnum}}[**{{datatypeWithEnum}}**](#{{datatypeWithEnum}}){{/isEnum}}{{^isEnum}}{{#isPrimitiveType}}**{{datatype}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{datatype}}**]({{complexType}}.md){{/isPrimitiveType}}{{/isEnum}} | {{description}} | {{^required}} [optional]{{/required}}{{#readOnly}} [readonly]{{/readOnly}} +{{#vars}}**{{name}}** | {{#isEnum}}[**{{datatypeWithEnum}}**](#{{datatypeWithEnum}}){{/isEnum}}{{^isEnum}}{{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}}{{/isEnum}} | {{description}} | {{^required}} [optional]{{/required}}{{#readOnly}} [readonly]{{/readOnly}} {{/vars}} {{#vars}}{{#isEnum}} From ad984f0bb97b92df9db7dbe8b5eeff6d0ab4ea3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Fri, 18 May 2018 19:01:11 +0200 Subject: [PATCH 021/370] [java] Enum in array of array (#66) --- pojo.mustache | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/pojo.mustache b/pojo.mustache index 93e02e86633..21c21b1ddd3 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -13,14 +13,12 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela {{^isContainer}} {{>modelInnerEnum}} {{/isContainer}} - {{/isEnum}} - {{#items.isEnum}} - {{#items}} - {{^isContainer}} + {{#isContainer}} + {{#mostInnerItems}} {{>modelInnerEnum}} - {{/isContainer}} - {{/items}} - {{/items.isEnum}} + {{/mostInnerItems}} + {{/isContainer}} + {{/isEnum}} {{#jackson}} @JsonProperty("{{baseName}}") {{#withXml}} From fbf6bfc3a08840451fbc71a56d13609c44bba5f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Sun, 20 May 2018 08:55:56 +0200 Subject: [PATCH 022/370] [Java] use html entities in javadoc of generated code (#106) --- api.mustache | 2 +- libraries/feign/api.mustache | 6 +++--- libraries/jersey2/api.mustache | 4 ++-- libraries/okhttp-gson/api.mustache | 8 ++++---- libraries/rest-assured/api.mustache | 14 +++++++------- libraries/resteasy/api.mustache | 2 +- libraries/retrofit/api.mustache | 4 ++-- libraries/retrofit2/api.mustache | 2 +- libraries/retrofit2/play24/api.mustache | 2 +- libraries/retrofit2/play25/api.mustache | 2 +- libraries/vertx/apiImpl.mustache | 2 +- libraries/vertx/rxApiImpl.mustache | 4 ++-- 12 files changed, 26 insertions(+), 26 deletions(-) diff --git a/api.mustache b/api.mustache index 542ccbba287..17f8d56ac6e 100644 --- a/api.mustache +++ b/api.mustache @@ -46,7 +46,7 @@ public class {{classname}} { * {{summary}} * {{notes}} {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} {{#returnType}} * @return {{returnType}} diff --git a/libraries/feign/api.mustache b/libraries/feign/api.mustache index 03eb7dd40cb..dea8a6e8aef 100644 --- a/libraries/feign/api.mustache +++ b/libraries/feign/api.mustache @@ -25,7 +25,7 @@ public interface {{classname}} extends ApiClient.Api { * {{summary}} * {{notes}} {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} {{#returnType}} * @return {{returnType}} @@ -55,14 +55,14 @@ public interface {{classname}} extends ApiClient.Api { * building up this map in a fluent style. {{#allParams}} {{^isQueryParam}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/isQueryParam}} {{/allParams}} * @param queryParams Map of query parameters as name-value pairs *

The following elements may be specified in the query map:

*
    {{#queryParams}} - *
  • {{paramName}} - {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}
  • + *
  • {{paramName}} - {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}
  • {{/queryParams}} *
{{#returnType}} diff --git a/libraries/jersey2/api.mustache b/libraries/jersey2/api.mustache index fed034609c8..ad7d43d6113 100644 --- a/libraries/jersey2/api.mustache +++ b/libraries/jersey2/api.mustache @@ -44,7 +44,7 @@ public class {{classname}} { * {{summary}} * {{notes}} {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} {{#returnType}} * @return {{returnType}} @@ -73,7 +73,7 @@ public class {{classname}} { * {{summary}} * {{notes}} {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} {{#returnType}} * @return ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> diff --git a/libraries/okhttp-gson/api.mustache b/libraries/okhttp-gson/api.mustache index ffc68bc7b5a..0ef776280fd 100644 --- a/libraries/okhttp-gson/api.mustache +++ b/libraries/okhttp-gson/api.mustache @@ -65,7 +65,7 @@ public class {{classname}} { {{#operation}} /** * Build call for {{operationId}}{{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}{{/allParams}} * @param progressListener Progress listener * @param progressRequestListener Progress request listener * @return Call to execute @@ -177,7 +177,7 @@ public class {{classname}} { /** * {{summary}} * {{notes}}{{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}}{{#returnType}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}{{/allParams}}{{#returnType}} * @return {{returnType}}{{/returnType}} * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body {{#isDeprecated}} @@ -199,7 +199,7 @@ public class {{classname}} { /** * {{summary}} * {{notes}}{{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}{{/allParams}} * @return ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body {{#isDeprecated}} @@ -222,7 +222,7 @@ public class {{classname}} { /** * {{summary}} (asynchronously) * {{notes}}{{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}{{/allParams}} * @param callback The callback to be executed when the API call finishes * @return The request call * @throws ApiException If fail to process the API call, e.g. serializing the request body object diff --git a/libraries/rest-assured/api.mustache b/libraries/rest-assured/api.mustache index cd481e61af9..0263f6cf323 100644 --- a/libraries/rest-assured/api.mustache +++ b/libraries/rest-assured/api.mustache @@ -67,7 +67,7 @@ public class {{classname}} { * {{notes}} * {{#allParams}} - * @see #{{#isPathParam}}{{paramName}}Path{{/isPathParam}}{{#isQueryParam}}{{paramName}}Query{{/isQueryParam}}{{#isFormParam}}{{^isFile}}{{paramName}}Form{{/isFile}}{{#isFile}}{{paramName}}MultiPart{{/isFile}}{{/isFormParam}}{{#isHeaderParam}}{{paramName}}Header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @see #{{#isPathParam}}{{paramName}}Path{{/isPathParam}}{{#isQueryParam}}{{paramName}}Query{{/isQueryParam}}{{#isFormParam}}{{^isFile}}{{paramName}}Form{{/isFile}}{{#isFile}}{{paramName}}MultiPart{{/isFile}}{{/isFormParam}}{{#isHeaderParam}}{{paramName}}Header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} {{#returnType}} * return {{returnType}} @@ -141,7 +141,7 @@ public class {{classname}} { {{#bodyParams}} /** - * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} * @return operation */ public {{operationIdCamelCase}}Oper body({{{dataType}}} {{paramName}}) { @@ -154,7 +154,7 @@ public class {{classname}} { public static final String {{#convert}}{{paramName}}{{/convert}}_HEADER = "{{baseName}}"; /** - * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} * @return operation */ public {{operationIdCamelCase}}Oper {{paramName}}Header(String {{paramName}}) { @@ -167,7 +167,7 @@ public class {{classname}} { public static final String {{#convert}}{{paramName}}{{/convert}}_PATH = "{{baseName}}"; /** - * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} * @return operation */ public {{operationIdCamelCase}}Oper {{paramName}}Path(Object {{paramName}}) { @@ -180,7 +180,7 @@ public class {{classname}} { public static final String {{#convert}}{{paramName}}{{/convert}}_QUERY = "{{baseName}}"; /** - * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} * @return operation */ public {{operationIdCamelCase}}Oper {{paramName}}Query(Object... {{paramName}}) { @@ -194,7 +194,7 @@ public class {{classname}} { public static final String {{#convert}}{{paramName}}{{/convert}}_FORM = "{{baseName}}"; /** - * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} * @return operation */ public {{operationIdCamelCase}}Oper {{paramName}}Form(Object... {{paramName}}) { @@ -209,7 +209,7 @@ public class {{classname}} { /** * It will assume that the control name is file and the <content-type> is <application/octet-stream> * @see #reqSpec for customise - * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} * @return operation */ public {{operationIdCamelCase}}Oper {{paramName}}MultiPart({{{dataType}}} {{paramName}}) { diff --git a/libraries/resteasy/api.mustache b/libraries/resteasy/api.mustache index f3fd01ed61b..9e6fa4e1364 100644 --- a/libraries/resteasy/api.mustache +++ b/libraries/resteasy/api.mustache @@ -42,7 +42,7 @@ public class {{classname}} { /** * {{summary}} * {{notes}}{{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}}{{#returnType}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}{{/allParams}}{{#returnType}} * @return {{{returnType}}}{{/returnType}} * @throws ApiException if fails to make API call {{#isDeprecated}} diff --git a/libraries/retrofit/api.mustache b/libraries/retrofit/api.mustache index 46df0ecedf3..9effc056056 100644 --- a/libraries/retrofit/api.mustache +++ b/libraries/retrofit/api.mustache @@ -24,7 +24,7 @@ public interface {{classname}} { * Sync method * {{notes}} {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} * @return {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}} {{#externalDocs}} @@ -43,7 +43,7 @@ public interface {{classname}} { * {{summary}} * Async method {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} * @param cb callback method {{#externalDocs}} diff --git a/libraries/retrofit2/api.mustache b/libraries/retrofit2/api.mustache index f6eb4c2dd07..44f33a514f8 100644 --- a/libraries/retrofit2/api.mustache +++ b/libraries/retrofit2/api.mustache @@ -39,7 +39,7 @@ public interface {{classname}} { * {{summary}} * {{notes}} {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} * @return {{^doNotUseRx}}{{#useRxJava}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/useRxJava}}{{#useRxJava2}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{returnType}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{/doNotUseRx}}{{#doNotUseRx}}Call<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/doNotUseRx}} {{#isDeprecated}} diff --git a/libraries/retrofit2/play24/api.mustache b/libraries/retrofit2/play24/api.mustache index 9d43d64d78a..dd6bf23e947 100644 --- a/libraries/retrofit2/play24/api.mustache +++ b/libraries/retrofit2/play24/api.mustache @@ -31,7 +31,7 @@ public interface {{classname}} { * {{summary}} * {{notes}} {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} * @return Call<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> */ diff --git a/libraries/retrofit2/play25/api.mustache b/libraries/retrofit2/play25/api.mustache index 32de090e435..b435a16c051 100644 --- a/libraries/retrofit2/play25/api.mustache +++ b/libraries/retrofit2/play25/api.mustache @@ -31,7 +31,7 @@ public interface {{classname}} { * {{summary}} * {{notes}} {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} * @return Call<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> */ diff --git a/libraries/vertx/apiImpl.mustache b/libraries/vertx/apiImpl.mustache index f4b5a723922..37893a8888f 100644 --- a/libraries/vertx/apiImpl.mustache +++ b/libraries/vertx/apiImpl.mustache @@ -44,7 +44,7 @@ public class {{classname}}Impl implements {{classname}} { * {{summary}} * {{notes}} {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} * @param resultHandler Asynchronous result handler */ diff --git a/libraries/vertx/rxApiImpl.mustache b/libraries/vertx/rxApiImpl.mustache index 09ca96895d6..be144ff3eaa 100644 --- a/libraries/vertx/rxApiImpl.mustache +++ b/libraries/vertx/rxApiImpl.mustache @@ -28,7 +28,7 @@ public class {{classname}} { * {{summary}} * {{notes}} {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} * @param resultHandler Asynchronous result handler */ @@ -40,7 +40,7 @@ public class {{classname}} { * {{summary}} * {{notes}} {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} * @return Asynchronous result handler (RxJava Single) */ From d915d9c8136b0f12ab2531a14afbbd63226e9a6b Mon Sep 17 00:00:00 2001 From: delenius Date: Fri, 25 May 2018 21:34:38 -0700 Subject: [PATCH 023/370] JavaDoc fixes for Java/RESTEasy client (#151) --- libraries/resteasy/ApiClient.mustache | 42 ++++++++++++++++++++++++++- libraries/resteasy/JSON.mustache | 1 + libraries/resteasy/api.mustache | 2 +- libraries/resteasy/pom.mustache | 8 +++++ 4 files changed, 51 insertions(+), 2 deletions(-) diff --git a/libraries/resteasy/ApiClient.mustache b/libraries/resteasy/ApiClient.mustache index 7144ed07221..f447d645807 100644 --- a/libraries/resteasy/ApiClient.mustache +++ b/libraries/resteasy/ApiClient.mustache @@ -85,6 +85,7 @@ public class ApiClient { /** * Gets the JSON instance to do JSON serialization and deserialization. + * @return the JSON utility class */ public JSON getJSON() { return json; @@ -110,6 +111,7 @@ public class ApiClient { /** * Gets the status code of the previous request + * @return the status code of the previous request */ public int getStatusCode() { return statusCode; @@ -117,6 +119,7 @@ public class ApiClient { /** * Gets the response headers of the previous request + * @return the response headers of the previous request */ public Map> getResponseHeaders() { return responseHeaders; @@ -124,6 +127,7 @@ public class ApiClient { /** * Get authentications (key: authentication name, value: authentication). + * @return the authentications */ public Map getAuthentications() { return authentications; @@ -141,6 +145,7 @@ public class ApiClient { /** * Helper method to set username for the first HTTP basic authentication. + * @param username the username */ public void setUsername(String username) { for (Authentication auth : authentications.values()) { @@ -154,6 +159,7 @@ public class ApiClient { /** * Helper method to set password for the first HTTP basic authentication. + * @param password the password */ public void setPassword(String password) { for (Authentication auth : authentications.values()) { @@ -167,6 +173,7 @@ public class ApiClient { /** * Helper method to set API key value for the first API key authentication. + * @param apiKey the API key */ public void setApiKey(String apiKey) { for (Authentication auth : authentications.values()) { @@ -180,6 +187,7 @@ public class ApiClient { /** * Helper method to set API key prefix for the first API key authentication. + * @param apiKeyPrefix the API key prefix */ public void setApiKeyPrefix(String apiKeyPrefix) { for (Authentication auth : authentications.values()) { @@ -193,6 +201,7 @@ public class ApiClient { /** * Helper method to set access token for the first OAuth2 authentication. + * @param accessToken the access token */ public void setAccessToken(String accessToken) { for (Authentication auth : authentications.values()) { @@ -206,6 +215,8 @@ public class ApiClient { /** * Set the User-Agent header's value (by adding to the default header map). + * @param userAgent the User-Agent header value + * @return this {@code ApiClient} */ public ApiClient setUserAgent(String userAgent) { addDefaultHeader("User-Agent", userAgent); @@ -217,6 +228,7 @@ public class ApiClient { * * @param key The header's key * @param value The header's value + * @return this {@code ApiClient} */ public ApiClient addDefaultHeader(String key, String value) { defaultHeaderMap.put(key, value); @@ -225,6 +237,7 @@ public class ApiClient { /** * Check that whether debugging is enabled for this API client. + * @return {@code true} if debugging is enabled for this API client */ public boolean isDebugging() { return debugging; @@ -234,6 +247,7 @@ public class ApiClient { * Enable/disable debugging for this API client. * * @param debugging To enable (true) or disable (false) debugging + * @return this {@code ApiClient} */ public ApiClient setDebugging(boolean debugging) { this.debugging = debugging; @@ -247,7 +261,8 @@ public class ApiClient { * with file response. The default value is null, i.e. using * the system's default tempopary folder. * - * @see https://docs.oracle.com/javase/7/docs/api/java/io/File.html#createTempFile(java.lang.String,%20java.lang.String,%20java.io.File) + * @return the temporary folder path + * @see */ public String getTempFolderPath() { return tempFolderPath; @@ -260,6 +275,7 @@ public class ApiClient { /** * Get the date format used to parse/format date parameters. + * @return the date format used to parse/format date parameters */ public DateFormat getDateFormat() { return dateFormat; @@ -267,6 +283,8 @@ public class ApiClient { /** * Set the date format used to parse/format date parameters. + * @param dateFormat a date format used to parse/format date parameters + * @return this {@code ApiClient} */ public ApiClient setDateFormat(DateFormat dateFormat) { this.dateFormat = dateFormat; @@ -277,6 +295,8 @@ public class ApiClient { /** * Parse the given string into Date object. + * @param str a string to parse + * @return a {@code Date} object */ public Date parseDate(String str) { try { @@ -288,6 +308,8 @@ public class ApiClient { /** * Format the given Date object into string. + * @param date a {@code Date} object to format + * @return the {@code String} version of the {@code Date} object */ public String formatDate(Date date) { return dateFormat.format(date); @@ -295,6 +317,8 @@ public class ApiClient { /** * Format the given parameter object into string. + * @param param an object to format + * @return the {@code String} version of the object */ public String parameterToString(Object param) { if (param == null) { @@ -430,6 +454,8 @@ public class ApiClient { /** * Escape the given string to be used as URL query value. + * @param str a {@code String} to escape + * @return the escaped version of the {@code String} */ public String escapeString(String str) { try { @@ -442,6 +468,11 @@ public class ApiClient { /** * Serialize the given Java object into string entity according the given * Content-Type (only JSON is supported for now). + * @param obj the object to serialize + * @param formParams the form parameters + * @param contentType the content type + * @return an {@code Entity} + * @throws ApiException on failure to serialize */ public Entity serialize(Object obj, Map formParams, String contentType) throws ApiException { Entity entity = null; @@ -476,6 +507,11 @@ public class ApiClient { /** * Deserialize response body to Java object according to the Content-Type. + * @param a Java type parameter + * @param response the response body to deserialize + * @param returnType a Java type to deserialize into + * @return a deserialized Java object + * @throws ApiException on failure to deserialize */ public T deserialize(Response response, GenericType returnType) throws ApiException { if (response == null || returnType == null) { @@ -504,6 +540,8 @@ public class ApiClient { /** * Download file from the given response. + * @param response a response + * @return a file from the given response * @throws ApiException If fail to read file content from response and write to disk */ public File downloadFileFromResponse(Response response) throws ApiException { @@ -560,6 +598,7 @@ public class ApiClient { /** * Invoke API by sending HTTP request with the given options. * + * @param a Java type parameter * @param path The sub-path of the HTTP URL * @param method The request method, one of "GET", "POST", "PUT", "HEAD" and "DELETE" * @param queryParams The query parameters @@ -571,6 +610,7 @@ public class ApiClient { * @param authNames The authentications to apply * @param returnType The return type into which to deserialize the response * @return The response body in type of string + * @throws ApiException if the invocation failed */ public T invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { updateParamsForAuth(authNames, queryParams, headerParams); diff --git a/libraries/resteasy/JSON.mustache b/libraries/resteasy/JSON.mustache index 27d2aa65d23..6f5829fa509 100644 --- a/libraries/resteasy/JSON.mustache +++ b/libraries/resteasy/JSON.mustache @@ -36,6 +36,7 @@ public class JSON implements ContextResolver { /** * Set the date format for JSON (de)serialization with Date properties. + * @param dateFormat the date format to set */ public void setDateFormat(DateFormat dateFormat) { mapper.setDateFormat(dateFormat); diff --git a/libraries/resteasy/api.mustache b/libraries/resteasy/api.mustache index 9e6fa4e1364..5a80dcca14b 100644 --- a/libraries/resteasy/api.mustache +++ b/libraries/resteasy/api.mustache @@ -43,7 +43,7 @@ public class {{classname}} { * {{summary}} * {{notes}}{{#allParams}} * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}{{/allParams}}{{#returnType}} - * @return {{{returnType}}}{{/returnType}} + * @return a {@code {{{returnType}}}}{{/returnType}} * @throws ApiException if fails to make API call {{#isDeprecated}} * @deprecated diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index 26d2431919a..e6aae545c91 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -134,6 +134,14 @@ org.apache.maven.plugins maven-javadoc-plugin 2.10.4 + + + attach-javadocs + + jar + + +
From 9dbb0a4c2dc418fe27dd2074e0b276e98204fb62 Mon Sep 17 00:00:00 2001 From: Ben Mordue Date: Thu, 7 Jun 2018 05:37:37 +0100 Subject: [PATCH 024/370] [JAVA][Client] New object instead of null for empty POST request (#98) new Object() for empty request body --- libraries/jersey2/api.mustache | 2 +- libraries/okhttp-gson/api.mustache | 2 +- libraries/resteasy/api.mustache | 2 +- libraries/resttemplate/api.mustache | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/jersey2/api.mustache b/libraries/jersey2/api.mustache index ad7d43d6113..985834fe2c1 100644 --- a/libraries/jersey2/api.mustache +++ b/libraries/jersey2/api.mustache @@ -91,7 +91,7 @@ public class {{classname}} { @Deprecated {{/isDeprecated}} public ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { - Object {{localVariablePrefix}}localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + Object {{localVariablePrefix}}localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}new Object(){{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { diff --git a/libraries/okhttp-gson/api.mustache b/libraries/okhttp-gson/api.mustache index 0ef776280fd..5f599b117d8 100644 --- a/libraries/okhttp-gson/api.mustache +++ b/libraries/okhttp-gson/api.mustache @@ -82,7 +82,7 @@ public class {{classname}} { @Deprecated {{/isDeprecated}} public com.squareup.okhttp.Call {{operationId}}Call({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ProgressResponseBody.ProgressListener progressListener, final ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException { - Object {{localVariablePrefix}}localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + Object {{localVariablePrefix}}localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}new Object(){{/bodyParam}}; // create path and map variables String {{localVariablePrefix}}localVarPath = "{{{path}}}"{{#pathParams}} diff --git a/libraries/resteasy/api.mustache b/libraries/resteasy/api.mustache index 5a80dcca14b..a4d0f9f239d 100644 --- a/libraries/resteasy/api.mustache +++ b/libraries/resteasy/api.mustache @@ -57,7 +57,7 @@ public class {{classname}} { @Deprecated {{/isDeprecated}} public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { - Object {{localVariablePrefix}}localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + Object {{localVariablePrefix}}localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}new Object(){{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { diff --git a/libraries/resttemplate/api.mustache b/libraries/resttemplate/api.mustache index f48180f4381..a906a80e7a8 100644 --- a/libraries/resttemplate/api.mustache +++ b/libraries/resttemplate/api.mustache @@ -61,7 +61,7 @@ public class {{classname}} { {{/externalDocs}} */ public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { - Object {{localVariablePrefix}}postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + Object {{localVariablePrefix}}postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}new Object(){{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { From 12ace30dd174008c63b9948c9c50af48193f9dc8 Mon Sep 17 00:00:00 2001 From: SiMing Weng Date: Sun, 10 Jun 2018 05:48:26 -0400 Subject: [PATCH 025/370] [Java][RestTemplate] Fix query parameter URL encoding (#260) * add URL encoding to the query parameters in case they have unsafe characters * add comment * update generated samples --- libraries/resttemplate/ApiClient.mustache | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libraries/resttemplate/ApiClient.mustache b/libraries/resttemplate/ApiClient.mustache index 54f2b14573b..471a936ad57 100644 --- a/libraries/resttemplate/ApiClient.mustache +++ b/libraries/resttemplate/ApiClient.mustache @@ -46,6 +46,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.text.DateFormat; import java.text.ParseException; @@ -527,6 +528,18 @@ public class ApiClient { final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(path); if (queryParams != null) { + //encode the query parameters in case they contain unsafe characters + for (List values : queryParams.values()) { + if (values != null) { + for (int i = 0; i < values.size(); i++) { + try { + values.set(i, URLEncoder.encode(values.get(i), "utf8")); + } catch (UnsupportedEncodingException e) { + + } + } + } + } builder.queryParams(queryParams); } From f18a6a1f96f89695ebe36cba14daa684d6b97e9b Mon Sep 17 00:00:00 2001 From: Stian Liknes Date: Thu, 14 Jun 2018 13:27:52 +0200 Subject: [PATCH 026/370] Configuration option to disable HTML escaping when using Gson (#298) * Configuration option to disable HTML escaping when using Gson The default implementation of Gson will escape certain characters by default. This includes the `=` character, which is used in base64 encoding and cause problems when deserializing the value to a base64 encoded string in a service. Adding an option for disabling this feature makes it easier to generate client code with sane defaults. * Update Petstore sample --- JSON.mustache | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/JSON.mustache b/JSON.mustache index a717df178e3..4ab6cee5cb1 100644 --- a/JSON.mustache +++ b/JSON.mustache @@ -76,7 +76,11 @@ public class JSON { }) {{/parent}} ; - return fireBuilder.createGsonBuilder(); + GsonBuilder builder = fireBuilder.createGsonBuilder(); + {{#disableHtmlEscaping}} + builder.disableHtmlEscaping(); + {{/disableHtmlEscaping}} + return builder; } private static String getDiscriminatorValue(JsonElement readElement, String discriminatorField) { From 4882a2306546144aa052dc1adc499e7a72fbd5fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Sat, 16 Jun 2018 19:49:01 +0300 Subject: [PATCH 027/370] Grammar and spelling fixes (#329) --- libraries/okhttp-gson/ApiClient.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index 0c7bbed5315..5af1e2285f9 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -915,7 +915,7 @@ public class ApiClient { * @param Type * @param response Response * @param returnType Return type - * @throws ApiException If the response has a unsuccessful status code or + * @throws ApiException If the response has an unsuccessful status code or * fail to deserialize the response body * @return Type */ From aa737e7aeba315b4f2eaf02ea86a5dc1119c09fd Mon Sep 17 00:00:00 2001 From: Daonomic Date: Wed, 4 Jul 2018 10:40:57 +0300 Subject: [PATCH 028/370] [Java-client] Add Spring 5 WebClient as new library (#435) --- libraries/webclient/ApiClient.mustache | 640 ++++++++++++++++++ libraries/webclient/api.mustache | 107 +++ libraries/webclient/api_test.mustache | 45 ++ libraries/webclient/auth/ApiKeyAuth.mustache | 60 ++ .../webclient/auth/Authentication.mustache | 13 + .../webclient/auth/HttpBasicAuth.mustache | 39 ++ libraries/webclient/auth/OAuth.mustache | 24 + libraries/webclient/auth/OAuthFlow.mustache | 5 + libraries/webclient/pom.mustache | 135 ++++ 9 files changed, 1068 insertions(+) create mode 100644 libraries/webclient/ApiClient.mustache create mode 100644 libraries/webclient/api.mustache create mode 100644 libraries/webclient/api_test.mustache create mode 100644 libraries/webclient/auth/ApiKeyAuth.mustache create mode 100644 libraries/webclient/auth/Authentication.mustache create mode 100644 libraries/webclient/auth/HttpBasicAuth.mustache create mode 100644 libraries/webclient/auth/OAuth.mustache create mode 100644 libraries/webclient/auth/OAuthFlow.mustache create mode 100644 libraries/webclient/pom.mustache diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache new file mode 100644 index 00000000000..28260368a9b --- /dev/null +++ b/libraries/webclient/ApiClient.mustache @@ -0,0 +1,640 @@ +package {{invokerPackage}}; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpRequest; +import org.springframework.http.HttpStatus; +import org.springframework.http.InvalidMediaTypeException; +import org.springframework.http.MediaType; +import org.springframework.http.RequestEntity; +import org.springframework.http.RequestEntity.BodyBuilder; +import org.springframework.http.ResponseEntity; +import org.springframework.http.client.BufferingClientHttpRequestFactory; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.http.codec.json.Jackson2JsonDecoder; +import org.springframework.http.codec.json.Jackson2JsonEncoder; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.util.StringUtils; +import org.springframework.http.client.reactive.ClientHttpRequest; +import org.springframework.web.client.RestClientException; +import org.springframework.web.util.UriComponentsBuilder; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.ClientResponse; +import org.springframework.web.reactive.function.BodyInserter; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.ExchangeStrategies; +import reactor.core.publisher.Mono; +import reactor.core.publisher.Flux; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.text.DateFormat; +import java.text.ParseException; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TimeZone; + +import {{invokerPackage}}.auth.Authentication; +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.OAuth; + +{{>generatedAnnotation}} +public class ApiClient { + public enum CollectionFormat { + CSV(","), TSV("\t"), SSV(" "), PIPES("|"), MULTI(null); + + private final String separator; + private CollectionFormat(String separator) { + this.separator = separator; + } + + private String collectionToString(Collection collection) { + return StringUtils.collectionToDelimitedString(collection, separator); + } + } + + private HttpHeaders defaultHeaders = new HttpHeaders(); + + private String basePath = "{{basePath}}"; + + private final WebClient webClient; + private final DateFormat dateFormat; + + private Map authentications; + + + public ApiClient() { + this.dateFormat = createDefaultDateFormat(); + this.webClient = buildWebClient(new ObjectMapper(), this.dateFormat); + } + + public ApiClient(ObjectMapper mapper, DateFormat format) { + this(buildWebClient(mapper.copy(), format), format); + } + + private ApiClient(WebClient webClient, DateFormat format) { + this.webClient = webClient; + this.dateFormat = format; + } + + public DateFormat createDefaultDateFormat() { + DateFormat dateFormat = new RFC3339DateFormat(); + dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + return dateFormat; + } + + protected void init() { + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap();{{#authMethods}}{{#isBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + } + + /** + * Build the RestTemplate used to make HTTP requests. + * @return RestTemplate + */ + public static WebClient buildWebClient(ObjectMapper mapper, DateFormat dateFormat) { + mapper.setDateFormat(dateFormat); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + ExchangeStrategies strategies = ExchangeStrategies + .builder() + .codecs(clientDefaultCodecsConfigurer -> { + clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonEncoder(new Jackson2JsonEncoder(mapper, MediaType.APPLICATION_JSON)); + clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(mapper, MediaType.APPLICATION_JSON)); + }).build(); + WebClient.Builder webClient = WebClient.builder().exchangeStrategies(strategies); + return webClient.build(); + } + + + /** + * Get the current base path + * @return String the base path + */ + public String getBasePath() { + return basePath; + } + + /** + * Set the base path, which should include the host + * @param basePath the base path + * @return ApiClient this client + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Get authentications (key: authentication name, value: authentication). + * @return Map the currently configured authentication types + */ + public Map getAuthentications() { + return authentications; + } + + /** + * Get authentication for the given name. + * + * @param authName The authentication name + * @return The authentication, null if not found + */ + public Authentication getAuthentication(String authName) { + return authentications.get(authName); + } + + /** + * Helper method to set username for the first HTTP basic authentication. + * @param username the username + */ + public void setUsername(String username) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setUsername(username); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set password for the first HTTP basic authentication. + * @param password the password + */ + public void setPassword(String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setPassword(password); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set API key value for the first API key authentication. + * @param apiKey the API key + */ + public void setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + * @param apiKeyPrefix the API key prefix + */ + public void setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set access token for the first OAuth2 authentication. + * @param accessToken the access token + */ + public void setAccessToken(String accessToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setAccessToken(accessToken); + return; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Set the User-Agent header's value (by adding to the default header map). + * @param userAgent the user agent string + * @return ApiClient this client + */ + public ApiClient setUserAgent(String userAgent) { + addDefaultHeader("User-Agent", userAgent); + return this; + } + + /** + * Add a default header. + * + * @param name The header's name + * @param value The header's value + * @return ApiClient this client + */ + public ApiClient addDefaultHeader(String name, String value) { + if (defaultHeaders.containsKey(name)) { + defaultHeaders.remove(name); + } + defaultHeaders.add(name, value); + return this; + } + + /** + * Get the date format used to parse/format date parameters. + * @return DateFormat format + */ + public DateFormat getDateFormat() { + return dateFormat; + } + + /** + * Parse the given string into Date object. + */ + public Date parseDate(String str) { + try { + return dateFormat.parse(str); + } catch (ParseException e) { + throw new RuntimeException(e); + } + } + + /** + * Format the given Date object into string. + */ + public String formatDate(Date date) { + return dateFormat.format(date); + } + + /** + * Format the given parameter object into string. + * @param param the object to convert + * @return String the parameter represented as a String + */ + public String parameterToString(Object param) { + if (param == null) { + return ""; + } else if (param instanceof Date) { + return formatDate( (Date) param); + } else if (param instanceof Collection) { + StringBuilder b = new StringBuilder(); + for(Object o : (Collection) param) { + if(b.length() > 0) { + b.append(","); + } + b.append(String.valueOf(o)); + } + return b.toString(); + } else { + return String.valueOf(param); + } + } + + /** + * Converts a parameter to a {@link MultiValueMap} for use in REST requests + * @param collectionFormat The format to convert to + * @param name The name of the parameter + * @param value The parameter's value + * @return a Map containing the String value(s) of the input parameter + */ + public MultiValueMap parameterToMultiValueMap(CollectionFormat collectionFormat, String name, Object value) { + final MultiValueMap params = new LinkedMultiValueMap(); + + if (name == null || name.isEmpty() || value == null) { + return params; + } + + if(collectionFormat == null) { + collectionFormat = CollectionFormat.CSV; + } + + Collection valueCollection = null; + if (value instanceof Collection) { + valueCollection = (Collection) value; + } else { + params.add(name, parameterToString(value)); + return params; + } + + if (valueCollection.isEmpty()){ + return params; + } + + if (collectionFormat.equals(CollectionFormat.MULTI)) { + for (Object item : valueCollection) { + params.add(name, parameterToString(item)); + } + return params; + } + + List values = new ArrayList(); + for(Object o : valueCollection) { + values.add(parameterToString(o)); + } + params.add(name, collectionFormat.collectionToString(values)); + + return params; + } + + /** + * Check if the given {@code String} is a JSON MIME. + * @param mediaType the input MediaType + * @return boolean true if the MediaType represents JSON, false otherwise + */ + public boolean isJsonMime(String mediaType) { + // "* / *" is default to JSON + if ("*/*".equals(mediaType)) { + return true; + } + + try { + return isJsonMime(MediaType.parseMediaType(mediaType)); + } catch (InvalidMediaTypeException e) { + } + return false; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * @param mediaType the input MediaType + * @return boolean true if the MediaType represents JSON, false otherwise + */ + public boolean isJsonMime(MediaType mediaType) { + return mediaType != null && (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType) || mediaType.getSubtype().matches("^.*\\+json[;]?\\s*$")); + } + + /** + * Select the Accept header's value from the given accepts array: + * if JSON exists in the given array, use it; + * otherwise use all of them (joining into a string) + * + * @param accepts The accepts array to select from + * @return List The list of MediaTypes to use for the Accept header + */ + public List selectHeaderAccept(String[] accepts) { + if (accepts.length == 0) { + return null; + } + for (String accept : accepts) { + MediaType mediaType = MediaType.parseMediaType(accept); + if (isJsonMime(mediaType)) { + return Collections.singletonList(mediaType); + } + } + return MediaType.parseMediaTypes(StringUtils.arrayToCommaDelimitedString(accepts)); + } + + /** + * Select the Content-Type header's value from the given array: + * if JSON exists in the given array, use it; + * otherwise use the first one of the array. + * + * @param contentTypes The Content-Type array to select from + * @return MediaType The Content-Type header to use. If the given array is empty, JSON will be used. + */ + public MediaType selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0) { + return MediaType.APPLICATION_JSON; + } + for (String contentType : contentTypes) { + MediaType mediaType = MediaType.parseMediaType(contentType); + if (isJsonMime(mediaType)) { + return mediaType; + } + } + return MediaType.parseMediaType(contentTypes[0]); + } + + /** + * Select the body to use for the request + * @param obj the body object + * @param formParams the form parameters + * @param contentType the content type of the request + * @return Object the selected body + */ + protected BodyInserter selectBody(Object obj, MultiValueMap formParams, MediaType contentType) { + boolean isForm = MediaType.MULTIPART_FORM_DATA.isCompatibleWith(contentType) || MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(contentType); + return isForm ? BodyInserters.fromMultipartData(formParams) : (obj != null ? BodyInserters.fromObject(obj) : null); + } + + /** + * Invoke API by sending HTTP request with the given options. + * + * @param the return type to use + * @param path The sub-path of the HTTP URL + * @param method The request method + * @param queryParams The query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param formParams The form parameters + * @param accept The request's Accept header + * @param contentType The request's Content-Type header + * @param authNames The authentications to apply + * @param returnType The return type into which to deserialize the response + * @return The response body in chosen type + */ + public Mono invokeAPI(String path, HttpMethod method, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { + final WebClient.RequestBodySpec requestBuilder = prepareRequest(path, method, queryParams, body, headerParams, formParams, accept, contentType, authNames); + + return requestBuilder.exchange() + .flatMap(response -> { + HttpStatus statusCode = response.statusCode(); + if (response.statusCode() == HttpStatus.NO_CONTENT) { + return Mono.empty(); + } else if (statusCode.is2xxSuccessful()) { + if (returnType == null) { + return Mono.empty(); + } else { + return response.bodyToMono(returnType); + } + } else { + return Mono.error(new RestClientException("API returned " + statusCode + " and it wasn't handled by the RestTemplate error handler")); + } + }); + } + + /** + * Invoke API by sending HTTP request with the given options. + * + * @param the return type to use + * @param path The sub-path of the HTTP URL + * @param method The request method + * @param queryParams The query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param formParams The form parameters + * @param accept The request's Accept header + * @param contentType The request's Content-Type header + * @param authNames The authentications to apply + * @param returnType The return type into which to deserialize the response + * @return The response body in chosen type + */ + public Flux invokeFluxAPI(String path, HttpMethod method, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { + final WebClient.RequestBodySpec requestBuilder = prepareRequest(path, method, queryParams, body, headerParams, formParams, accept, contentType, authNames); + + return requestBuilder.exchange() + .flatMapMany(response -> { + HttpStatus statusCode = response.statusCode(); + ClientResponse.Headers headers = response.headers(); + if (response.statusCode() == HttpStatus.NO_CONTENT) { + return Flux.empty(); + } else if (statusCode.is2xxSuccessful()) { + if (returnType == null) { + return Flux.empty(); + } else { + return response.bodyToFlux(returnType); + } + } else { + return Flux.error(new RestClientException("API returned " + statusCode + " and it wasn't handled by the RestTemplate error handler")); + } + }); + } + + private WebClient.RequestBodySpec prepareRequest(String path, HttpMethod method, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames) { + updateParamsForAuth(authNames, queryParams, headerParams); + + final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(path); + if (queryParams != null) { + //encode the query parameters in case they contain unsafe characters + for (List values : queryParams.values()) { + if (values != null) { + for (int i = 0; i < values.size(); i++) { + try { + values.set(i, URLEncoder.encode(values.get(i), "utf8")); + } catch (UnsupportedEncodingException e) { + + } + } + } + } + builder.queryParams(queryParams); + } + + final WebClient.RequestBodySpec requestBuilder = webClient.method(method).uri(builder.build().toUri()); + if(accept != null) { + requestBuilder.accept(accept.toArray(new MediaType[accept.size()])); + } + if(contentType != null) { + requestBuilder.contentType(contentType); + } + + addHeadersToRequest(headerParams, requestBuilder); + addHeadersToRequest(defaultHeaders, requestBuilder); + + requestBuilder.body(selectBody(body, formParams, contentType)); + return requestBuilder; + } + + /** + * Add headers to the request that is being built + * @param headers The headers to add + * @param requestBuilder The current request + */ + protected void addHeadersToRequest(HttpHeaders headers, WebClient.RequestBodySpec requestBuilder) { + for (Entry> entry : headers.entrySet()) { + List values = entry.getValue(); + for(String value : values) { + if (value != null) { + requestBuilder.header(entry.getKey(), value); + } + } + } + } + + /** + * Update query and header parameters based on authentication settings. + * + * @param authNames The authentications to apply + * @param queryParams The query parameters + * @param headerParams The header parameters + */ + private void updateParamsForAuth(String[] authNames, MultiValueMap queryParams, HttpHeaders headerParams) { + for (String authName : authNames) { + Authentication auth = authentications.get(authName); + if (auth == null) { + throw new RestClientException("Authentication undefined: " + authName); + } + auth.applyToParams(queryParams, headerParams); + } + } + + private class ApiClientHttpRequestInterceptor implements ClientHttpRequestInterceptor { + private final Log log = LogFactory.getLog(ApiClientHttpRequestInterceptor.class); + + @Override + public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { + logRequest(request, body); + ClientHttpResponse response = execution.execute(request, body); + logResponse(response); + return response; + } + + private void logRequest(HttpRequest request, byte[] body) throws UnsupportedEncodingException { + log.info("URI: " + request.getURI()); + log.info("HTTP Method: " + request.getMethod()); + log.info("HTTP Headers: " + headersToString(request.getHeaders())); + log.info("Request Body: " + new String(body, StandardCharsets.UTF_8)); + } + + private void logResponse(ClientHttpResponse response) throws IOException { + log.info("HTTP Status Code: " + response.getRawStatusCode()); + log.info("Status Text: " + response.getStatusText()); + log.info("HTTP Headers: " + headersToString(response.getHeaders())); + log.info("Response Body: " + bodyToString(response.getBody())); + } + + private String headersToString(HttpHeaders headers) { + StringBuilder builder = new StringBuilder(); + for(Entry> entry : headers.entrySet()) { + builder.append(entry.getKey()).append("=["); + for(String value : entry.getValue()) { + builder.append(value).append(","); + } + builder.setLength(builder.length() - 1); // Get rid of trailing comma + builder.append("],"); + } + builder.setLength(builder.length() - 1); // Get rid of trailing comma + return builder.toString(); + } + + private String bodyToString(InputStream body) throws IOException { + StringBuilder builder = new StringBuilder(); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(body, StandardCharsets.UTF_8)); + String line = bufferedReader.readLine(); + while (line != null) { + builder.append(line).append(System.lineSeparator()); + line = bufferedReader.readLine(); + } + bufferedReader.close(); + return builder.toString(); + } + } +} diff --git a/libraries/webclient/api.mustache b/libraries/webclient/api.mustache new file mode 100644 index 00000000000..6d6a38e25c0 --- /dev/null +++ b/libraries/webclient/api.mustache @@ -0,0 +1,107 @@ +package {{package}}; + +import {{invokerPackage}}.ApiClient; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}}import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map;{{/fullJavaUtil}} + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.util.UriComponentsBuilder; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.core.io.FileSystemResource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import reactor.core.publisher.Mono; +import reactor.core.publisher.Flux; + +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}} { + private ApiClient {{localVariablePrefix}}apiClient; + + public {{classname}}() { + this(new ApiClient()); + } + + @Autowired + public {{classname}}(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + public ApiClient getApiClient() { + return {{localVariablePrefix}}apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.{{localVariablePrefix}}apiClient = apiClient; + } + + {{#operation}} + /** + * {{summary}} + * {{notes}} +{{#responses}} *

{{code}}{{#message}} - {{message}}{{/message}} +{{/responses}}{{#allParams}} * @param {{paramName}} {{description}}{{^description}}The {{paramName}} parameter{{/description}} +{{/allParams}}{{#returnType}} * @return {{returnType}} +{{/returnType}} * @throws RestClientException if an error occurs while attempting to invoke the API +{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation +{{/externalDocs}} + */ + public {{#returnType}}{{#isListContainer}}Flux<{{{returnBaseType}}}>{{/isListContainer}}{{^isListContainer}}Mono<{{{returnType}}}>{{/isListContainer}} {{/returnType}}{{^returnType}}Mono {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { + Object {{localVariablePrefix}}postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + } + {{/required}}{{/allParams}}{{#hasPathParams}} + // create path and map variables + final Map uriVariables = new HashMap();{{#pathParams}} + uriVariables.put("{{baseName}}", {{{paramName}}});{{/pathParams}}{{/hasPathParams}} + String {{localVariablePrefix}}path = UriComponentsBuilder.fromPath("{{{path}}}"){{#hasPathParams}}.buildAndExpand(uriVariables){{/hasPathParams}}{{^hasPathParams}}.build(){{/hasPathParams}}.toUriString(); + + final MultiValueMap {{localVariablePrefix}}queryParams = new LinkedMultiValueMap(); + final HttpHeaders {{localVariablePrefix}}headerParams = new HttpHeaders(); + final MultiValueMap {{localVariablePrefix}}formParams = new LinkedMultiValueMap();{{#hasQueryParams}} + + {{#queryParams}}{{localVariablePrefix}}queryParams.putAll({{localVariablePrefix}}apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase()){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{#hasMore}} + {{/hasMore}}{{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}} + + {{#headerParams}}if ({{paramName}} != null) + {{localVariablePrefix}}headerParams.add("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}}));{{#hasMore}} + {{/hasMore}}{{/headerParams}}{{/hasHeaderParams}}{{#hasFormParams}} + + {{#formParams}}if ({{paramName}} != null) + {{localVariablePrefix}}formParams.add("{{baseName}}", {{#isFile}}new FileSystemResource({{paramName}}){{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} + {{/hasMore}}{{/formParams}}{{/hasFormParams}} + + final String[] {{localVariablePrefix}}accepts = { {{#hasProduces}} + {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} + {{/hasProduces}}}; + final List {{localVariablePrefix}}accept = {{localVariablePrefix}}apiClient.selectHeaderAccept({{localVariablePrefix}}accepts); + final String[] {{localVariablePrefix}}contentTypes = { {{#hasConsumes}} + {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} + {{/hasConsumes}}}; + final MediaType {{localVariablePrefix}}contentType = {{localVariablePrefix}}apiClient.selectHeaderContentType({{localVariablePrefix}}contentTypes); + + String[] {{localVariablePrefix}}authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + + {{#returnType}}ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}> {{localVariablePrefix}}returnType = new ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference {{localVariablePrefix}}returnType = new ParameterizedTypeReference() {};{{/returnType}} + return {{localVariablePrefix}}apiClient.{{#isListContainer}}invokeFluxAPI{{/isListContainer}}{{^isListContainer}}invokeAPI{{/isListContainer}}({{localVariablePrefix}}path, HttpMethod.{{httpMethod}}, {{localVariablePrefix}}queryParams, {{localVariablePrefix}}postBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames, {{localVariablePrefix}}returnType); + } + {{/operation}} +} +{{/operations}} diff --git a/libraries/webclient/api_test.mustache b/libraries/webclient/api_test.mustache new file mode 100644 index 00000000000..f1dca2f41cf --- /dev/null +++ b/libraries/webclient/api_test.mustache @@ -0,0 +1,45 @@ +{{>licenseInfo}} + +package {{package}}; + +import {{invokerPackage}}.ApiException; +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Test; +import org.junit.Ignore; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +@Ignore +public class {{classname}}Test { + + private final {{classname}} api = new {{classname}}(); + + {{#operations}}{{#operation}} + /** + * {{summary}} + * + * {{notes}} + * + * @throws ApiException + * if the Api call fails + */ + @Test + public void {{operationId}}Test() throws ApiException { + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#isListContainer}}.collectList().block(){{/isListContainer}}{{^isListContainer}}.block(){{/isListContainer}}; + + // TODO: test validations + } + {{/operation}}{{/operations}} +} diff --git a/libraries/webclient/auth/ApiKeyAuth.mustache b/libraries/webclient/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..8b8c40fde75 --- /dev/null +++ b/libraries/webclient/auth/ApiKeyAuth.mustache @@ -0,0 +1,60 @@ +package {{invokerPackage}}.auth; + +import org.springframework.http.HttpHeaders; +import org.springframework.util.MultiValueMap; + +{{>generatedAnnotation}} +public class ApiKeyAuth implements Authentication { + private final String location; + private final String paramName; + + private String apiKey; + private String apiKeyPrefix; + + public ApiKeyAuth(String location, String paramName) { + this.location = location; + this.paramName = paramName; + } + + public String getLocation() { + return location; + } + + public String getParamName() { + return paramName; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + public String getApiKeyPrefix() { + return apiKeyPrefix; + } + + public void setApiKeyPrefix(String apiKeyPrefix) { + this.apiKeyPrefix = apiKeyPrefix; + } + + @Override + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams) { + if (apiKey == null) { + return; + } + String value; + if (apiKeyPrefix != null) { + value = apiKeyPrefix + " " + apiKey; + } else { + value = apiKey; + } + if (location.equals("query")) { + queryParams.add(paramName, value); + } else if (location.equals("header")) { + headerParams.add(paramName, value); + } + } +} diff --git a/libraries/webclient/auth/Authentication.mustache b/libraries/webclient/auth/Authentication.mustache new file mode 100644 index 00000000000..586de70836a --- /dev/null +++ b/libraries/webclient/auth/Authentication.mustache @@ -0,0 +1,13 @@ +package {{invokerPackage}}.auth; + +import org.springframework.http.HttpHeaders; +import org.springframework.util.MultiValueMap; + +public interface Authentication { + /** + * Apply authentication settings to header and / or query parameters. + * @param queryParams The query parameters for the request + * @param headerParams The header parameters for the request + */ + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams); +} diff --git a/libraries/webclient/auth/HttpBasicAuth.mustache b/libraries/webclient/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..5f535b3698a --- /dev/null +++ b/libraries/webclient/auth/HttpBasicAuth.mustache @@ -0,0 +1,39 @@ +package {{invokerPackage}}.auth; + +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; + +import org.springframework.http.HttpHeaders; +import org.springframework.util.Base64Utils; +import org.springframework.util.MultiValueMap; + +{{>generatedAnnotation}} +public class HttpBasicAuth implements Authentication { + private String username; + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams) { + if (username == null && password == null) { + return; + } + String str = (username == null ? "" : username) + ":" + (password == null ? "" : password); + headerParams.add(HttpHeaders.AUTHORIZATION, "Basic " + Base64Utils.encodeToString(str.getBytes(StandardCharsets.UTF_8))); + } +} diff --git a/libraries/webclient/auth/OAuth.mustache b/libraries/webclient/auth/OAuth.mustache new file mode 100644 index 00000000000..fbb2f7f9c72 --- /dev/null +++ b/libraries/webclient/auth/OAuth.mustache @@ -0,0 +1,24 @@ +package {{invokerPackage}}.auth; + +import org.springframework.http.HttpHeaders; +import org.springframework.util.MultiValueMap; + +{{>generatedAnnotation}} +public class OAuth implements Authentication { + private String accessToken; + + public String getAccessToken() { + return accessToken; + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + @Override + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams) { + if (accessToken != null) { + headerParams.add(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken); + } + } +} diff --git a/libraries/webclient/auth/OAuthFlow.mustache b/libraries/webclient/auth/OAuthFlow.mustache new file mode 100644 index 00000000000..7ab35f6d890 --- /dev/null +++ b/libraries/webclient/auth/OAuthFlow.mustache @@ -0,0 +1,5 @@ +package {{invokerPackage}}.auth; + +public enum OAuthFlow { + accessCode, implicit, password, application +} \ No newline at end of file diff --git a/libraries/webclient/pom.mustache b/libraries/webclient/pom.mustache new file mode 100644 index 00000000000..4771a9bb658 --- /dev/null +++ b/libraries/webclient/pom.mustache @@ -0,0 +1,135 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{artifactUrl}} + {{artifactDescription}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-annotations-version} + + + + io.projectreactor + reactor-core + ${reactor-version} + + + + + org.springframework + spring-webflux + ${spring-web-version} + + + + io.projectreactor.ipc + reactor-netty + ${reactor-netty-version} + + + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-version} + + + {{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{/java8}} + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + + joda-time + joda-time + ${jodatime-version} + + {{/joda}} + + + + junit + junit + ${junit-version} + test + + + + UTF-8 + 1.5.20 + 5.0.7.RELEASE + 2.9.5 + 4.12 + 3.1.8.RELEASE + 0.7.8.RELEASE + {{#joda}} + 2.9.9 + {{/joda}} + + From c3299512d765aef844877dc27a13c583175f446a Mon Sep 17 00:00:00 2001 From: developersteve Date: Wed, 4 Jul 2018 21:05:14 +1000 Subject: [PATCH 029/370] [Java] version in the generated README dependent from {{java8}} (#380) --- README.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.mustache b/README.mustache index 888992bc914..a462368db62 100644 --- a/README.mustache +++ b/README.mustache @@ -18,7 +18,7 @@ ## Requirements Building the API client library requires: -1. Java 1.7+ +1. Java {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}+ 2. Maven/Gradle ## Installation From a484cb2d0a5559c38c22f02bec70672d2b886c8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Sat, 14 Jul 2018 15:13:23 +0200 Subject: [PATCH 030/370] Java6 support: fix pom and gradle files, avoid diamond notation (#560) --- README.mustache | 2 +- build.gradle.mustache | 12 ++++++++++ libraries/feign/build.gradle.mustache | 22 +++++++++++++++++-- libraries/feign/pom.mustache | 2 +- .../google-api-client/build.gradle.mustache | 12 ++++++++++ libraries/google-api-client/pom.mustache | 6 +++++ libraries/jersey2/ApiClient.mustache | 6 ++--- libraries/jersey2/build.gradle.mustache | 12 ++++++++++ libraries/jersey2/pom.mustache | 6 +++++ libraries/okhttp-gson/build.gradle.mustache | 22 +++++++++++++++++-- libraries/okhttp-gson/pom.mustache | 2 +- libraries/resteasy/build.gradle.mustache | 12 ++++++++++ libraries/resteasy/pom.mustache | 6 +++++ libraries/resttemplate/build.gradle.mustache | 12 ++++++++++ libraries/resttemplate/pom.mustache | 6 +++++ libraries/retrofit/build.gradle.mustache | 6 +++++ libraries/retrofit/pom.mustache | 16 ++++++++++++-- libraries/retrofit2/build.gradle.mustache | 22 +++++++++++++++++-- libraries/retrofit2/play24/ApiClient.mustache | 6 ++--- libraries/retrofit2/play25/ApiClient.mustache | 6 ++--- libraries/retrofit2/pom.mustache | 2 +- pom.mustache | 6 +++++ 22 files changed, 183 insertions(+), 21 deletions(-) diff --git a/README.mustache b/README.mustache index a462368db62..45cf63f7b6a 100644 --- a/README.mustache +++ b/README.mustache @@ -18,7 +18,7 @@ ## Requirements Building the API client library requires: -1. Java {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}+ +1. Java {{#supportJava6}}1.6{{/supportJava6}}{{^supportJava6}}{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}{{/supportJava6}}+ 2. Maven/Gradle ## Installation diff --git a/build.gradle.mustache b/build.gradle.mustache index 575811da812..192ac3cbbbc 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -31,6 +31,11 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 25 } compileOptions { + {{#supportJava6}} + sourceCompatibility JavaVersion.VERSION_1_6 + targetCompatibility JavaVersion.VERSION_1_6 + {{/supportJava6}} + {{^supportJava6}} {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -39,6 +44,7 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 {{/java8}} + {{/supportJava6}} } // Rename the aar correctly @@ -83,6 +89,11 @@ if(hasProperty('target') && target == 'android') { apply plugin: 'java' apply plugin: 'maven' + {{#supportJava6}} + sourceCompatibility = JavaVersion.VERSION_1_6 + targetCompatibility = JavaVersion.VERSION_1_6 + {{/supportJava6}} + {{^supportJava6}} {{#java8}} sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 @@ -91,6 +102,7 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility = JavaVersion.VERSION_1_7 targetCompatibility = JavaVersion.VERSION_1_7 {{/java8}} + {{/supportJava6}} install { repositories.mavenInstaller { diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index 0074c0e38a2..32254e52506 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -32,6 +32,11 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 25 } compileOptions { + {{#supportJava6}} + sourceCompatibility JavaVersion.VERSION_1_6 + targetCompatibility JavaVersion.VERSION_1_6 + {{/supportJava6}} + {{^supportJava6}} {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -40,6 +45,7 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 {{/java8}} + {{/supportJava6}} } // Rename the aar correctly @@ -84,8 +90,20 @@ if(hasProperty('target') && target == 'android') { apply plugin: 'java' apply plugin: 'maven' - sourceCompatibility = JavaVersion.VERSION_{{^java8}}1_7{{/java8}}{{#java8}}1_8{{/java8}} - targetCompatibility = JavaVersion.VERSION_{{^java8}}1_7{{/java8}}{{#java8}}1_8{{/java8}} + {{#supportJava6}} + sourceCompatibility = JavaVersion.VERSION_1_6 + targetCompatibility = JavaVersion.VERSION_1_6 + {{/supportJava6}} + {{^supportJava6}} + {{#java8}} + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + {{/java8}} + {{/supportJava6}} install { repositories.mavenInstaller { diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index ad255c13ea4..a616e68bcff 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -291,7 +291,7 @@ UTF-8 - {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}} + {{#supportJava6}}1.6{{/supportJava6}}{{^supportJava6}}{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}{{/supportJava6}} ${java.version} ${java.version} 1.5.18 diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache index e6197b08f7a..1a2b2afc6cd 100644 --- a/libraries/google-api-client/build.gradle.mustache +++ b/libraries/google-api-client/build.gradle.mustache @@ -32,6 +32,11 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 22 } compileOptions { + {{#supportJava6}} + sourceCompatibility JavaVersion.VERSION_1_6 + targetCompatibility JavaVersion.VERSION_1_6 + {{/supportJava6}} + {{^supportJava6}} {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -40,6 +45,7 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 {{/java8}} + {{/supportJava6}} } // Rename the aar correctly @@ -84,6 +90,11 @@ if(hasProperty('target') && target == 'android') { apply plugin: 'java' apply plugin: 'maven' + {{#supportJava6}} + sourceCompatibility = JavaVersion.VERSION_1_6 + targetCompatibility = JavaVersion.VERSION_1_6 + {{/supportJava6}} + {{^supportJava6}} {{#java8}} sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 @@ -92,6 +103,7 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility = JavaVersion.VERSION_1_7 targetCompatibility = JavaVersion.VERSION_1_7 {{/java8}} + {{/supportJava6}} install { repositories.mavenInstaller { diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index e8605bbac61..2fff29a15b5 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -139,6 +139,11 @@ maven-compiler-plugin 3.6.1 + {{#supportJava6}} + 1.6 + 1.6 + {{/supportJava6}} + {{^supportJava6}} {{#java8}} 1.8 1.8 @@ -147,6 +152,7 @@ 1.7 1.7 {{/java8}} + {{/supportJava6}} diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index e70b34ad0dc..da375a01057 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -709,12 +709,12 @@ public class ApiClient { Map> responseHeaders = buildResponseHeaders(response); if (response.getStatus() == Status.NO_CONTENT.getStatusCode()) { - return new ApiResponse<>(statusCode, responseHeaders); + return new ApiResponse<{{#supportJava6}}T{{/supportJava6}}>(statusCode, responseHeaders); } else if (response.getStatusInfo().getFamily() == Status.Family.SUCCESSFUL) { if (returnType == null) - return new ApiResponse<>(statusCode, responseHeaders); + return new ApiResponse<{{#supportJava6}}T{{/supportJava6}}>(statusCode, responseHeaders); else - return new ApiResponse<>(statusCode, responseHeaders, deserialize(response, returnType)); + return new ApiResponse<{{#supportJava6}}T{{/supportJava6}}>(statusCode, responseHeaders, deserialize(response, returnType)); } else { String message = "error"; String respBody = null; diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index 19d8c2c6d84..9da2a053e84 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -32,6 +32,11 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 25 } compileOptions { + {{#supportJava6}} + sourceCompatibility JavaVersion.VERSION_1_6 + targetCompatibility JavaVersion.VERSION_1_6 + {{/supportJava6}} + {{^supportJava6}} {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -40,6 +45,7 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 {{/java8}} + {{/supportJava6}} } // Rename the aar correctly @@ -83,6 +89,11 @@ if(hasProperty('target') && target == 'android') { apply plugin: 'java' apply plugin: 'maven' + {{#supportJava6}} + sourceCompatibility = JavaVersion.VERSION_1_6 + targetCompatibility = JavaVersion.VERSION_1_6 + {{/supportJava6}} + {{^supportJava6}} {{#java8}} sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 @@ -91,6 +102,7 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility = JavaVersion.VERSION_1_7 targetCompatibility = JavaVersion.VERSION_1_7 {{/java8}} + {{/supportJava6}} install { repositories.mavenInstaller { diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 85f38605dd8..ebdd3f9d925 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -139,6 +139,11 @@ maven-compiler-plugin 3.6.1 + {{#supportJava6}} + 1.6 + 1.6 + {{/supportJava6}} + {{^supportJava6}} {{#java8}} 1.8 1.8 @@ -147,6 +152,7 @@ 1.7 1.7 {{/java8}} + {{/supportJava6}} diff --git a/libraries/okhttp-gson/build.gradle.mustache b/libraries/okhttp-gson/build.gradle.mustache index 27fe1caaf25..69621c1a6bd 100644 --- a/libraries/okhttp-gson/build.gradle.mustache +++ b/libraries/okhttp-gson/build.gradle.mustache @@ -32,6 +32,11 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 25 } compileOptions { + {{#supportJava6}} + sourceCompatibility JavaVersion.VERSION_1_6 + targetCompatibility JavaVersion.VERSION_1_6 + {{/supportJava6}} + {{^supportJava6}} {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -40,6 +45,7 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 {{/java8}} + {{/supportJava6}} } // Rename the aar correctly @@ -84,8 +90,20 @@ if(hasProperty('target') && target == 'android') { apply plugin: 'java' apply plugin: 'maven' - sourceCompatibility = JavaVersion.VERSION_{{^java8}}1_7{{/java8}}{{#java8}}1_8{{/java8}} - targetCompatibility = JavaVersion.VERSION_{{^java8}}1_7{{/java8}}{{#java8}}1_8{{/java8}} + {{#supportJava6}} + sourceCompatibility = JavaVersion.VERSION_1_6 + targetCompatibility = JavaVersion.VERSION_1_6 + {{/supportJava6}} + {{^supportJava6}} + {{#java8}} + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + {{/java8}} + {{/supportJava6}} install { repositories.mavenInstaller { diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index b5119774a05..0b0903d617b 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -267,7 +267,7 @@ - {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}} + {{#supportJava6}}1.6{{/supportJava6}}{{^supportJava6}}{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}{{/supportJava6}} ${java.version} ${java.version} 1.8.0 diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index fc42da3e68c..fc2cd18dbea 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -32,6 +32,11 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 23 } compileOptions { + {{#supportJava6}} + sourceCompatibility JavaVersion.VERSION_1_6 + targetCompatibility JavaVersion.VERSION_1_6 + {{/supportJava6}} + {{^supportJava6}} {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -40,6 +45,7 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 {{/java8}} + {{/supportJava6}} } // Rename the aar correctly @@ -83,6 +89,11 @@ if(hasProperty('target') && target == 'android') { apply plugin: 'java' apply plugin: 'maven' + {{#supportJava6}} + sourceCompatibility = JavaVersion.VERSION_1_6 + targetCompatibility = JavaVersion.VERSION_1_6 + {{/supportJava6}} + {{^supportJava6}} {{#java8}} sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 @@ -91,6 +102,7 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility = JavaVersion.VERSION_1_7 targetCompatibility = JavaVersion.VERSION_1_7 {{/java8}} + {{/supportJava6}} install { repositories.mavenInstaller { diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index e6aae545c91..479c22ba75c 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -120,6 +120,11 @@ maven-compiler-plugin 2.5.1 + {{#supportJava6}} + 1.6 + 1.6 + {{/supportJava6}} + {{^supportJava6}} {{#java8}} 1.8 1.8 @@ -128,6 +133,7 @@ 1.7 1.7 {{/java8}} + {{/supportJava6}} diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index e4fc1caa4f0..9925cc43daf 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -32,6 +32,11 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 22 } compileOptions { + {{#supportJava6}} + sourceCompatibility JavaVersion.VERSION_1_6 + targetCompatibility JavaVersion.VERSION_1_6 + {{/supportJava6}} + {{^supportJava6}} {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -40,6 +45,7 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 {{/java8}} + {{/supportJava6}} } // Rename the aar correctly @@ -84,6 +90,11 @@ if(hasProperty('target') && target == 'android') { apply plugin: 'java' apply plugin: 'maven' + {{#supportJava6}} + sourceCompatibility = JavaVersion.VERSION_1_6 + targetCompatibility = JavaVersion.VERSION_1_6 + {{/supportJava6}} + {{^supportJava6}} {{#java8}} sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 @@ -92,6 +103,7 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility = JavaVersion.VERSION_1_7 targetCompatibility = JavaVersion.VERSION_1_7 {{/java8}} + {{/supportJava6}} install { repositories.mavenInstaller { diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache index 01abe39efb5..0d371de6ea1 100644 --- a/libraries/resttemplate/pom.mustache +++ b/libraries/resttemplate/pom.mustache @@ -139,6 +139,11 @@ maven-compiler-plugin 3.6.1 + {{#supportJava6}} + 1.6 + 1.6 + {{/supportJava6}} + {{^supportJava6}} {{#java8}} 1.8 1.8 @@ -147,6 +152,7 @@ 1.7 1.7 {{/java8}} + {{/supportJava6}} diff --git a/libraries/retrofit/build.gradle.mustache b/libraries/retrofit/build.gradle.mustache index 6befe74db7c..f0c1cbe4c88 100644 --- a/libraries/retrofit/build.gradle.mustache +++ b/libraries/retrofit/build.gradle.mustache @@ -32,6 +32,11 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 25 } compileOptions { + {{#supportJava6}} + sourceCompatibility JavaVersion.VERSION_1_6 + targetCompatibility JavaVersion.VERSION_1_6 + {{/supportJava6}} + {{^supportJava6}} {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -40,6 +45,7 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 {{/java8}} + {{/supportJava6}} } // Rename the aar correctly diff --git a/libraries/retrofit/pom.mustache b/libraries/retrofit/pom.mustache index 0921ab21ac4..adbd6e99e50 100644 --- a/libraries/retrofit/pom.mustache +++ b/libraries/retrofit/pom.mustache @@ -139,8 +139,20 @@ maven-compiler-plugin 3.6.1 - {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}} - {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}} + {{#supportJava6}} + 1.6 + 1.6 + {{/supportJava6}} + {{^supportJava6}} + {{#java8}} + 1.8 + 1.8 + {{/java8}} + {{^java8}} + 1.7 + 1.7 + {{/java8}} + {{/supportJava6}} diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index f341375f821..858b88971b2 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -32,6 +32,11 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 25 } compileOptions { + {{#supportJava6}} + sourceCompatibility JavaVersion.VERSION_1_6 + targetCompatibility JavaVersion.VERSION_1_6 + {{/supportJava6}} + {{^supportJava6}} {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -40,6 +45,7 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 {{/java8}} + {{/supportJava6}} } // Rename the aar correctly @@ -84,8 +90,20 @@ if(hasProperty('target') && target == 'android') { apply plugin: 'java' apply plugin: 'maven' - sourceCompatibility = JavaVersion.VERSION_{{^java8}}1_7{{/java8}}{{#java8}}1_8{{/java8}} - targetCompatibility = JavaVersion.VERSION_{{^java8}}1_7{{/java8}}{{#java8}}1_8{{/java8}} + {{#supportJava6}} + sourceCompatibility = JavaVersion.VERSION_1_6 + targetCompatibility = JavaVersion.VERSION_1_6 + {{/supportJava6}} + {{^supportJava6}} + {{#java8}} + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + {{/java8}} + {{/supportJava6}} install { repositories.mavenInstaller { diff --git a/libraries/retrofit2/play24/ApiClient.mustache b/libraries/retrofit2/play24/ApiClient.mustache index 5c871c62073..8683ccc5f22 100644 --- a/libraries/retrofit2/play24/ApiClient.mustache +++ b/libraries/retrofit2/play24/ApiClient.mustache @@ -40,7 +40,7 @@ public class ApiClient { public ApiClient() { // Setup authentications (key: authentication name, value: authentication). - authentications = new HashMap<>();{{#authMethods}}{{#isBasic}} + authentications = new HashMap<{{#supportJava6}}String, Authentication{{/supportJava6}}>();{{#authMethods}}{{#isBasic}} // authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} // authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} @@ -57,8 +57,8 @@ public class ApiClient { basePath = basePath + "/"; } - Map extraHeaders = new HashMap<>(); - List extraQueryParams = new ArrayList<>(); + Map extraHeaders = new HashMap<{{#supportJava6}}String, String{{/supportJava6}}>(); + List extraQueryParams = new ArrayList<{{#supportJava6}}Pair{{/supportJava6}}>(); for (String authName : authentications.keySet()) { Authentication auth = authentications.get(authName); diff --git a/libraries/retrofit2/play25/ApiClient.mustache b/libraries/retrofit2/play25/ApiClient.mustache index 163afd670c1..7d3dbd1e28c 100644 --- a/libraries/retrofit2/play25/ApiClient.mustache +++ b/libraries/retrofit2/play25/ApiClient.mustache @@ -40,7 +40,7 @@ public class ApiClient { public ApiClient() { // Setup authentications (key: authentication name, value: authentication). - authentications = new HashMap<>();{{#authMethods}}{{#isBasic}} + authentications = new HashMap<{{#supportJava6}}String, Authentication{{/supportJava6}}>();{{#authMethods}}{{#isBasic}} // authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} // authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} @@ -57,8 +57,8 @@ public class ApiClient { basePath = basePath + "/"; } - Map extraHeaders = new HashMap<>(); - List extraQueryParams = new ArrayList<>(); + Map extraHeaders = new HashMap<{{#supportJava6}}String, String{{/supportJava6}}>(); + List extraQueryParams = new ArrayList<{{#supportJava6}}Pair{{/supportJava6}}>(); for (String authName : authentications.keySet()) { Authentication auth = authentications.get(authName); diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index 3adfab68fe7..f23642e46bb 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -327,7 +327,7 @@ UTF-8 - {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}} + {{#supportJava6}}1.6{{/supportJava6}}{{^supportJava6}}{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}{{/supportJava6}} ${java.version} ${java.version} 1.8.0 diff --git a/pom.mustache b/pom.mustache index 7e61c4c05ad..0c1501e115c 100644 --- a/pom.mustache +++ b/pom.mustache @@ -139,6 +139,11 @@ maven-compiler-plugin 3.6.1 + {{#supportJava6}} + 1.6 + 1.6 + {{/supportJava6}} + {{^supportJava6}} {{#java8}} 1.8 1.8 @@ -147,6 +152,7 @@ 1.7 1.7 {{/java8}} + {{/supportJava6}} From c558d1d1dd408182f95b49acf7e5b442065b0ed6 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Sun, 15 Jul 2018 16:00:07 +0800 Subject: [PATCH 031/370] Add travis.yml to test java6 option (#568) Add travis.yml to test java6 option, update Java (Jersey2) dependencies --- libraries/jersey2/build.gradle.mustache | 15 +++++++++------ libraries/jersey2/build.sbt.mustache | 8 ++++---- libraries/jersey2/pom.mustache | 17 ++++++++++------- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index 9da2a053e84..8f7c03adefa 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -117,17 +117,20 @@ if(hasProperty('target') && target == 'android') { } ext { - swagger_annotations_version = "1.5.17" - jackson_version = "2.8.9" + swagger_annotations_version = "1.5.20" + jackson_version = "2.9.6" {{#supportJava6}} jersey_version = "2.6" commons_io_version=2.5 commons_lang3_version=3.6 {{/supportJava6}} {{^supportJava6}} - jersey_version = "2.25.1" + jersey_version = "2.27" {{/supportJava6}} junit_version = "4.12" + {{#threetenbp}} + threetenbp_version = "2.6.4" + {{/threetenbp}} } dependencies { @@ -139,17 +142,17 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" {{#joda}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version", + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} {{#java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version", + compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} {{#supportJava6}} compile "commons-io:commons-io:$commons_io_version" compile "org.apache.commons:commons-lang3:$commons_lang3_version" {{/supportJava6}} {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_version", + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$threetenbp_version" {{/threetenbp}} {{^java8}} compile "com.brsanthu:migbase64:2.2" diff --git a/libraries/jersey2/build.sbt.mustache b/libraries/jersey2/build.sbt.mustache index 544297d481d..54902da7989 100644 --- a/libraries/jersey2/build.sbt.mustache +++ b/libraries/jersey2/build.sbt.mustache @@ -9,13 +9,13 @@ lazy val root = (project in file(".")). publishArtifact in (Compile, packageDoc) := false, resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( - "io.swagger" % "swagger-annotations" % "1.5.17", + "io.swagger" % "swagger-annotations" % "1.5.20", "org.glassfish.jersey.core" % "jersey-client" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, "org.glassfish.jersey.media" % "jersey-media-multipart" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, "org.glassfish.jersey.media" % "jersey-media-json-jackson" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, - "com.fasterxml.jackson.core" % "jackson-core" % "{{^threetenbp}}2.8.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "{{^threetenbp}}2.8.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "{{^threetenbp}}2.8.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.8.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.9" % "compile", {{#joda}} "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.8.9" % "compile", {{/joda}} diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index ebdd3f9d925..5c273fa147b 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -276,7 +276,7 @@ com.github.joschi.jackson jackson-datatype-threetenbp - ${jackson-version} + ${threetenbp-version} {{/threetenbp}} {{^java8}} @@ -318,16 +318,19 @@ UTF-8 - 1.5.18 + 1.5.20 {{^supportJava6}} - 2.25.1 + 2.27 {{/supportJava6}} {{#supportJava6}} - 2.6 - 2.5 - 3.6 + 2.6 + 2.5 + 3.6 {{/supportJava6}} - {{^threetenbp}}2.7.5{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} + 2.8.9 + {{#threetenbp}} + 2.6.4 + {{/threetenbp}} 1.0.0 4.12 From c8016c0917a34def2ead556ed21d1217fdcfa17b Mon Sep 17 00:00:00 2001 From: Daonomic Date: Wed, 18 Jul 2018 07:14:42 +0300 Subject: [PATCH 032/370] Support for discriminator.mapping (#536) --- JSON.mustache | 13 ++++++------- libraries/retrofit2/JSON.mustache | 13 ++++++------- typeInfoAnnotation.mustache | 9 +++++---- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/JSON.mustache b/JSON.mustache index 4ab6cee5cb1..92fa0f9d0fa 100644 --- a/JSON.mustache +++ b/JSON.mustache @@ -60,21 +60,20 @@ public class JSON { public static GsonBuilder createGson() { GsonFireBuilder fireBuilder = new GsonFireBuilder() - {{#parent}} - .registerTypeSelector({{classname}}.class, new TypeSelector() { + {{#models}}{{#model}}{{#discriminator}} .registerTypeSelector({{classname}}.class, new TypeSelector() { @Override public Class getClassForElement(JsonElement readElement) { Map classByDiscriminatorValue = new HashMap(); - {{#children}} - classByDiscriminatorValue.put("{{name}}".toUpperCase(), {{classname}}.class); - {{/children}} + {{#mappedModels}} + classByDiscriminatorValue.put("{{mappingName}}".toUpperCase(), {{modelName}}.class); + {{/mappedModels}} classByDiscriminatorValue.put("{{classname}}".toUpperCase(), {{classname}}.class); return getClassByDiscriminator( classByDiscriminatorValue, - getDiscriminatorValue(readElement, "{{{discriminatorName}}}")); + getDiscriminatorValue(readElement, "{{{propertyName}}}")); } }) - {{/parent}} + {{/discriminator}}{{/model}}{{/models}} ; GsonBuilder builder = fireBuilder.createGsonBuilder(); {{#disableHtmlEscaping}} diff --git a/libraries/retrofit2/JSON.mustache b/libraries/retrofit2/JSON.mustache index 3dcea989c19..ac8958824cb 100644 --- a/libraries/retrofit2/JSON.mustache +++ b/libraries/retrofit2/JSON.mustache @@ -57,21 +57,20 @@ public class JSON { public static GsonBuilder createGson() { GsonFireBuilder fireBuilder = new GsonFireBuilder() - {{#parent}} - .registerTypeSelector({{classname}}.class, new TypeSelector() { + {{#models}}{{#model}}{{#discriminator}} .registerTypeSelector({{classname}}.class, new TypeSelector() { @Override public Class getClassForElement(JsonElement readElement) { Map classByDiscriminatorValue = new HashMap(); - {{#children}} - classByDiscriminatorValue.put("{{name}}".toUpperCase(), {{classname}}.class); - {{/children}} + {{#mappedModels}} + classByDiscriminatorValue.put("{{mappingName}}".toUpperCase(), {{modelName}}.class); + {{/mappedModels}} classByDiscriminatorValue.put("{{classname}}".toUpperCase(), {{classname}}.class); return getClassByDiscriminator( classByDiscriminatorValue, - getDiscriminatorValue(readElement, "{{{discriminatorName}}}")); + getDiscriminatorValue(readElement, "{{{propertyName}}}")); } }) - {{/parent}} + {{/discriminator}}{{/model}}{{/models}} ; return fireBuilder.createGsonBuilder(); } diff --git a/typeInfoAnnotation.mustache b/typeInfoAnnotation.mustache index 1e2d5134b34..8e4b33b7848 100644 --- a/typeInfoAnnotation.mustache +++ b/typeInfoAnnotation.mustache @@ -1,7 +1,8 @@ {{#jackson}} -@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "{{{discriminatorName}}}", visible = true ) + +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "{{{discriminatorName}}}", visible = true) @JsonSubTypes({ - {{#children}} - @JsonSubTypes.Type(value = {{classname}}.class, name = "{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}"), - {{/children}} + {{#discriminator.mappedModels}} + @JsonSubTypes.Type(value = {{modelName}}.class, name = "{{^vendorExtensions.x-discriminator-value}}{{mappingName}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}"), + {{/discriminator.mappedModels}} }){{/jackson}} From b2030bcfdfd41a017a6545098223b6c12936c61c Mon Sep 17 00:00:00 2001 From: delenius Date: Wed, 18 Jul 2018 19:50:59 -0700 Subject: [PATCH 033/370] Fix version incompatibility in resteasy client (#594) --- libraries/resteasy/pom.mustache | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index 479c22ba75c..f2f7fa53a40 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -247,7 +247,7 @@ com.github.joschi.jackson jackson-datatype-threetenbp - ${jackson-version} + ${threetenbp-version} @@ -261,7 +261,8 @@ UTF-8 1.5.18 3.1.3.Final - 2.6.4 + 2.8.6 + 2.6.4 {{^java8}} 2.9.9 {{/java8}} From 8b333b4045a1ebaab52e1753a8bb00f3108c0dfd Mon Sep 17 00:00:00 2001 From: Marvin Date: Thu, 19 Jul 2018 11:55:01 +0200 Subject: [PATCH 034/370] [Java][RESTEasy] Fixed setting of custom headers (#599) Fixed header generation. Previously the key was used as value parameter. --- libraries/resteasy/ApiClient.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/resteasy/ApiClient.mustache b/libraries/resteasy/ApiClient.mustache index f447d645807..ad1fcc649dd 100644 --- a/libraries/resteasy/ApiClient.mustache +++ b/libraries/resteasy/ApiClient.mustache @@ -638,7 +638,7 @@ public class ApiClient { for (Entry defaultHeaderEnrty: defaultHeaderMap.entrySet()) { if (!headerParams.containsKey(defaultHeaderEnrty.getKey())) { - String value = defaultHeaderEnrty.getKey(); + String value = defaultHeaderEnrty.getValue(); if (value != null) { invocationBuilder = invocationBuilder.header(defaultHeaderEnrty.getKey(), value); } From 7081ce43726fb7317a8a4fd58549bf892f1d8e4c Mon Sep 17 00:00:00 2001 From: William Cheng Date: Thu, 19 Jul 2018 17:57:21 +0800 Subject: [PATCH 035/370] Update gradle dependency for Java RESTEasy API client (#597) * update resteasy gradle dependency * remove java8 option when testing resteasy (java) --- libraries/resteasy/build.gradle.mustache | 7 ++++--- libraries/resteasy/build.sbt.mustache | 18 +++++++++++------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index fc2cd18dbea..ac2cb6fab8e 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -117,8 +117,9 @@ if(hasProperty('target') && target == 'android') { } ext { - swagger_annotations_version = "1.5.8" - jackson_version = "2.6.4" + swagger_annotations_version = "1.5.18" + jackson_version = "2.8.6" + threetenbp_version = "2.6.4" jersey_version = "2.22.2" resteasy_version = "3.1.3.Final" {{^java8}} @@ -142,7 +143,7 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_version" + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$threetenbp_version" {{#java8}} compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} diff --git a/libraries/resteasy/build.sbt.mustache b/libraries/resteasy/build.sbt.mustache index 348d29d96d1..cdfc4f848fd 100644 --- a/libraries/resteasy/build.sbt.mustache +++ b/libraries/resteasy/build.sbt.mustache @@ -9,17 +9,21 @@ lazy val root = (project in file(".")). publishArtifact in (Compile, packageDoc) := false, resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( - "io.swagger" % "swagger-annotations" % "1.5.8", + "io.swagger" % "swagger-annotations" % "1.5.18", "org.glassfish.jersey.core" % "jersey-client" % "2.22.2", "org.glassfish.jersey.media" % "jersey-media-multipart" % "2.22.2", "org.glassfish.jersey.media" % "jersey-media-json-jackson" % "2.22.2", - "com.fasterxml.jackson.core" % "jackson-core" % "2.7.5", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.7.5", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.7.5", + "org.jboss.resteasy" % "resteasy-client" % "3.1.3.Final", + "org.jboss.resteasy" % "resteasy-multipart-provider" % "3.1.3.Final", + "org.jboss.resteasy" % "resteasy-jackson2-provider" % "3.1.3.Final", + "com.fasterxml.jackson.core" % "jackson-core" % "2.8.6", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.6", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.6", + "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4", {{#java8}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.7.5", - {{/java8}} - {{^java8}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.8.6", + {{/java8}} + {{^java8}} "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.7.5", "joda-time" % "joda-time" % "2.9.4", "com.brsanthu" % "migbase64" % "2.2", From ecc8c7e643eb4383b2fa4dfdd860655460ee9bd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Mart=C3=ADnez?= Date: Fri, 20 Jul 2018 17:49:12 +0200 Subject: [PATCH 036/370] [Java][Client][RestTemplate] Do not create new Object for empty body (#605) #513 Fixed error that causes exception when trying to perform HTTP requests without a body and an empty Object is used as body instead. In these cases an exception is thrown indicating that it is not possible to find a message converter for java.lang.Object and application/json. --- libraries/resttemplate/api.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/resttemplate/api.mustache b/libraries/resttemplate/api.mustache index a906a80e7a8..f48180f4381 100644 --- a/libraries/resttemplate/api.mustache +++ b/libraries/resttemplate/api.mustache @@ -61,7 +61,7 @@ public class {{classname}} { {{/externalDocs}} */ public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { - Object {{localVariablePrefix}}postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}new Object(){{/bodyParam}}; + Object {{localVariablePrefix}}postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { From 7637281aa67bd7d98cae15cd7359d67099e280ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Thu, 26 Jul 2018 11:00:45 +0200 Subject: [PATCH 037/370] [java] add useNullForUnknownEnumValue option (#633) --- modelEnum.mustache | 2 +- modelInnerEnum.mustache | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modelEnum.mustache b/modelEnum.mustache index 209d310172b..6dd5334b771 100644 --- a/modelEnum.mustache +++ b/modelEnum.mustache @@ -48,7 +48,7 @@ public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum return b; } } - return null; + {{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + text + "'");{{/useNullForUnknownEnumValue}} } {{#gson}} diff --git a/modelInnerEnum.mustache b/modelInnerEnum.mustache index bcd6908950a..aef0f27b89a 100644 --- a/modelInnerEnum.mustache +++ b/modelInnerEnum.mustache @@ -39,7 +39,7 @@ return b; } } - return null; + {{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + text + "'");{{/useNullForUnknownEnumValue}} } {{#gson}} From aec7d4411326f5d7789860246665279b35845725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Mart=C3=ADnez?= Date: Mon, 30 Jul 2018 08:38:10 +0200 Subject: [PATCH 038/370] [Java][Client][RestTemplate] Fixed invalid URL-encoding of query parameters (#646) Fix for the #644 --- libraries/resttemplate/ApiClient.mustache | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libraries/resttemplate/ApiClient.mustache b/libraries/resttemplate/ApiClient.mustache index 471a936ad57..11a042ab347 100644 --- a/libraries/resttemplate/ApiClient.mustache +++ b/libraries/resttemplate/ApiClient.mustache @@ -46,6 +46,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.text.DateFormat; @@ -542,8 +544,15 @@ public class ApiClient { } builder.queryParams(queryParams); } + + URI uri; + try { + uri = new URI(builder.build().toUriString()); + } catch(URISyntaxException ex) { + throw new RestClientException("Could not build URL: " + builder.toUriString(), ex); + } - final BodyBuilder requestBuilder = RequestEntity.method(method, builder.build().toUri()); + final BodyBuilder requestBuilder = RequestEntity.method(method, uri); if(accept != null) { requestBuilder.accept(accept.toArray(new MediaType[accept.size()])); } From b1c695d41fd1822273315bfdcdc215efc0ba0b46 Mon Sep 17 00:00:00 2001 From: Victor Orlovsky Date: Wed, 1 Aug 2018 07:02:11 +0300 Subject: [PATCH 039/370] Added constant "httpMethod", "summary" (#697) --- libraries/rest-assured/api.mustache | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/libraries/rest-assured/api.mustache b/libraries/rest-assured/api.mustache index 0263f6cf323..00c0fe7c03c 100644 --- a/libraries/rest-assured/api.mustache +++ b/libraries/rest-assured/api.mustache @@ -70,7 +70,7 @@ public class {{classname}} { * @see #{{#isPathParam}}{{paramName}}Path{{/isPathParam}}{{#isQueryParam}}{{paramName}}Query{{/isQueryParam}}{{#isFormParam}}{{^isFile}}{{paramName}}Form{{/isFile}}{{#isFile}}{{paramName}}MultiPart{{/isFile}}{{/isFormParam}}{{#isHeaderParam}}{{paramName}}Header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} {{#returnType}} - * return {{returnType}} + * return {{{returnType}}} {{/returnType}} {{#isDeprecated}} * @deprecated @@ -85,7 +85,9 @@ public class {{classname}} { {{/isDeprecated}} public class {{operationIdCamelCase}}Oper { + public static final String REQ_METHOD = "{{httpMethod}}"; public static final String REQ_URI = "{{path}}"; + public static final String SUMMARY = "{{{summary}}}"; private RequestSpecBuilder reqSpec; @@ -131,7 +133,7 @@ public class {{classname}} { /** * {{httpMethod}} {{path}} * @param handler handler - * @return {{returnType}} + * @return {{{returnType}}} */ public {{{returnType}}} executeAs(Function handler) { Type type = new TypeToken<{{{returnType}}}>(){}.getType(); @@ -141,7 +143,7 @@ public class {{classname}} { {{#bodyParams}} /** - * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} * @return operation */ public {{operationIdCamelCase}}Oper body({{{dataType}}} {{paramName}}) { @@ -154,7 +156,7 @@ public class {{classname}} { public static final String {{#convert}}{{paramName}}{{/convert}}_HEADER = "{{baseName}}"; /** - * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} * @return operation */ public {{operationIdCamelCase}}Oper {{paramName}}Header(String {{paramName}}) { @@ -167,7 +169,7 @@ public class {{classname}} { public static final String {{#convert}}{{paramName}}{{/convert}}_PATH = "{{baseName}}"; /** - * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} * @return operation */ public {{operationIdCamelCase}}Oper {{paramName}}Path(Object {{paramName}}) { @@ -180,7 +182,7 @@ public class {{classname}} { public static final String {{#convert}}{{paramName}}{{/convert}}_QUERY = "{{baseName}}"; /** - * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} * @return operation */ public {{operationIdCamelCase}}Oper {{paramName}}Query(Object... {{paramName}}) { @@ -194,7 +196,7 @@ public class {{classname}} { public static final String {{#convert}}{{paramName}}{{/convert}}_FORM = "{{baseName}}"; /** - * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} * @return operation */ public {{operationIdCamelCase}}Oper {{paramName}}Form(Object... {{paramName}}) { @@ -209,7 +211,7 @@ public class {{classname}} { /** * It will assume that the control name is file and the <content-type> is <application/octet-stream> * @see #reqSpec for customise - * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} * @return operation */ public {{operationIdCamelCase}}Oper {{paramName}}MultiPart({{{dataType}}} {{paramName}}) { From deaa3a56bad67014a22b37a497f0d21acca3aace Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 1 Aug 2018 22:13:41 +0800 Subject: [PATCH 040/370] Fix Javadoc string error in Java (rest-assured) client (#702) * fix docstring * trigger build failure * Revert "trigger build failure" This reverts commit 12cd26f0ca981db37d177a55001dac8b6afcd0bf. * update java samples --- libraries/rest-assured/api.mustache | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/rest-assured/api.mustache b/libraries/rest-assured/api.mustache index 00c0fe7c03c..3a0d2c78d9f 100644 --- a/libraries/rest-assured/api.mustache +++ b/libraries/rest-assured/api.mustache @@ -70,7 +70,7 @@ public class {{classname}} { * @see #{{#isPathParam}}{{paramName}}Path{{/isPathParam}}{{#isQueryParam}}{{paramName}}Query{{/isQueryParam}}{{#isFormParam}}{{^isFile}}{{paramName}}Form{{/isFile}}{{#isFile}}{{paramName}}MultiPart{{/isFile}}{{/isFormParam}}{{#isHeaderParam}}{{paramName}}Header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} {{#returnType}} - * return {{{returnType}}} + * return {{returnType}} {{/returnType}} {{#isDeprecated}} * @deprecated @@ -133,7 +133,7 @@ public class {{classname}} { /** * {{httpMethod}} {{path}} * @param handler handler - * @return {{{returnType}}} + * @return {{returnType}} */ public {{{returnType}}} executeAs(Function handler) { Type type = new TypeToken<{{{returnType}}}>(){}.getType(); @@ -243,4 +243,4 @@ public class {{classname}} { } {{/operation}} {{/operations}} -} \ No newline at end of file +} From bbb286add00c0fe3cad39ee70ae96c4fd947e169 Mon Sep 17 00:00:00 2001 From: Victor Orlovsky Date: Wed, 15 Aug 2018 18:56:14 +0300 Subject: [PATCH 041/370] [JAVA][Rest-assured] add more information about operations (#815) Add swagger annotations to client and set default baseReqSpec and baseContextConsumer in ApiClient --- libraries/rest-assured/ApiClient.mustache | 20 +++++++------- libraries/rest-assured/api.mustache | 32 ++++++++++------------- 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/libraries/rest-assured/ApiClient.mustache b/libraries/rest-assured/ApiClient.mustache index 184dc13e05c..cf8d5c45ba2 100644 --- a/libraries/rest-assured/ApiClient.mustache +++ b/libraries/rest-assured/ApiClient.mustache @@ -6,22 +6,20 @@ import {{apiPackage}}.*; {{#imports}}import {{import}}; {{/imports}} - {{^fullJavaUtil}} -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import io.restassured.RestAssured; import io.restassured.builder.RequestSpecBuilder; -import io.restassured.builder.ResponseSpecBuilder; -import io.restassured.response.Response; import java.util.function.Consumer; -import java.util.function.Function; import java.util.function.Supplier; + +import static io.restassured.config.ObjectMapperConfig.objectMapperConfig; +import static io.restassured.config.RestAssuredConfig.config; +import static org.openapitools.client.GsonObjectMapper.gson; {{/fullJavaUtil}} public class ApiClient { + {{#basePath}} + public static final String BASE_URI = "{{basePath}}"; + {{/basePath}} private final Config config; @@ -42,7 +40,9 @@ public class ApiClient { {{/apiInfo}} public static class Config { - private Supplier baseReqSpec; + private Supplier baseReqSpec = () -> new RequestSpecBuilder() + {{#basePath}}.setBaseUri(BASE_URI){{/basePath}} + .setConfig(config().objectMapperConfig(objectMapperConfig().defaultObjectMapper(gson()))); /** * Use common specification for all operations diff --git a/libraries/rest-assured/api.mustache b/libraries/rest-assured/api.mustache index 3a0d2c78d9f..1f400d0efa1 100644 --- a/libraries/rest-assured/api.mustache +++ b/libraries/rest-assured/api.mustache @@ -15,7 +15,9 @@ import java.util.Map; import io.restassured.RestAssured; import io.restassured.builder.RequestSpecBuilder; import io.restassured.builder.ResponseSpecBuilder; +import io.restassured.http.Method; import io.restassured.response.Response; +import io.swagger.annotations.*; import java.lang.reflect.Type; import java.util.function.Consumer; @@ -41,6 +43,15 @@ public class {{classname}} { {{#operations}} {{#operation}} + @ApiOperation(value = "{{{summary}}}", notes = "{{{notes}}}"{{#hasAuthMethods}}, authorizations = { + {{#authMethods}}@Authorization(value = "{{name}}"{{#isOAuth}}, scopes = { + {{#scopes}}@AuthorizationScope(scope = "{{scope}}", description = "{{description}}"){{#hasMore}}, + {{/hasMore}}{{/scopes}} + }{{/isOAuth}}){{#hasMore}}, + {{/hasMore}}{{/authMethods}} + }{{/hasAuthMethods}}, tags={ {{#tags}}{{#name}}"{{{name}}}"{{/name}}{{^-last}}, {{/-last}}{{/tags}} }) + @ApiResponses(value = { {{#responses}} + @ApiResponse(code = {{{code}}}, message = "{{{message}}}") {{#hasMore}},{{/hasMore}}{{/responses}} }) {{#isDeprecated}} @Deprecated {{/isDeprecated}} @@ -83,29 +94,14 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public class {{operationIdCamelCase}}Oper { + public static class {{operationIdCamelCase}}Oper { - public static final String REQ_METHOD = "{{httpMethod}}"; + public static final Method REQ_METHOD = {{httpMethod}}; public static final String REQ_URI = "{{path}}"; - public static final String SUMMARY = "{{{summary}}}"; private RequestSpecBuilder reqSpec; - private ResponseSpecBuilder respSpec; - public {{operationIdCamelCase}}Oper() { - this.reqSpec = new RequestSpecBuilder(); - {{#vendorExtensions}} - {{#x-contentType}} - reqSpec.setContentType("{{x-contentType}}"); - {{/x-contentType}} - {{#x-accepts}} - reqSpec.setAccept("{{x-accepts}}"); - {{/x-accepts}} - {{/vendorExtensions}} - this.respSpec = new ResponseSpecBuilder(); - } - public {{operationIdCamelCase}}Oper(RequestSpecBuilder reqSpec) { this.reqSpec = reqSpec; {{#vendorExtensions}} @@ -126,7 +122,7 @@ public class {{classname}} { * @return type */ public T execute(Function handler) { - return handler.apply(RestAssured.given().spec(reqSpec.build()).expect().spec(respSpec.build()).when().request({{httpMethod}}, REQ_URI)); + return handler.apply(RestAssured.given().spec(reqSpec.build()).expect().spec(respSpec.build()).when().request(REQ_METHOD, REQ_URI)); } {{#returnType}} From 34ae5ff04e89a264a4786d6ef6e9769ba86cccbe Mon Sep 17 00:00:00 2001 From: Victor Orlovsky Date: Thu, 16 Aug 2018 07:15:15 +0300 Subject: [PATCH 042/370] [Java][Rest-assured] Fix "invokerPackage" in ApiClient, remove unnecessary @Authorization (#822) --- libraries/rest-assured/ApiClient.mustache | 2 +- libraries/rest-assured/api.mustache | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/libraries/rest-assured/ApiClient.mustache b/libraries/rest-assured/ApiClient.mustache index cf8d5c45ba2..42bdf68613b 100644 --- a/libraries/rest-assured/ApiClient.mustache +++ b/libraries/rest-assured/ApiClient.mustache @@ -13,7 +13,7 @@ import java.util.function.Supplier; import static io.restassured.config.ObjectMapperConfig.objectMapperConfig; import static io.restassured.config.RestAssuredConfig.config; -import static org.openapitools.client.GsonObjectMapper.gson; +import static {{invokerPackage}}.GsonObjectMapper.gson; {{/fullJavaUtil}} public class ApiClient { diff --git a/libraries/rest-assured/api.mustache b/libraries/rest-assured/api.mustache index 1f400d0efa1..f536ddf9b49 100644 --- a/libraries/rest-assured/api.mustache +++ b/libraries/rest-assured/api.mustache @@ -43,13 +43,9 @@ public class {{classname}} { {{#operations}} {{#operation}} - @ApiOperation(value = "{{{summary}}}", notes = "{{{notes}}}"{{#hasAuthMethods}}, authorizations = { - {{#authMethods}}@Authorization(value = "{{name}}"{{#isOAuth}}, scopes = { - {{#scopes}}@AuthorizationScope(scope = "{{scope}}", description = "{{description}}"){{#hasMore}}, - {{/hasMore}}{{/scopes}} - }{{/isOAuth}}){{#hasMore}}, - {{/hasMore}}{{/authMethods}} - }{{/hasAuthMethods}}, tags={ {{#tags}}{{#name}}"{{{name}}}"{{/name}}{{^-last}}, {{/-last}}{{/tags}} }) + @ApiOperation(value = "{{{summary}}}", + notes = "{{{notes}}}", + tags={ {{#tags}}{{#name}}"{{{name}}}"{{/name}}{{^-last}}, {{/-last}}{{/tags}} }) @ApiResponses(value = { {{#responses}} @ApiResponse(code = {{{code}}}, message = "{{{message}}}") {{#hasMore}},{{/hasMore}}{{/responses}} }) {{#isDeprecated}} From 461e4d4ec7d9f01e50accdc221b60adede202776 Mon Sep 17 00:00:00 2001 From: Victor Orlovsky Date: Fri, 17 Aug 2018 19:15:02 +0300 Subject: [PATCH 043/370] [Java][Rest-assured] Fix generated javadoc and "swagger-annotations" improvement (#831) Added "@Api" swagger annotation, "nickname" for ApiOperation. Fixed javadock for rest-assured client. --- libraries/rest-assured/api.mustache | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/libraries/rest-assured/api.mustache b/libraries/rest-assured/api.mustache index f536ddf9b49..75c3a373ae3 100644 --- a/libraries/rest-assured/api.mustache +++ b/libraries/rest-assured/api.mustache @@ -28,6 +28,7 @@ import {{invokerPackage}}.JSON; import static io.restassured.http.Method.*; +@Api(value = "{{{baseName}}}") public class {{classname}} { private RequestSpecBuilder reqSpec; @@ -44,10 +45,11 @@ public class {{classname}} { {{#operation}} @ApiOperation(value = "{{{summary}}}", - notes = "{{{notes}}}", - tags={ {{#tags}}{{#name}}"{{{name}}}"{{/name}}{{^-last}}, {{/-last}}{{/tags}} }) + notes = "{{{notes}}}", + nickname = "{{{operationId}}}", + tags = { {{#tags}}{{#name}}"{{{name}}}"{{/name}}{{^-last}}, {{/-last}}{{/tags}} }) @ApiResponses(value = { {{#responses}} - @ApiResponse(code = {{{code}}}, message = "{{{message}}}") {{#hasMore}},{{/hasMore}}{{/responses}} }) + @ApiResponse(code = {{{code}}}, message = "{{{message}}}") {{#hasMore}},{{/hasMore}}{{/responses}} }) {{#isDeprecated}} @Deprecated {{/isDeprecated}} @@ -135,7 +137,7 @@ public class {{classname}} { {{#bodyParams}} /** - * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} * @return operation */ public {{operationIdCamelCase}}Oper body({{{dataType}}} {{paramName}}) { @@ -148,7 +150,7 @@ public class {{classname}} { public static final String {{#convert}}{{paramName}}{{/convert}}_HEADER = "{{baseName}}"; /** - * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} * @return operation */ public {{operationIdCamelCase}}Oper {{paramName}}Header(String {{paramName}}) { @@ -161,7 +163,7 @@ public class {{classname}} { public static final String {{#convert}}{{paramName}}{{/convert}}_PATH = "{{baseName}}"; /** - * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} * @return operation */ public {{operationIdCamelCase}}Oper {{paramName}}Path(Object {{paramName}}) { @@ -174,7 +176,7 @@ public class {{classname}} { public static final String {{#convert}}{{paramName}}{{/convert}}_QUERY = "{{baseName}}"; /** - * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} * @return operation */ public {{operationIdCamelCase}}Oper {{paramName}}Query(Object... {{paramName}}) { @@ -188,7 +190,7 @@ public class {{classname}} { public static final String {{#convert}}{{paramName}}{{/convert}}_FORM = "{{baseName}}"; /** - * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} * @return operation */ public {{operationIdCamelCase}}Oper {{paramName}}Form(Object... {{paramName}}) { @@ -203,7 +205,7 @@ public class {{classname}} { /** * It will assume that the control name is file and the <content-type> is <application/octet-stream> * @see #reqSpec for customise - * @param {{paramName}} ({{{dataType}}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + * @param {{paramName}} ({{dataType}}) {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} * @return operation */ public {{operationIdCamelCase}}Oper {{paramName}}MultiPart({{{dataType}}} {{paramName}}) { From d42c964cfba9ff183202079f1979c529c09d260a Mon Sep 17 00:00:00 2001 From: ccozzolino Date: Tue, 21 Aug 2018 00:12:18 -0500 Subject: [PATCH 044/370] Adjust client response handler to be backwards compatible with older versions of Vert.x (<3.5) (#854) --- libraries/vertx/ApiClient.mustache | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libraries/vertx/ApiClient.mustache b/libraries/vertx/ApiClient.mustache index fb80f0d2dba..3bcf3ede667 100644 --- a/libraries/vertx/ApiClient.mustache +++ b/libraries/vertx/ApiClient.mustache @@ -18,6 +18,7 @@ import io.vertx.core.file.FileSystem; import io.vertx.core.file.OpenOptions; import io.vertx.core.http.HttpHeaders; import io.vertx.core.http.HttpMethod; +import io.vertx.core.json.DecodeException; import io.vertx.core.json.Json; import io.vertx.core.json.JsonObject; import io.vertx.ext.web.client.HttpRequest; @@ -553,7 +554,11 @@ public class ApiClient { handleFileDownload(httpResponse, handler); return; } else { - resultContent = Json.decodeValue(httpResponse.body(), returnType); + try { + resultContent = Json.mapper.readValue(httpResponse.bodyAsString(), returnType); + } catch (Exception e) { + throw new DecodeException("Failed to decode:" + e.getMessage(), e); + } } result = Future.succeededFuture(resultContent); } @@ -597,4 +602,4 @@ public class ApiClient { auth.applyToParams(queryParams, headerParams); } } -} \ No newline at end of file +} From 2e171840acb66a9d4db5ce9b6efacea39371914d Mon Sep 17 00:00:00 2001 From: Jens Oberender Date: Wed, 22 Aug 2018 06:06:01 +0200 Subject: [PATCH 045/370] Forbiddenapis check and fix (#672) * Added forbiddenapis check and fixed the findings in the normal code * Fixed forbiddenapi findings in java templates and samples. * Generated all samples for Java. --- JSON.mustache | 7 ++++--- libraries/resteasy/ApiClient.mustache | 5 +++-- libraries/resttemplate/api.mustache | 3 ++- libraries/retrofit2/JSON.mustache | 7 ++++--- libraries/webclient/api.mustache | 3 ++- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/JSON.mustache b/JSON.mustache index 92fa0f9d0fa..ae8de32fafc 100644 --- a/JSON.mustache +++ b/JSON.mustache @@ -40,6 +40,7 @@ import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; {{/java8}} import java.util.Date; +import java.util.Locale; import java.util.Map; import java.util.HashMap; @@ -65,9 +66,9 @@ public class JSON { public Class getClassForElement(JsonElement readElement) { Map classByDiscriminatorValue = new HashMap(); {{#mappedModels}} - classByDiscriminatorValue.put("{{mappingName}}".toUpperCase(), {{modelName}}.class); + classByDiscriminatorValue.put("{{mappingName}}".toUpperCase(Locale.ROOT), {{modelName}}.class); {{/mappedModels}} - classByDiscriminatorValue.put("{{classname}}".toUpperCase(), {{classname}}.class); + classByDiscriminatorValue.put("{{classname}}".toUpperCase(Locale.ROOT), {{classname}}.class); return getClassByDiscriminator( classByDiscriminatorValue, getDiscriminatorValue(readElement, "{{{propertyName}}}")); @@ -91,7 +92,7 @@ public class JSON { } private static Class getClassByDiscriminator(Map classByDiscriminatorValue, String discriminatorValue) { - Class clazz = (Class) classByDiscriminatorValue.get(discriminatorValue.toUpperCase()); + Class clazz = (Class) classByDiscriminatorValue.get(discriminatorValue.toUpperCase(Locale.ROOT)); if(null == clazz) { throw new IllegalArgumentException("cannot determine model class of name: <" + discriminatorValue + ">"); } diff --git a/libraries/resteasy/ApiClient.mustache b/libraries/resteasy/ApiClient.mustache index ad1fcc649dd..96ff0f77653 100644 --- a/libraries/resteasy/ApiClient.mustache +++ b/libraries/resteasy/ApiClient.mustache @@ -16,6 +16,7 @@ import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.TimeZone; @@ -64,7 +65,7 @@ public class ApiClient { json = new JSON(); httpClient = buildHttpClient(debugging); - this.dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + this.dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ROOT); // Use UTC as the default time zone. this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); @@ -477,7 +478,7 @@ public class ApiClient { public Entity serialize(Object obj, Map formParams, String contentType) throws ApiException { Entity entity = null; if (contentType.startsWith("multipart/form-data")) { - MultipartFormDataOutput multipart = new MultipartFormDataOutput(); + MultipartFormDataOutput multipart = new MultipartFormDataOutput(); //MultiPart multiPart = new MultiPart(); for (Entry param: formParams.entrySet()) { if (param.getValue() instanceof File) { diff --git a/libraries/resttemplate/api.mustache b/libraries/resttemplate/api.mustache index f48180f4381..beede4b55b1 100644 --- a/libraries/resttemplate/api.mustache +++ b/libraries/resttemplate/api.mustache @@ -8,6 +8,7 @@ import {{invokerPackage}}.ApiClient; {{^fullJavaUtil}}import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map;{{/fullJavaUtil}} import org.springframework.beans.factory.annotation.Autowired; @@ -77,7 +78,7 @@ public class {{classname}} { final HttpHeaders {{localVariablePrefix}}headerParams = new HttpHeaders(); final MultiValueMap {{localVariablePrefix}}formParams = new LinkedMultiValueMap();{{#hasQueryParams}} - {{#queryParams}}{{localVariablePrefix}}queryParams.putAll({{localVariablePrefix}}apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase()){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{#hasMore}} + {{#queryParams}}{{localVariablePrefix}}queryParams.putAll({{localVariablePrefix}}apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{#hasMore}} {{/hasMore}}{{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}} {{#headerParams}}if ({{paramName}} != null) diff --git a/libraries/retrofit2/JSON.mustache b/libraries/retrofit2/JSON.mustache index ac8958824cb..7dbb56a3da1 100644 --- a/libraries/retrofit2/JSON.mustache +++ b/libraries/retrofit2/JSON.mustache @@ -39,6 +39,7 @@ import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; {{/java8}} import java.util.Date; +import java.util.Locale; import java.util.Map; import java.util.HashMap; @@ -62,9 +63,9 @@ public class JSON { public Class getClassForElement(JsonElement readElement) { Map classByDiscriminatorValue = new HashMap(); {{#mappedModels}} - classByDiscriminatorValue.put("{{mappingName}}".toUpperCase(), {{modelName}}.class); + classByDiscriminatorValue.put("{{mappingName}}".toUpperCase(Locale.ROOT), {{modelName}}.class); {{/mappedModels}} - classByDiscriminatorValue.put("{{classname}}".toUpperCase(), {{classname}}.class); + classByDiscriminatorValue.put("{{classname}}".toUpperCase(Locale.ROOT), {{classname}}.class); return getClassByDiscriminator( classByDiscriminatorValue, getDiscriminatorValue(readElement, "{{{propertyName}}}")); @@ -84,7 +85,7 @@ public class JSON { } private static Class getClassByDiscriminator(Map classByDiscriminatorValue, String discriminatorValue) { - Class clazz = (Class) classByDiscriminatorValue.get(discriminatorValue.toUpperCase()); + Class clazz = (Class) classByDiscriminatorValue.get(discriminatorValue.toUpperCase(Locale.ROOT)); if(null == clazz) { throw new IllegalArgumentException("cannot determine model class of name: <" + discriminatorValue + ">"); } diff --git a/libraries/webclient/api.mustache b/libraries/webclient/api.mustache index 6d6a38e25c0..9c3f9fb140c 100644 --- a/libraries/webclient/api.mustache +++ b/libraries/webclient/api.mustache @@ -8,6 +8,7 @@ import {{invokerPackage}}.ApiClient; {{^fullJavaUtil}}import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map;{{/fullJavaUtil}} import org.springframework.beans.factory.annotation.Autowired; @@ -77,7 +78,7 @@ public class {{classname}} { final HttpHeaders {{localVariablePrefix}}headerParams = new HttpHeaders(); final MultiValueMap {{localVariablePrefix}}formParams = new LinkedMultiValueMap();{{#hasQueryParams}} - {{#queryParams}}{{localVariablePrefix}}queryParams.putAll({{localVariablePrefix}}apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase()){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{#hasMore}} + {{#queryParams}}{{localVariablePrefix}}queryParams.putAll({{localVariablePrefix}}apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{#hasMore}} {{/hasMore}}{{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}} {{#headerParams}}if ({{paramName}} != null) From 5ff35916b7a408a191770000ccc5738b7ed572b4 Mon Sep 17 00:00:00 2001 From: Marco Date: Sat, 25 Aug 2018 14:22:16 +0200 Subject: [PATCH 046/370] [Java][Webclient] Init authentication on ApiClient instantiation (#887) --- libraries/webclient/ApiClient.mustache | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index 28260368a9b..fe3c172a629 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -88,6 +88,8 @@ public class ApiClient { public ApiClient() { this.dateFormat = createDefaultDateFormat(); this.webClient = buildWebClient(new ObjectMapper(), this.dateFormat); + + init(); } public ApiClient(ObjectMapper mapper, DateFormat format) { @@ -97,6 +99,8 @@ public class ApiClient { private ApiClient(WebClient webClient, DateFormat format) { this.webClient = webClient; this.dateFormat = format; + + init(); } public DateFormat createDefaultDateFormat() { From d460384ea4d8fb48d28718e77a84513250df0356 Mon Sep 17 00:00:00 2001 From: Hugo Barrigas Date: Sat, 25 Aug 2018 14:22:36 +0100 Subject: [PATCH 047/370] [JAVA][Webclient] Add constructor to allow custom WebClient to be passed into ApiClient (#882) * add constructor to allow custom webclient to be passed into ApiClient --- libraries/webclient/ApiClient.mustache | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index fe3c172a629..41b81a004c5 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -33,6 +33,7 @@ import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.ExchangeStrategies; import reactor.core.publisher.Mono; import reactor.core.publisher.Flux; +import java.util.Optional; import java.io.BufferedReader; import java.io.IOException; @@ -76,7 +77,7 @@ public class ApiClient { } private HttpHeaders defaultHeaders = new HttpHeaders(); - + private String basePath = "{{basePath}}"; private final WebClient webClient; @@ -87,20 +88,22 @@ public class ApiClient { public ApiClient() { this.dateFormat = createDefaultDateFormat(); - this.webClient = buildWebClient(new ObjectMapper(), this.dateFormat); - - init(); + this.webClient = buildWebClient(new ObjectMapper(), dateFormat); + this.init(); } public ApiClient(ObjectMapper mapper, DateFormat format) { this(buildWebClient(mapper.copy(), format), format); } + public ApiClient(WebClient webClient, ObjectMapper mapper, DateFormat format) { + this(Optional.ofNullable(webClient).orElseGet(() ->buildWebClient(mapper.copy(), format)), format); + } + private ApiClient(WebClient webClient, DateFormat format) { this.webClient = webClient; this.dateFormat = format; - - init(); + this.init(); } public DateFormat createDefaultDateFormat() { @@ -108,7 +111,7 @@ public class ApiClient { dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); return dateFormat; } - + protected void init() { // Setup authentications (key: authentication name, value: authentication). authentications = new HashMap();{{#authMethods}}{{#isBasic}} @@ -136,7 +139,7 @@ public class ApiClient { return webClient.build(); } - + /** * Get the current base path * @return String the base path @@ -589,7 +592,7 @@ public class ApiClient { auth.applyToParams(queryParams, headerParams); } } - + private class ApiClientHttpRequestInterceptor implements ClientHttpRequestInterceptor { private final Log log = LogFactory.getLog(ApiClientHttpRequestInterceptor.class); @@ -628,7 +631,7 @@ public class ApiClient { builder.setLength(builder.length() - 1); // Get rid of trailing comma return builder.toString(); } - + private String bodyToString(InputStream body) throws IOException { StringBuilder builder = new StringBuilder(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(body, StandardCharsets.UTF_8)); From 84514205d7a72c56170f616b0a88b3e74b02a338 Mon Sep 17 00:00:00 2001 From: lukoyanov Date: Tue, 28 Aug 2018 17:48:05 +0300 Subject: [PATCH 048/370] [Java] Retrofit2 Play! Framework 2.6.x support (#901) * added play framework 2.6 support * generated petstore sample * generated petstore sample #2 * generated petstore sample #3 * Revert "generated petstore sample #3" * generated petstore sample #4 * fixed circleci configs * one more time samples regen --- libraries/retrofit2/build.gradle.mustache | 10 + libraries/retrofit2/build.sbt.mustache | 7 + libraries/retrofit2/play26/ApiClient.mustache | 205 +++++++++++++++ .../play26/Play26CallAdapterFactory.mustache | 116 +++++++++ .../play26/Play26CallFactory.mustache | 245 ++++++++++++++++++ libraries/retrofit2/play26/api.mustache | 59 +++++ libraries/retrofit2/pom.mustache | 27 ++ 7 files changed, 669 insertions(+) create mode 100644 libraries/retrofit2/play26/ApiClient.mustache create mode 100644 libraries/retrofit2/play26/Play26CallAdapterFactory.mustache create mode 100644 libraries/retrofit2/play26/Play26CallFactory.mustache create mode 100644 libraries/retrofit2/play26/api.mustache diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index 858b88971b2..cd9baeb50d3 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -129,6 +129,10 @@ ext { jackson_version = "2.7.8" play_version = "2.5.14" {{/play25}} + {{#play26}} + jackson_version = "2.8.10" + play_version = "2.6.7" + {{/play26}} {{/usePlayWS}} swagger_annotations_version = "1.5.17" junit_version = "4.12" @@ -171,7 +175,13 @@ dependencies { compile "org.threeten:threetenbp:$threetenbp_version" {{/threetenbp}} {{#usePlayWS}} + {{#play26}} + compile "com.typesafe.play:play-ahc-ws_2.12:$play_version" + compile "javax.validation:validation-api:1.1.0.Final" + {{/play26}} + {{^play26}} compile "com.typesafe.play:play-java-ws_2.11:$play_version" + {{/play26}} compile "com.squareup.retrofit2:converter-jackson:$retrofit_version" compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" diff --git a/libraries/retrofit2/build.sbt.mustache b/libraries/retrofit2/build.sbt.mustache index 66635daa973..b08e715a7bd 100644 --- a/libraries/retrofit2/build.sbt.mustache +++ b/libraries/retrofit2/build.sbt.mustache @@ -27,6 +27,13 @@ lazy val root = (project in file(".")). "com.fasterxml.jackson.core" % "jackson-annotations" % "2.7.8" % "compile", "com.fasterxml.jackson.core" % "jackson-databind" % "2.7.8" % "compile", {{/play25}} + {{#play26}} + "com.typesafe.play" % "play-ahc-ws_2.12" % "2.6.7" % "compile", + "javax.validation" % "validation-api" % "1.1.0.Final" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.8.10" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.10" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.10" % "compile", + {{/play26}} "com.squareup.retrofit2" % "converter-jackson" % "2.3.0" % "compile", {{/usePlayWS}} {{#useRxJava}} diff --git a/libraries/retrofit2/play26/ApiClient.mustache b/libraries/retrofit2/play26/ApiClient.mustache new file mode 100644 index 00000000000..d59912773c8 --- /dev/null +++ b/libraries/retrofit2/play26/ApiClient.mustache @@ -0,0 +1,205 @@ +package {{invokerPackage}}; + +import java.io.File; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.*; + +import com.fasterxml.jackson.databind.ObjectMapper; +import retrofit2.Converter; +import retrofit2.Retrofit; +import retrofit2.converter.scalars.ScalarsConverterFactory; +import retrofit2.converter.jackson.JacksonConverterFactory; + +import play.libs.Json; +import play.libs.ws.WSClient; + +import {{invokerPackage}}.Play26CallAdapterFactory; +import {{invokerPackage}}.Play26CallFactory; + +import okhttp3.Interceptor; +import okhttp3.ResponseBody; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.auth.Authentication; + +/** + * API client + */ +public class ApiClient { + + /** Underlying HTTP-client */ + private WSClient wsClient; + + /** Creates HTTP call instances */ + private Play26CallFactory callFactory; + + /** Create {@link java.util.concurrent.CompletionStage} instances from HTTP calls */ + private Play26CallAdapterFactory callAdapterFactory; + + /** Supported auths */ + private Map authentications; + + /** API base path */ + private String basePath = "{{{basePath}}}"; + + /** Default ObjectMapper */ + private ObjectMapper defaultMapper; + + public ApiClient(WSClient wsClient) { + this(); + this.wsClient = wsClient; + } + + public ApiClient() { + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap<>();{{#authMethods}}{{#isBasic}} + // authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + // authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + } + + /** + * Creates a retrofit2 client for given API interface + */ + public S createService(Class serviceClass) { + if(!basePath.endsWith("/")) { + basePath = basePath + "/"; + } + + Map extraHeaders = new HashMap<>(); + List extraQueryParams = new ArrayList<>(); + + for (String authName : authentications.keySet()) { + Authentication auth = authentications.get(authName); + if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + + auth.applyToParams(extraQueryParams, extraHeaders); + } + + if (callFactory == null) { + callFactory = new Play26CallFactory(wsClient, extraHeaders, extraQueryParams); + } + if (callAdapterFactory == null) { + callAdapterFactory = new Play26CallAdapterFactory(); + } + if (defaultMapper == null) { + defaultMapper = Json.mapper(); + } + + return new Retrofit.Builder() + .baseUrl(basePath) + .addConverterFactory(new FileConverter()) + .addConverterFactory(ScalarsConverterFactory.create()) + .addConverterFactory(JacksonConverterFactory.create(defaultMapper)) + .callFactory(callFactory) + .addCallAdapterFactory(callAdapterFactory) + .build() + .create(serviceClass); + } + + /** + * Helper method to set API base path + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Get authentications (key: authentication name, value: authentication). + */ + public Map getAuthentications() { + return authentications; + } + + /** + * Get authentication for the given name. + * + * @param authName The authentication name + * @return The authentication, null if not found + */ + public Authentication getAuthentication(String authName) { + return authentications.get(authName); + } + + /** + * Helper method to set API key value for the first API key authentication. + */ + public ApiClient setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return this; + } + } + + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + */ + public ApiClient setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return this; + } + } + + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set HTTP call instances factory + */ + public ApiClient setCallFactory(Play26CallFactory callFactory) { + this.callFactory = callFactory; + return this; + } + + /** + * Helper method to set {@link java.util.concurrent.CompletionStage} instances factory + */ + public ApiClient setCallAdapterFactory(Play26CallAdapterFactory callAdapterFactory) { + this.callAdapterFactory = callAdapterFactory; + return this; + } + + /** + * Helper method to set Jackson's {@link ObjectMapper} + */ + public ApiClient setObjectMapper(ObjectMapper mapper) { + this.defaultMapper = mapper; + return this; + } + + static class FileConverter extends Converter.Factory { + + @Override + public Converter responseBodyConverter(Type type, + Annotation[] annotations, Retrofit retrofit) { + + if (!File.class.getTypeName().equals(type.getTypeName())) { + return null; + } + + return new Converter() { + + @Override + public File convert(ResponseBody value) throws IOException { + + File file = File.createTempFile("retrofit-file", ".tmp"); + Files.write(Paths.get(file.getPath()), value.bytes()); + return file; + } + }; + } + } + +} diff --git a/libraries/retrofit2/play26/Play26CallAdapterFactory.mustache b/libraries/retrofit2/play26/Play26CallAdapterFactory.mustache new file mode 100644 index 00000000000..efbc0ac298b --- /dev/null +++ b/libraries/retrofit2/play26/Play26CallAdapterFactory.mustache @@ -0,0 +1,116 @@ +package {{invokerPackage}}; + +import java.util.concurrent.CompletionStage; +import retrofit2.*; + +import java.lang.annotation.Annotation; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.WildcardType; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.function.Function; + +/** + * Creates {@link CallAdapter} instances that convert {@link Call} into {@link java.util.concurrent.CompletionStage} + */ +public class Play26CallAdapterFactory extends CallAdapter.Factory { + + private Function exceptionConverter = Function.identity(); + + public Play26CallAdapterFactory() { + } + + public Play26CallAdapterFactory( + Function exceptionConverter) { + this.exceptionConverter = exceptionConverter; + } + + @Override + public CallAdapter get(Type returnType, Annotation[] annotations, Retrofit retrofit) { + if (!(returnType instanceof ParameterizedType)) { + return null; + } + + ParameterizedType type = (ParameterizedType) returnType; + if (type.getRawType() != CompletionStage.class) { + return null; + } + + return createAdapter((ParameterizedType) returnType); + } + + private CallAdapter> createAdapter(ParameterizedType returnType) { + // Get CompletionStage type argument + Type[] types = returnType.getActualTypeArguments(); + if (types.length != 1) { + throw new IllegalStateException("Must be exactly one type parameter"); + } + + Type resultType = types[0]; + Class rawTypeParam = getRawType(resultType); + + boolean includeResponse = false; + if (rawTypeParam == Response.class) { + if (!(resultType instanceof ParameterizedType)) { + throw new IllegalStateException("Response must be parameterized" + + " as Response"); + } + resultType = ((ParameterizedType) resultType).getActualTypeArguments()[0]; + includeResponse = true; + } + + return new ValueAdapter(resultType, includeResponse, exceptionConverter); + } + + /** + * Adpater that coverts values returned by API interface into CompletionStage + */ + private static final class ValueAdapter implements CallAdapter> { + + private final Type responseType; + private final boolean includeResponse; + private Function exceptionConverter; + + ValueAdapter(Type responseType, boolean includeResponse, + Function exceptionConverter) { + this.responseType = responseType; + this.includeResponse = includeResponse; + this.exceptionConverter = exceptionConverter; + } + + @Override + public Type responseType() { + return responseType; + } + + @Override + public CompletionStage adapt(final Call call) { + final CompletableFuture promise = new CompletableFuture(); + + call.enqueue(new Callback() { + + @Override + public void onResponse(Call call, Response response) { + if (response.isSuccessful()) { + if (includeResponse) { + promise.complete((R) response); + } else { + promise.complete(response.body()); + } + } else { + promise.completeExceptionally(exceptionConverter.apply(new HttpException(response))); + } + } + + @Override + public void onFailure(Call call, Throwable t) { + promise.completeExceptionally(t); + } + + }); + + return promise; + } + } +} diff --git a/libraries/retrofit2/play26/Play26CallFactory.mustache b/libraries/retrofit2/play26/Play26CallFactory.mustache new file mode 100644 index 00000000000..6e4180341bf --- /dev/null +++ b/libraries/retrofit2/play26/Play26CallFactory.mustache @@ -0,0 +1,245 @@ +package {{invokerPackage}}; + +import okhttp3.*; +import okio.Buffer; +import okio.BufferedSource; +import play.libs.ws.WSClient; +import play.libs.ws.WSRequest; +import play.libs.ws.WSResponse; +import play.libs.ws.WSRequestFilter; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.Executor; + +/** + * Creates {@link Call} instances that invoke underlying {@link WSClient} + */ +public class Play26CallFactory implements okhttp3.Call.Factory { + + /** PlayWS http client */ + private final WSClient wsClient; + + /** Extra headers to add to request */ + private Map extraHeaders = new HashMap<>(); + + /** Extra query parameters to add to request */ + private List extraQueryParams = new ArrayList<>(); + + /** Filters (interceptors) */ + private List filters = new ArrayList<>(); + + /** Executor for WSClient */ + private Executor executor; + + public Play26CallFactory(WSClient wsClient) { + this.wsClient = wsClient; + } + + public Play26CallFactory(WSClient wsClient, List filters) { + this.wsClient = wsClient; + this.filters.addAll(filters); + } + + public Play26CallFactory(WSClient wsClient, Map extraHeaders, + List extraQueryParams) { + this.wsClient = wsClient; + + this.extraHeaders.putAll(extraHeaders); + this.extraQueryParams.addAll(extraQueryParams); + } + + public Play26CallFactory withExecutor(Executor executor) { + this.executor = executor; + return this; + } + + @Override + public Call newCall(Request request) { + // add extra headers + Request.Builder rb = request.newBuilder(); + for (Map.Entry header : this.extraHeaders.entrySet()) { + rb.addHeader(header.getKey(), header.getValue()); + } + + // add extra query params + if (!this.extraQueryParams.isEmpty()) { + String newQuery = request.url().uri().getQuery(); + for (Pair queryParam : this.extraQueryParams) { + String param = String.format("%s=%s", queryParam.getName(), queryParam.getValue()); + if (newQuery == null) { + newQuery = param; + } else { + newQuery += "&" + param; + } + } + + URI newUri; + try { + newUri = new URI(request.url().uri().getScheme(), request.url().uri().getAuthority(), + request.url().uri().getPath(), newQuery, request.url().uri().getFragment()); + rb.url(newUri.toURL()); + } catch (MalformedURLException | URISyntaxException e) { + throw new RuntimeException("Error while updating an url", e); + } + } + + return new PlayWSCall(wsClient, this.executor, this.filters, rb.build()); + } + + /** + * Call implementation that delegates to Play WS Client + */ + static class PlayWSCall implements Call { + + private final WSClient wsClient; + private WSRequest wsRequest; + private List filters; + private Executor executor = java.util.concurrent.ForkJoinPool.commonPool(); + + private final Request request; + + public PlayWSCall(WSClient wsClient, Executor executor, List filters, Request request) { + this.wsClient = wsClient; + this.request = request; + this.filters = filters; + + if (executor != null) { + this.executor = executor; + } + } + + @Override + public Request request() { + return request; + } + + @Override + public void enqueue(final okhttp3.Callback responseCallback) { + final Call call = this; + final CompletionStage promise = executeAsync(); + + promise.whenCompleteAsync((v, t) -> { + if (t != null) { + if (t instanceof IOException) { + responseCallback.onFailure(call, (IOException) t); + } else { + responseCallback.onFailure(call, new IOException(t)); + } + } else { + try { + responseCallback.onResponse(call, PlayWSCall.this.toWSResponse(v)); + } catch (Exception e) { + responseCallback.onFailure(call, new IOException(e)); + } + } + }, this.executor); + } + + CompletionStage executeAsync() { + try { + HttpUrl url = request.url(); + wsRequest = wsClient.url(url.scheme()+ "://" + url.host() + ":" + url.port() + url.encodedPath()); + url.queryParameterNames().forEach(queryParam -> { + wsRequest.addQueryParameter(queryParam, url.queryParameter(queryParam)); + }); + addHeaders(wsRequest); + if (request.body() != null) { + addBody(wsRequest); + } + filters.stream().forEach(f -> wsRequest.setRequestFilter(f)); + + return wsRequest.execute(request.method()); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + private void addHeaders(WSRequest wsRequest) { + for(Map.Entry> entry : request.headers().toMultimap().entrySet()) { + List values = entry.getValue(); + for (String value : values) { + wsRequest.setHeader(entry.getKey(), value); + } + } + } + + private void addBody(WSRequest wsRequest) throws IOException { + MediaType mediaType = request.body().contentType(); + if (mediaType != null) { + wsRequest.setContentType(mediaType.toString()); + } + + Buffer buffer = new Buffer(); + request.body().writeTo(buffer); + wsRequest.setBody(buffer.inputStream()); + } + + private Response toWSResponse(final WSResponse r) { + final Response.Builder builder = new Response.Builder(); + builder.request(request) + .code(r.getStatus()) + .body(new ResponseBody() { + + @Override + public MediaType contentType() { + return r.getSingleHeader("Content-Type") + .map(MediaType::parse) + .orElse(null); + } + + @Override + public long contentLength() { + return r.asByteArray().length; + } + + @Override + public BufferedSource source() { + return new Buffer().write(r.asByteArray()); + } + }); + + for (Map.Entry> entry : r.getAllHeaders().entrySet()) { + for (String value : entry.getValue()) { + builder.addHeader(entry.getKey(), value); + } + } + + builder.message(r.getStatusText()); + builder.protocol(Protocol.HTTP_1_1); + return builder.build(); + } + + @Override + public Response execute() throws IOException { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public void cancel() { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public PlayWSCall clone() { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public boolean isExecuted() { + return false; + } + + @Override + public boolean isCanceled() { + return false; + } + } +} diff --git a/libraries/retrofit2/play26/api.mustache b/libraries/retrofit2/play26/api.mustache new file mode 100644 index 00000000000..b435a16c051 --- /dev/null +++ b/libraries/retrofit2/play26/api.mustache @@ -0,0 +1,59 @@ +package {{package}}; + +import {{invokerPackage}}.CollectionFormats.*; + +{{#useRxJava}}import rx.Observable;{{/useRxJava}} +{{#useRxJava2}}import io.reactivex.Observable;{{/useRxJava2}} +{{#doNotUseRx}}import retrofit2.Call;{{/doNotUseRx}} +import retrofit2.http.*; + +import okhttp3.RequestBody; +import okhttp3.ResponseBody; +import okhttp3.MultipartBody; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +import java.util.concurrent.*; +import retrofit2.Response; + +{{#operations}} +public interface {{classname}} { + {{#operation}} + /** + * {{summary}} + * {{notes}} +{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} +{{/allParams}} + * @return Call<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + */ + {{#formParams}} + {{#-first}} + {{#isMultipart}}@retrofit2.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit2.http.FormUrlEncoded{{/isMultipart}} + {{/-first}} + {{/formParams}} + {{^formParams}} + {{#prioritizedContentTypes}} + {{#-first}} + @Headers({ + "Content-Type:{{{mediaType}}}" + }) + {{/-first}} + {{/prioritizedContentTypes}} + {{/formParams}} + @{{httpMethod}}("{{{path}}}") + CompletionStage> {{operationId}}({{^allParams}});{{/allParams}} + {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{#hasMore}}, {{/hasMore}}{{^hasMore}} + );{{/hasMore}}{{/allParams}} + + {{/operation}} +} +{{/operations}} diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index f23642e46bb..8518053b809 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -300,11 +300,34 @@ {{/withXml}} + + {{#play24}} + + com.typesafe.play + play-java-ws_2.11 + ${play-version} + + {{/play24}} + {{#play25}} com.typesafe.play play-java-ws_2.11 ${play-version} + {{/play25}} + {{#play26}} + + com.typesafe.play + play-ahc-ws_2.12 + ${play-version} + + + javax.validation + validation-api + 1.1.0.Final + + {{/play26}} + {{/usePlayWS}} {{#parcelableModel}} @@ -341,6 +364,10 @@ 2.7.8 2.5.15 {{/play25}} + {{#play26}} + 2.8.10 + 2.6.7 + {{/play26}} {{/usePlayWS}} 2.3.0 {{#useRxJava}} From 2499409434e6bdead9254d5bb8f5222504bed1f5 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 29 Aug 2018 16:43:41 +0800 Subject: [PATCH 049/370] Update swagger annotation version in Java clients (#915) * update swagger annotation version in java client * add java retrofit2 play 2.6 to java petstore all bin script * remove empty line in pom.xml --- libraries/feign/build.gradle.mustache | 2 +- libraries/feign/build.sbt.mustache | 2 +- libraries/feign/pom.mustache | 12 ++--- .../google-api-client/build.gradle.mustache | 2 +- .../google-api-client/build.sbt.mustache | 2 +- libraries/google-api-client/pom.mustache | 12 ++--- libraries/jersey2/build.gradle.mustache | 2 +- libraries/jersey2/build.sbt.mustache | 2 +- libraries/jersey2/pom.mustache | 10 ++-- libraries/rest-assured/build.gradle.mustache | 2 +- libraries/rest-assured/build.sbt.mustache | 2 +- libraries/rest-assured/pom.mustache | 10 ++-- libraries/resteasy/pom.mustache | 10 ++-- libraries/resttemplate/build.gradle.mustache | 2 +- libraries/resttemplate/pom.mustache | 8 ++- libraries/retrofit/build.gradle.mustache | 2 +- libraries/retrofit/build.sbt.mustache | 2 +- libraries/retrofit/pom.mustache | 26 +++++----- libraries/retrofit2/build.gradle.mustache | 2 +- libraries/retrofit2/build.sbt.mustache | 2 +- libraries/retrofit2/pom.mustache | 49 ++++++++----------- libraries/vertx/build.gradle.mustache | 2 +- libraries/vertx/pom.mustache | 10 ++-- pom.mustache | 8 ++- 24 files changed, 77 insertions(+), 106 deletions(-) diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index 32254e52506..a4e5ea5a791 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -118,7 +118,7 @@ if(hasProperty('target') && target == 'android') { } ext { - swagger_annotations_version = "1.5.9" + swagger_annotations_version = "1.5.21" jackson_version = "2.8.7" {{#threetenbp}} threepane_version = "2.6.4" diff --git a/libraries/feign/build.sbt.mustache b/libraries/feign/build.sbt.mustache index d745ef7e86d..a3dff942003 100644 --- a/libraries/feign/build.sbt.mustache +++ b/libraries/feign/build.sbt.mustache @@ -9,7 +9,7 @@ lazy val root = (project in file(".")). publishArtifact in (Compile, packageDoc) := false, resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( - "io.swagger" % "swagger-annotations" % "1.5.9" % "compile", + "io.swagger" % "swagger-annotations" % "1.5.21" % "compile", "io.github.openfeign" % "feign-core" % "9.4.0" % "compile", "io.github.openfeign" % "feign-jackson" % "9.4.0" % "compile", "io.github.openfeign" % "feign-slf4j" % "9.4.0" % "compile", diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index a616e68bcff..7a81b340af9 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -114,8 +114,7 @@ - - src/main/java + src/main/java @@ -127,8 +126,7 @@ - - src/test/java + src/test/java @@ -191,7 +189,7 @@ io.swagger swagger-annotations - ${swagger-core-version} + ${swagger-annotations-version} @@ -294,12 +292,12 @@ {{#supportJava6}}1.6{{/supportJava6}}{{^supportJava6}}{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}{{/supportJava6}} ${java.version} ${java.version} - 1.5.18 + 1.5.21 9.4.0 2.1.0 2.8.9 {{#threetenbp}} - 2.6.4 + 2.6.4 {{/threetenbp}} 4.12 1.0.0 diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache index 1a2b2afc6cd..acbe24a53f6 100644 --- a/libraries/google-api-client/build.gradle.mustache +++ b/libraries/google-api-client/build.gradle.mustache @@ -118,7 +118,7 @@ if(hasProperty('target') && target == 'android') { } ext { - swagger_annotations_version = "1.5.17" + swagger_annotations_version = "1.5.21" jackson_version = "2.8.9" google_api_client_version = "1.23.0" jersey_common_version = "2.25.1" diff --git a/libraries/google-api-client/build.sbt.mustache b/libraries/google-api-client/build.sbt.mustache index d6b88c91d96..9f1aeaf1570 100644 --- a/libraries/google-api-client/build.sbt.mustache +++ b/libraries/google-api-client/build.sbt.mustache @@ -9,7 +9,7 @@ lazy val root = (project in file(".")). publishArtifact in (Compile, packageDoc) := false, resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( - "io.swagger" % "swagger-annotations" % "1.5.17", + "io.swagger" % "swagger-annotations" % "1.5.21", "com.google.api-client" % "google-api-client" % "1.23.0", "org.glassfish.jersey.core" % "jersey-common" % "2.25.1", "com.fasterxml.jackson.core" % "jackson-core" % "2.8.9" % "compile", diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index 2fff29a15b5..69aac87b279 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -114,8 +114,7 @@ - - src/main/java + src/main/java @@ -127,8 +126,7 @@ - - src/test/java + src/test/java @@ -287,15 +285,15 @@ UTF-8 - 1.5.17 + 1.5.21 1.23.0 2.25.1 2.8.9 {{#joda}} - 2.9.9 + 2.9.9 {{/joda}} {{#threetenbp}} - 2.6.4 + 2.6.4 {{/threetenbp}} 1.0.0 4.12 diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index 8f7c03adefa..2a4a56b935c 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -117,7 +117,7 @@ if(hasProperty('target') && target == 'android') { } ext { - swagger_annotations_version = "1.5.20" + swagger_annotations_version = "1.5.21" jackson_version = "2.9.6" {{#supportJava6}} jersey_version = "2.6" diff --git a/libraries/jersey2/build.sbt.mustache b/libraries/jersey2/build.sbt.mustache index 54902da7989..cc2e9480b6a 100644 --- a/libraries/jersey2/build.sbt.mustache +++ b/libraries/jersey2/build.sbt.mustache @@ -9,7 +9,7 @@ lazy val root = (project in file(".")). publishArtifact in (Compile, packageDoc) := false, resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( - "io.swagger" % "swagger-annotations" % "1.5.20", + "io.swagger" % "swagger-annotations" % "1.5.21", "org.glassfish.jersey.core" % "jersey-client" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, "org.glassfish.jersey.media" % "jersey-media-multipart" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, "org.glassfish.jersey.media" % "jersey-media-json-jackson" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 5c273fa147b..93f2d9e2c9b 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -114,8 +114,7 @@ - - src/main/java + src/main/java @@ -127,8 +126,7 @@ - - src/test/java + src/test/java @@ -212,7 +210,7 @@ io.swagger swagger-annotations - ${swagger-core-version} + ${swagger-annotations-version} @@ -318,7 +316,7 @@ UTF-8 - 1.5.20 + 1.5.21 {{^supportJava6}} 2.27 {{/supportJava6}} diff --git a/libraries/rest-assured/build.gradle.mustache b/libraries/rest-assured/build.gradle.mustache index 54b90483f4c..87608f21024 100644 --- a/libraries/rest-assured/build.gradle.mustache +++ b/libraries/rest-assured/build.gradle.mustache @@ -94,7 +94,7 @@ if(hasProperty('target') && target == 'android') { } ext { - swagger_annotations_version = "1.5.15" + swagger_annotations_version = "1.5.21" rest_assured_version = "3.1.0" junit_version = "4.12" gson_version = "2.6.1" diff --git a/libraries/rest-assured/build.sbt.mustache b/libraries/rest-assured/build.sbt.mustache index 68f3eff08d0..7a666ebace6 100644 --- a/libraries/rest-assured/build.sbt.mustache +++ b/libraries/rest-assured/build.sbt.mustache @@ -9,7 +9,7 @@ lazy val root = (project in file(".")). publishArtifact in (Compile, packageDoc) := false, resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( - "io.swagger" % "swagger-annotations" % "1.5.15", + "io.swagger" % "swagger-annotations" % "1.5.21", "io.rest-assured" % "scala-support" % "3.1.0", "com.google.code.gson" % "gson" % "2.6.1", "io.gsonfire" % "gson-fire" % "1.8.2" % "compile", diff --git a/libraries/rest-assured/pom.mustache b/libraries/rest-assured/pom.mustache index 1d0c1711389..aa0c15d8b38 100644 --- a/libraries/rest-assured/pom.mustache +++ b/libraries/rest-assured/pom.mustache @@ -113,8 +113,7 @@ - - src/main/java + src/main/java @@ -126,8 +125,7 @@ - - src/test/java + src/test/java @@ -199,7 +197,7 @@ io.swagger swagger-annotations - ${swagger-core-version} + ${swagger-annotations-version} io.rest-assured @@ -245,7 +243,7 @@ UTF-8 - 1.5.15 + 1.5.21 3.1.0 2.6.1 1.8.2 diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index f2f7fa53a40..540c54c6813 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -95,8 +95,7 @@ - - src/main/java + src/main/java @@ -108,8 +107,7 @@ - - src/test/java + src/test/java @@ -155,7 +153,7 @@ io.swagger swagger-annotations - ${swagger-core-version} + ${swagger-annotations-version} @@ -259,7 +257,7 @@ UTF-8 - 1.5.18 + 1.5.21 3.1.3.Final 2.8.6 2.6.4 diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index 9925cc43daf..b50203a337a 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -118,7 +118,7 @@ if(hasProperty('target') && target == 'android') { } ext { - swagger_annotations_version = "1.5.17" + swagger_annotations_version = "1.5.21" jackson_version = "2.8.9" spring_web_version = "4.3.9.RELEASE" jodatime_version = "2.9.9" diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache index 0d371de6ea1..10d84edafc2 100644 --- a/libraries/resttemplate/pom.mustache +++ b/libraries/resttemplate/pom.mustache @@ -114,8 +114,7 @@ - - src/main/java + src/main/java @@ -127,8 +126,7 @@ - - src/test/java + src/test/java @@ -290,7 +288,7 @@ UTF-8 - 1.5.17 + 1.5.21 4.3.9.RELEASE 2.8.9 {{#joda}} diff --git a/libraries/retrofit/build.gradle.mustache b/libraries/retrofit/build.gradle.mustache index f0c1cbe4c88..45da8dd03bb 100644 --- a/libraries/retrofit/build.gradle.mustache +++ b/libraries/retrofit/build.gradle.mustache @@ -109,7 +109,7 @@ ext { okhttp_version = "2.7.5" oltu_version = "1.0.1" retrofit_version = "1.9.0" - swagger_annotations_version = "1.5.8" + swagger_annotations_version = "1.5.21" junit_version = "4.12" jodatime_version = "2.9.3" {{#threetenbp}} diff --git a/libraries/retrofit/build.sbt.mustache b/libraries/retrofit/build.sbt.mustache index ffa308d528a..9d5df5e223c 100644 --- a/libraries/retrofit/build.sbt.mustache +++ b/libraries/retrofit/build.sbt.mustache @@ -11,7 +11,7 @@ lazy val root = (project in file(".")). libraryDependencies ++= Seq( "com.squareup.okhttp" % "okhttp" % "2.7.5" % "compile", "com.squareup.retrofit" % "retrofit" % "1.9.0" % "compile", - "io.swagger" % "swagger-annotations" % "1.5.8" % "compile", + "io.swagger" % "swagger-annotations" % "1.5.21" % "compile", "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", "joda-time" % "joda-time" % "2.9.3" % "compile", {{#threetenbp}} diff --git a/libraries/retrofit/pom.mustache b/libraries/retrofit/pom.mustache index adbd6e99e50..155a8128e30 100644 --- a/libraries/retrofit/pom.mustache +++ b/libraries/retrofit/pom.mustache @@ -114,8 +114,7 @@ - - src/main/java + src/main/java @@ -127,8 +126,7 @@ - - src/test/java + src/test/java @@ -212,7 +210,7 @@ io.swagger swagger-annotations - ${swagger-core-version} + ${swagger-annotations-version} com.squareup.retrofit @@ -241,17 +239,15 @@ ${threetenbp-version} {{/threetenbp}} - {{#parcelableModel}} - - - com.google.android - android - 4.1.1.4 - provided - + + + com.google.android + android + 4.1.1.4 + provided + {{/parcelableModel}} - junit @@ -262,7 +258,7 @@ UTF-8 - 1.5.18 + 1.5.21 1.9.0 2.7.5 2.9.9 diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index cd9baeb50d3..dfd1f6d9405 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -134,7 +134,7 @@ ext { play_version = "2.6.7" {{/play26}} {{/usePlayWS}} - swagger_annotations_version = "1.5.17" + swagger_annotations_version = "1.5.21" junit_version = "4.12" {{#useRxJava}} rx_java_version = "1.3.0" diff --git a/libraries/retrofit2/build.sbt.mustache b/libraries/retrofit2/build.sbt.mustache index b08e715a7bd..e66ca784036 100644 --- a/libraries/retrofit2/build.sbt.mustache +++ b/libraries/retrofit2/build.sbt.mustache @@ -44,7 +44,7 @@ lazy val root = (project in file(".")). "com.squareup.retrofit2" % "adapter-rxjava2" % "2.3.0" % "compile", "io.reactivex.rxjava2" % "rxjava" % "2.1.1" % "compile", {{/useRxJava2}} - "io.swagger" % "swagger-annotations" % "1.5.17" % "compile", + "io.swagger" % "swagger-annotations" % "1.5.21" % "compile", "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", {{#joda}} "joda-time" % "joda-time" % "2.9.9" % "compile", diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index 8518053b809..3028604c360 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -114,8 +114,7 @@ - - src/main/java + src/main/java @@ -127,8 +126,7 @@ - - src/test/java + src/test/java @@ -191,7 +189,7 @@ io.swagger swagger-annotations - ${swagger-core-version} + ${swagger-annotations-version} com.squareup.retrofit2 @@ -262,7 +260,6 @@ ${retrofit-version} {{/useRxJava2}} - {{#usePlayWS}} @@ -291,16 +288,13 @@ ${jackson-version} {{#withXml}} - com.fasterxml.jackson.dataformat jackson-dataformat-xml ${jackson-version} - {{/withXml}} - {{#play24}} com.typesafe.play @@ -327,9 +321,7 @@ 1.1.0.Final {{/play26}} - {{/usePlayWS}} - {{#parcelableModel}} @@ -339,7 +331,6 @@ provided {{/parcelableModel}} - junit @@ -354,33 +345,33 @@ ${java.version} ${java.version} 1.8.0 - 1.5.18 + 1.5.21 {{#usePlayWS}} - {{#play24}} - 2.6.6 - 2.4.11 - {{/play24}} - {{#play25}} - 2.7.8 - 2.5.15 - {{/play25}} - {{#play26}} - 2.8.10 - 2.6.7 - {{/play26}} + {{#play24}} + 2.6.6 + 2.4.11 + {{/play24}} + {{#play25}} + 2.7.8 + 2.5.15 + {{/play25}} + {{#play26}} + 2.8.10 + 2.6.7 + {{/play26}} {{/usePlayWS}} 2.3.0 {{#useRxJava}} - 1.3.0 + 1.3.0 {{/useRxJava}} {{#useRxJava2}} - 2.1.1 + 2.1.1 {{/useRxJava2}} {{#joda}} - 2.9.9 + 2.9.9 {{/joda}} {{#threetenbp}} - 1.3.5 + 1.3.5 {{/threetenbp}} 1.0.1 4.12 diff --git a/libraries/vertx/build.gradle.mustache b/libraries/vertx/build.gradle.mustache index e1c956d5f72..1f2ebac4399 100644 --- a/libraries/vertx/build.gradle.mustache +++ b/libraries/vertx/build.gradle.mustache @@ -26,7 +26,7 @@ task execute(type:JavaExec) { } ext { - swagger_annotations_version = "1.5.17" + swagger_annotations_version = "1.5.21" jackson_version = "{{^threetenbp}}2.8.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" vertx_version = "3.4.2" junit_version = "4.12" diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache index 32f94b62639..b8d7e513d6b 100644 --- a/libraries/vertx/pom.mustache +++ b/libraries/vertx/pom.mustache @@ -114,8 +114,7 @@ - - src/main/java + src/main/java @@ -127,8 +126,7 @@ - - src/test/java + src/test/java @@ -200,7 +198,7 @@ io.swagger swagger-annotations - ${swagger-core-version} + ${swagger-annotations-version} @@ -271,7 +269,7 @@ UTF-8 3.4.2 - 1.5.18 + 1.5.21 {{^threetenbp}}2.8.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} 4.12 diff --git a/pom.mustache b/pom.mustache index 0c1501e115c..275a5c869a4 100644 --- a/pom.mustache +++ b/pom.mustache @@ -114,8 +114,7 @@ - - src/main/java + src/main/java @@ -127,8 +126,7 @@ - - src/test/java + src/test/java @@ -327,7 +325,7 @@ UTF-8 - 1.5.17 + 1.5.21 1.19.4 {{#supportJava6}} 2.5 From df576305f39dbbd581b8cfc4e3a91dce077d5bea Mon Sep 17 00:00:00 2001 From: Marco Date: Tue, 4 Sep 2018 09:58:14 +0200 Subject: [PATCH 050/370] [Java][Webclient ]Avoid double encoding on query params (#924) * call build() with encoded = true * Regenerate client --- libraries/webclient/ApiClient.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index 41b81a004c5..7f91fe44134 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -545,7 +545,7 @@ public class ApiClient { builder.queryParams(queryParams); } - final WebClient.RequestBodySpec requestBuilder = webClient.method(method).uri(builder.build().toUri()); + final WebClient.RequestBodySpec requestBuilder = webClient.method(method).uri(builder.build(true).toUri()); if(accept != null) { requestBuilder.accept(accept.toArray(new MediaType[accept.size()])); } From 4abca8863e0f2dbc596313fc6cdbf2e26768f0ee Mon Sep 17 00:00:00 2001 From: William Cheng Date: Thu, 6 Sep 2018 14:24:14 +0800 Subject: [PATCH 051/370] Better code format for Java (okhttp-gson) client (#971) * better code format for java okhttp client * update java petstore samples --- JSON.mustache | 46 ++++++++++--------- Pair.mustache | 17 +++++-- StringUtil.mustache | 12 +++-- libraries/okhttp-gson/ApiClient.mustache | 28 ++++++----- .../GzipRequestInterceptor.mustache | 14 ++++-- libraries/okhttp-gson/api.mustache | 35 +++++++++----- 6 files changed, 96 insertions(+), 56 deletions(-) diff --git a/JSON.mustache b/JSON.mustache index ae8de32fafc..724b428392b 100644 --- a/JSON.mustache +++ b/JSON.mustache @@ -61,20 +61,24 @@ public class JSON { public static GsonBuilder createGson() { GsonFireBuilder fireBuilder = new GsonFireBuilder() - {{#models}}{{#model}}{{#discriminator}} .registerTypeSelector({{classname}}.class, new TypeSelector() { - @Override - public Class getClassForElement(JsonElement readElement) { - Map classByDiscriminatorValue = new HashMap(); - {{#mappedModels}} - classByDiscriminatorValue.put("{{mappingName}}".toUpperCase(Locale.ROOT), {{modelName}}.class); - {{/mappedModels}} - classByDiscriminatorValue.put("{{classname}}".toUpperCase(Locale.ROOT), {{classname}}.class); - return getClassByDiscriminator( - classByDiscriminatorValue, - getDiscriminatorValue(readElement, "{{{propertyName}}}")); - } + {{#models}} + {{#model}} + {{#discriminator}} + .registerTypeSelector({{classname}}.class, new TypeSelector() { + @Override + public Class getClassForElement(JsonElement readElement) { + Map classByDiscriminatorValue = new HashMap(); + {{#mappedModels}} + classByDiscriminatorValue.put("{{mappingName}}".toUpperCase(Locale.ROOT), {{modelName}}.class); + {{/mappedModels}} + classByDiscriminatorValue.put("{{classname}}".toUpperCase(Locale.ROOT), {{classname}}.class); + return getClassByDiscriminator(classByDiscriminatorValue, + getDiscriminatorValue(readElement, "{{{propertyName}}}")); + } }) - {{/discriminator}}{{/model}}{{/models}} + {{/discriminator}} + {{/model}} + {{/models}} ; GsonBuilder builder = fireBuilder.createGsonBuilder(); {{#disableHtmlEscaping}} @@ -85,7 +89,7 @@ public class JSON { private static String getDiscriminatorValue(JsonElement readElement, String discriminatorField) { JsonElement element = readElement.getAsJsonObject().get(discriminatorField); - if(null == element) { + if (null == element) { throw new IllegalArgumentException("missing discriminator field: <" + discriminatorField + ">"); } return element.getAsString(); @@ -93,7 +97,7 @@ public class JSON { private static Class getClassByDiscriminator(Map classByDiscriminatorValue, String discriminatorValue) { Class clazz = (Class) classByDiscriminatorValue.get(discriminatorValue.toUpperCase(Locale.ROOT)); - if(null == clazz) { + if (null == clazz) { throw new IllegalArgumentException("cannot determine model class of name: <" + discriminatorValue + ">"); } return clazz; @@ -172,9 +176,11 @@ public class JSON { } catch (JsonParseException e) { // Fallback processing when failed to parse JSON form response body: // return the response body string directly for the String return type; - if (returnType.equals(String.class)) + if (returnType.equals(String.class)) { return (T) body; - else throw (e); + } else { + throw (e); + } } } @@ -408,8 +414,7 @@ public class JSON { private DateFormat dateFormat; - public SqlDateTypeAdapter() { - } + public SqlDateTypeAdapter() {} public SqlDateTypeAdapter(DateFormat dateFormat) { this.dateFormat = dateFormat; @@ -462,8 +467,7 @@ public class JSON { private DateFormat dateFormat; - public DateTypeAdapter() { - } + public DateTypeAdapter() {} public DateTypeAdapter(DateFormat dateFormat) { this.dateFormat = dateFormat; diff --git a/Pair.mustache b/Pair.mustache index c08f145a482..ff9e06b20d4 100644 --- a/Pair.mustache +++ b/Pair.mustache @@ -13,13 +13,17 @@ public class Pair { } private void setName(String name) { - if (!isValidString(name)) return; + if (!isValidString(name)) { + return; + } this.name = name; } private void setValue(String value) { - if (!isValidString(value)) return; + if (!isValidString(value)) { + return; + } this.value = value; } @@ -33,8 +37,13 @@ public class Pair { } private boolean isValidString(String arg) { - if (arg == null) return false; - if (arg.trim().isEmpty()) return false; + if (arg == null) { + return false; + } + + if (arg.trim().isEmpty()) { + return false; + } return true; } diff --git a/StringUtil.mustache b/StringUtil.mustache index 7b72a7bab45..ce52c82384d 100644 --- a/StringUtil.mustache +++ b/StringUtil.mustache @@ -13,8 +13,12 @@ public class StringUtil { */ public static boolean containsIgnoreCase(String[] array, String value) { for (String str : array) { - if (value == null && str == null) return true; - if (value != null && value.equalsIgnoreCase(str)) return true; + if (value == null && str == null) { + return true; + } + if (value != null && value.equalsIgnoreCase(str)) { + return true; + } } return false; } @@ -32,7 +36,9 @@ public class StringUtil { */ public static String join(String[] array, String separator) { int len = array.length; - if (len == 0) return ""; + if (len == 0) { + return ""; + } StringBuilder out = new StringBuilder(); out.append(array[0]); diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index 5af1e2285f9..178dd691ad8 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -517,7 +517,7 @@ public class ApiClient { return jsonStr.substring(1, jsonStr.length() - 1); } else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); - for (Object o : (Collection)param) { + for (Object o : (Collection) param) { if (b.length() > 0) { b.append(","); } @@ -542,7 +542,9 @@ public class ApiClient { List params = new ArrayList(); // preconditions - if (name == null || name.isEmpty() || value == null || value instanceof Collection) return params; + if (name == null || name.isEmpty() || value == null || value instanceof Collection) { + return params; + } params.add(new Pair(name, parameterToString(value))); return params; @@ -587,7 +589,7 @@ public class ApiClient { delimiter = escapeString("|"); } - StringBuilder sb = new StringBuilder() ; + StringBuilder sb = new StringBuilder(); for (Object item : value) { sb.append(delimiter); sb.append(escapeString(parameterToString(item))); @@ -657,7 +659,7 @@ public class ApiClient { */ public String selectHeaderContentType(String[] contentTypes) { if (contentTypes.length == 0 || contentTypes[0].equals("*/*")) { - return "application/json"; + return "application/json"; } for (String contentType : contentTypes) { if (isJsonMime(contentType)) { @@ -981,7 +983,7 @@ public class ApiClient { * @param formParams The form parameters * @param authNames The authentications to apply * @param progressRequestListener Progress request listener - * @return The HTTP request + * @return The HTTP request * @throws ApiException If fail to serialize the request body object */ public Request buildRequest(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map formParams, String[] authNames, ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException { @@ -1098,13 +1100,15 @@ public class ApiClient { * Update query and header parameters based on authentication settings. * * @param authNames The authentications to apply - * @param queryParams List of query parameters - * @param headerParams Map of header parameters + * @param queryParams List of query parameters + * @param headerParams Map of header parameters */ public void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams) { for (String authName : authNames) { Authentication auth = authentications.get(authName); - if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + if (auth == null) { + throw new RuntimeException("Authentication undefined: " + authName); + } auth.applyToParams(queryParams, headerParams); } } @@ -1116,7 +1120,7 @@ public class ApiClient { * @return RequestBody */ public RequestBody buildRequestBodyFormEncoding(Map formParams) { - FormEncodingBuilder formBuilder = new FormEncodingBuilder(); + FormEncodingBuilder formBuilder = new FormEncodingBuilder(); for (Entry param : formParams.entrySet()) { formBuilder.add(param.getKey(), parameterToString(param.getValue())); } @@ -1179,10 +1183,12 @@ public class ApiClient { public X509Certificate[] getAcceptedIssuers() { return null; } }; SSLContext sslContext = SSLContext.getInstance("TLS"); - trustManagers = new TrustManager[]{ trustAll }; + trustManagers = new TrustManager[] {trustAll}; hostnameVerifier = new HostnameVerifier() { @Override - public boolean verify(String hostname, SSLSession session) { return true; } + public boolean verify(String hostname, SSLSession session) { + return true; + } }; } else if (sslCaCert != null) { char[] password = null; // Any password will work. diff --git a/libraries/okhttp-gson/GzipRequestInterceptor.mustache b/libraries/okhttp-gson/GzipRequestInterceptor.mustache index 23224cf5d5b..61a5b7b0ba2 100644 --- a/libraries/okhttp-gson/GzipRequestInterceptor.mustache +++ b/libraries/okhttp-gson/GzipRequestInterceptor.mustache @@ -16,7 +16,8 @@ import java.io.IOException; * Taken from https://github.com/square/okhttp/issues/350 */ class GzipRequestInterceptor implements Interceptor { - @Override public Response intercept(Chain chain) throws IOException { + @Override + public Response intercept(Chain chain) throws IOException { Request originalRequest = chain.request(); if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) { return chain.proceed(originalRequest); @@ -52,19 +53,22 @@ class GzipRequestInterceptor implements Interceptor { private RequestBody gzip(final RequestBody body) { return new RequestBody() { - @Override public MediaType contentType() { + @Override + public MediaType contentType() { return body.contentType(); } - @Override public long contentLength() { + @Override + public long contentLength() { return -1; // We don't know the compressed length in advance! } - @Override public void writeTo(BufferedSink sink) throws IOException { + @Override + public void writeTo(BufferedSink sink) throws IOException { BufferedSink gzipSink = Okio.buffer(new GzipSink(sink)); body.writeTo(gzipSink); gzipSink.close(); } }; } -} \ No newline at end of file +} diff --git a/libraries/okhttp-gson/api.mustache b/libraries/okhttp-gson/api.mustache index 5f599b117d8..9af817bc272 100644 --- a/libraries/okhttp-gson/api.mustache +++ b/libraries/okhttp-gson/api.mustache @@ -89,23 +89,34 @@ public class {{classname}} { .replaceAll("\\{" + "{{baseName}}" + "\\}", {{localVariablePrefix}}apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; {{javaUtilPrefix}}List {{localVariablePrefix}}localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); - {{javaUtilPrefix}}List {{localVariablePrefix}}localVarCollectionQueryParams = new {{javaUtilPrefix}}ArrayList();{{#queryParams}} - if ({{paramName}} != null) - {{localVariablePrefix}}{{#collectionFormat}}localVarCollectionQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPairs("{{{collectionFormat}}}", {{/collectionFormat}}{{^collectionFormat}}localVarQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPair({{/collectionFormat}}"{{baseName}}", {{paramName}}));{{/queryParams}} + {{javaUtilPrefix}}List {{localVariablePrefix}}localVarCollectionQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{#queryParams}} + if ({{paramName}} != null) { + {{localVariablePrefix}}{{#collectionFormat}}localVarCollectionQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPairs("{{{collectionFormat}}}", {{/collectionFormat}}{{^collectionFormat}}localVarQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPair({{/collectionFormat}}"{{baseName}}", {{paramName}})); + } - {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarHeaderParams = new {{javaUtilPrefix}}HashMap();{{#headerParams}} - if ({{paramName}} != null) - {{localVariablePrefix}}localVarHeaderParams.put("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}}));{{/headerParams}} + {{/queryParams}} + {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); + {{#headerParams}} + if ({{paramName}} != null) { + {{localVariablePrefix}}localVarHeaderParams.put("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}})); + } - {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarFormParams = new {{javaUtilPrefix}}HashMap();{{#formParams}} - if ({{paramName}} != null) - {{localVariablePrefix}}localVarFormParams.put("{{baseName}}", {{paramName}});{{/formParams}} + {{/headerParams}} + {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarFormParams = new {{javaUtilPrefix}}HashMap(); + {{#formParams}} + if ({{paramName}} != null) { + {{localVariablePrefix}}localVarFormParams.put("{{baseName}}", {{paramName}}); + } + {{/formParams}} final String[] {{localVariablePrefix}}localVarAccepts = { {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }; final String {{localVariablePrefix}}localVarAccept = {{localVariablePrefix}}apiClient.selectHeaderAccept({{localVariablePrefix}}localVarAccepts); - if ({{localVariablePrefix}}localVarAccept != null) {{localVariablePrefix}}localVarHeaderParams.put("Accept", {{localVariablePrefix}}localVarAccept); + if ({{localVariablePrefix}}localVarAccept != null) { + {{localVariablePrefix}}localVarHeaderParams.put("Accept", {{localVariablePrefix}}localVarAccept); + } final String[] {{localVariablePrefix}}localVarContentTypes = { {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} @@ -113,7 +124,7 @@ public class {{classname}} { final String {{localVariablePrefix}}localVarContentType = {{localVariablePrefix}}apiClient.selectHeaderContentType({{localVariablePrefix}}localVarContentTypes); {{localVariablePrefix}}localVarHeaderParams.put("Content-Type", {{localVariablePrefix}}localVarContentType); - if(progressListener != null) { + if (progressListener != null) { apiClient.getHttpClient().networkInterceptors().add(new com.squareup.okhttp.Interceptor() { @Override public com.squareup.okhttp.Response intercept(com.squareup.okhttp.Interceptor.Chain chain) throws IOException { @@ -265,4 +276,4 @@ public class {{classname}} { } {{/operation}} } -{{/operations}} \ No newline at end of file +{{/operations}} From fc783ab7b4c70647cbb9073d288b65bc775c45be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilya=20Hranko=C5=ADski?= Date: Sun, 9 Sep 2018 13:11:59 +0300 Subject: [PATCH 052/370] [Java][Feign] Add support for Feign 10 (#977) (#988) --- libraries/feign/auth/OAuth.mustache | 8 ++++++++ libraries/feign/build.gradle.mustache | 2 +- libraries/feign/build.sbt.mustache | 6 +++--- libraries/feign/pom.mustache | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/libraries/feign/auth/OAuth.mustache b/libraries/feign/auth/OAuth.mustache index 1df88d403a2..0ed92dbcae9 100644 --- a/libraries/feign/auth/OAuth.mustache +++ b/libraries/feign/auth/OAuth.mustache @@ -19,6 +19,9 @@ import org.apache.oltu.oauth2.common.message.types.GrantType; import org.apache.oltu.oauth2.common.token.BasicOAuthToken; import feign.Client; +{{#useFeign10}} +import feign.Request.HttpMethod; +{{/useFeign10}} import feign.Request.Options; import feign.RequestInterceptor; import feign.RequestTemplate; @@ -92,7 +95,12 @@ public class OAuth implements RequestInterceptor { try { accessTokenResponse = oauthClient.accessToken(tokenRequestBuilder.buildBodyMessage()); } catch (Exception e) { + {{#useFeign10}} + throw new RetryableException(e.getMessage(), HttpMethod.POST, e, null); + {{/useFeign10}} + {{^useFeign10}} throw new RetryableException(e.getMessage(), e,null); + {{/useFeign10}} } if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { setAccessToken(accessTokenResponse.getAccessToken(), accessTokenResponse.getExpiresIn()); diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index a4e5ea5a791..b852a3d43af 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -123,7 +123,7 @@ ext { {{#threetenbp}} threepane_version = "2.6.4" {{/threetenbp}} - feign_version = "9.4.0" + feign_version = "{{#useFeign10}}10.0.1{{/useFeign10}}{{^useFeign10}}9.4.0{{/useFeign10}}" feign_form_version = "2.1.0" junit_version = "4.12" oltu_version = "1.0.1" diff --git a/libraries/feign/build.sbt.mustache b/libraries/feign/build.sbt.mustache index a3dff942003..f5c8355a02b 100644 --- a/libraries/feign/build.sbt.mustache +++ b/libraries/feign/build.sbt.mustache @@ -10,9 +10,9 @@ lazy val root = (project in file(".")). resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( "io.swagger" % "swagger-annotations" % "1.5.21" % "compile", - "io.github.openfeign" % "feign-core" % "9.4.0" % "compile", - "io.github.openfeign" % "feign-jackson" % "9.4.0" % "compile", - "io.github.openfeign" % "feign-slf4j" % "9.4.0" % "compile", + "io.github.openfeign" % "feign-core" % "{{#useFeign10}}10.0.1{{/useFeign10}}{{^useFeign10}}9.4.0{{/useFeign10}}" % "compile", + "io.github.openfeign" % "feign-jackson" % "{{#useFeign10}}10.0.1{{/useFeign10}}{{^useFeign10}}9.4.0{{/useFeign10}}" % "compile", + "io.github.openfeign" % "feign-slf4j" % "{{#useFeign10}}10.0.1{{/useFeign10}}{{^useFeign10}}9.4.0{{/useFeign10}}" % "compile", "io.github.openfeign.form" % "feign-form" % "2.1.0" % "compile", "com.fasterxml.jackson.core" % "jackson-core" % "2.8.7" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.7" % "compile", diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index 7a81b340af9..bf74b39c617 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -293,7 +293,7 @@ ${java.version} ${java.version} 1.5.21 - 9.4.0 + {{#useFeign10}}10.0.1{{/useFeign10}}{{^useFeign10}}9.4.0{{/useFeign10}} 2.1.0 2.8.9 {{#threetenbp}} From ee74cf187b35877a9fff5905fb86f06856b08fe6 Mon Sep 17 00:00:00 2001 From: Vladislav Cheparin Date: Sun, 16 Sep 2018 11:00:38 +0300 Subject: [PATCH 053/370] [Java][Retrofit2] The part name is not added to the annotation (#1029) * fixed retrofit2/formParams.mustache * added play26 to retrofit2-all.sh * fixed samples --- libraries/retrofit2/formParams.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/retrofit2/formParams.mustache b/libraries/retrofit2/formParams.mustache index af65a37bc36..0456f44947e 100644 --- a/libraries/retrofit2/formParams.mustache +++ b/libraries/retrofit2/formParams.mustache @@ -1 +1 @@ -{{#isFormParam}}{{^isFile}}{{#isMultipart}}@retrofit2.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit2.http.Field{{/isMultipart}}("{{baseName}}") {{{dataType}}} {{paramName}}{{/isFile}}{{#isFile}}{{#isMultipart}}@retrofit2.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit2.http.Field{{/isMultipart}}("{{baseName}}") MultipartBody.Part {{paramName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file +{{#isFormParam}}{{^isFile}}{{#isMultipart}}@retrofit2.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit2.http.Field{{/isMultipart}}("{{baseName}}") {{{dataType}}} {{paramName}}{{/isFile}}{{#isFile}}{{#isMultipart}}@retrofit2.http.Part{{/isMultipart}}{{^isMultipart}}@retrofit2.http.Field("{{baseName}}"){{/isMultipart}} MultipartBody.Part {{paramName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file From 52ee3f00e47c78fa91411d41651305baac15ac42 Mon Sep 17 00:00:00 2001 From: Kiran-Sivakumar <43218409+Kiran-Sivakumar@users.noreply.github.com> Date: Thu, 20 Sep 2018 04:29:59 -0700 Subject: [PATCH 054/370] [okhttp-gson] Add support for OAuth access token retry (#1058) * Add support for access token retry in okhttp-gson lib * Update expected number of generated files in test * Update samples * Update security samples * Fix default user-agent and update samples --- libraries/okhttp-gson/ApiClient.mustache | 58 ++++++- .../auth/OAuthOkHttpClient.mustache | 68 ++++++++ .../okhttp-gson/auth/RetryingOAuth.mustache | 147 ++++++++++++++++++ libraries/okhttp-gson/build.gradle.mustache | 1 + libraries/okhttp-gson/pom.mustache | 5 + 5 files changed, 272 insertions(+), 7 deletions(-) create mode 100644 libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache create mode 100644 libraries/okhttp-gson/auth/RetryingOAuth.mustache diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index 178dd691ad8..4ba31c8cbc0 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -19,6 +19,9 @@ import org.threeten.bp.OffsetDateTime; import org.threeten.bp.format.DateTimeFormatter; {{/threetenbp}} +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; +import org.apache.oltu.oauth2.common.message.types.GrantType; + import javax.net.ssl.*; import java.io.File; import java.io.IOException; @@ -50,6 +53,7 @@ import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; import {{invokerPackage}}.auth.ApiKeyAuth; import {{invokerPackage}}.auth.OAuth; +import {{invokerPackage}}.auth.RetryingOAuth; public class ApiClient { @@ -78,6 +82,38 @@ public class ApiClient { * Constructor for ApiClient */ public ApiClient() { + init(); + + // Setup authentications (key: authentication name, value: authentication).{{#authMethods}}{{#isBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + } + {{#authMethods}}{{#isOAuth}} + /* + * Constructor for ApiClient to support access token retry on 401/403 + */ + public ApiClient( + String clientId, + String clientSecret, + Map parameters + ) { + init(); + + RetryingOAuth retryingOAuth = new RetryingOAuth("{{tokenUrl}}", clientId, GrantType.valueOf("{{flow}}"), clientSecret, parameters); + authentications.put( + "{{name}}", + retryingOAuth + ); + httpClient.interceptors().add(retryingOAuth); + + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + } + {{/isOAuth}}{{/authMethods}} + private void init() { httpClient = new OkHttpClient(); {{#useGzipFeature}} @@ -92,13 +128,7 @@ public class ApiClient { // Set default User-Agent. setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); - // Setup authentications (key: authentication name, value: authentication). - authentications = new HashMap();{{#authMethods}}{{#isBasic}} - authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} - authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} - authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} - // Prevent the authentications from being modified. - authentications = Collections.unmodifiableMap(authentications); + authentications = new HashMap(); } /** @@ -502,6 +532,20 @@ public class ApiClient { return this; } + /** + * Helper method to configure the token endpoint of the first oauth found in the apiAuthorizations (there should be only one) + * @return Token request builder + */ + public TokenRequestBuilder getTokenEndPoint() { + for (Authentication apiAuth : authentications.values()) { + if (apiAuth instanceof RetryingOAuth) { + RetryingOAuth retryingOAuth = (RetryingOAuth) apiAuth; + return retryingOAuth.getTokenRequestBuilder(); + } + } + return null; + } + /** * Format the given parameter object into string. * diff --git a/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache b/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache new file mode 100644 index 00000000000..6886c2fc358 --- /dev/null +++ b/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache @@ -0,0 +1,68 @@ +package {{invokerPackage}}.auth; + +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.MediaType; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.RequestBody; +import com.squareup.okhttp.Response; + +import org.apache.oltu.oauth2.client.HttpClient; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest; +import org.apache.oltu.oauth2.client.response.OAuthClientResponse; +import org.apache.oltu.oauth2.client.response.OAuthClientResponseFactory; +import org.apache.oltu.oauth2.common.exception.OAuthProblemException; +import org.apache.oltu.oauth2.common.exception.OAuthSystemException; + +import java.io.IOException; +import java.util.Map; +import java.util.Map.Entry; + +public class OAuthOkHttpClient implements HttpClient { + private OkHttpClient client; + + public OAuthOkHttpClient() { + this.client = new OkHttpClient(); + } + + public OAuthOkHttpClient(OkHttpClient client) { + this.client = client; + } + + @Override + public T execute(OAuthClientRequest request, Map headers, + String requestMethod, Class responseClass) + throws OAuthSystemException, OAuthProblemException { + + MediaType mediaType = MediaType.parse("application/json"); + Request.Builder requestBuilder = new Request.Builder().url(request.getLocationUri()); + + if(headers != null) { + for (Entry entry : headers.entrySet()) { + if (entry.getKey().equalsIgnoreCase("Content-Type")) { + mediaType = MediaType.parse(entry.getValue()); + } else { + requestBuilder.addHeader(entry.getKey(), entry.getValue()); + } + } + } + + RequestBody body = request.getBody() != null ? RequestBody.create(mediaType, request.getBody()) : null; + requestBuilder.method(requestMethod, body); + + try { + Response response = client.newCall(requestBuilder.build()).execute(); + return OAuthClientResponseFactory.createCustomResponse( + response.body().string(), + response.body().contentType().toString(), + response.code(), + responseClass); + } catch (IOException e) { + throw new OAuthSystemException(e); + } + } + + @Override + public void shutdown() { + // Nothing to do here + } +} diff --git a/libraries/okhttp-gson/auth/RetryingOAuth.mustache b/libraries/okhttp-gson/auth/RetryingOAuth.mustache new file mode 100644 index 00000000000..b28169a6f22 --- /dev/null +++ b/libraries/okhttp-gson/auth/RetryingOAuth.mustache @@ -0,0 +1,147 @@ +package {{invokerPackage}}.auth; + +import com.squareup.okhttp.Interceptor; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; + +import org.apache.oltu.oauth2.client.OAuthClient; +import org.apache.oltu.oauth2.client.request.OAuthBearerClientRequest; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest; +import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; +import org.apache.oltu.oauth2.client.response.OAuthJSONAccessTokenResponse; +import org.apache.oltu.oauth2.common.exception.OAuthProblemException; +import org.apache.oltu.oauth2.common.exception.OAuthSystemException; +import org.apache.oltu.oauth2.common.message.types.GrantType; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.util.Map; + +public class RetryingOAuth extends OAuth implements Interceptor { + private OAuthClient oAuthClient; + + private TokenRequestBuilder tokenRequestBuilder; + + public RetryingOAuth(OkHttpClient client, TokenRequestBuilder tokenRequestBuilder) { + this.oAuthClient = new OAuthClient(new OAuthOkHttpClient(client)); + this.tokenRequestBuilder = tokenRequestBuilder; + } + + public RetryingOAuth(TokenRequestBuilder tokenRequestBuilder) { + this(new OkHttpClient(), tokenRequestBuilder); + } + + public RetryingOAuth( + String tokenUrl, + String clientId, + GrantType grantType, + String clientSecret, + Map parameters + ) { + this(OAuthClientRequest.tokenLocation(tokenUrl) + .setClientId(clientId) + .setGrantType(grantType) + .setClientSecret(clientSecret)); + + if (parameters != null) { + for (String paramName : parameters.keySet()) { + tokenRequestBuilder.setParameter(paramName, parameters.get(paramName)); + } + } + } + + @Override + public Response intercept(Chain chain) throws IOException { + return retryingIntercept(chain, true); + } + + private Response retryingIntercept(Chain chain, boolean updateTokenAndRetryOnAuthorizationFailure) throws IOException { + Request request = chain.request(); + + // If the request already has an authorization (e.g. Basic auth), proceed with the request as is + if (request.header("Authorization") != null) { + return chain.proceed(request); + } + + // Get the token if it has not yet been acquired + if (getAccessToken() == null) { + updateAccessToken(null); + } + + OAuthClientRequest oAuthRequest; + if (getAccessToken() != null) { + // Build the request + Request.Builder requestBuilder = request.newBuilder(); + + String requestAccessToken = getAccessToken(); + try { + oAuthRequest = + new OAuthBearerClientRequest(request.urlString()). + setAccessToken(requestAccessToken). + buildHeaderMessage(); + } catch (OAuthSystemException e) { + throw new IOException(e); + } + + Map headers = oAuthRequest.getHeaders(); + for (String headerName : headers.keySet()) { + requestBuilder.addHeader(headerName, headers.get(headerName)); + } + requestBuilder.url(oAuthRequest.getLocationUri()); + + // Execute the request + Response response = chain.proceed(requestBuilder.build()); + + // 401/403 response codes most likely indicate an expired access token, unless it happens two times in a row + if ( + response != null && + ( response.code() == HttpURLConnection.HTTP_UNAUTHORIZED || + response.code() == HttpURLConnection.HTTP_FORBIDDEN ) && + updateTokenAndRetryOnAuthorizationFailure + ) { + try { + if (updateAccessToken(requestAccessToken)) { + response.body().close(); + return retryingIntercept(chain, false); + } + } catch (Exception e) { + response.body().close(); + throw e; + } + } + return response; + } + else { + return chain.proceed(chain.request()); + } + } + + /* + * Returns true if the access token has been updated + */ + public synchronized boolean updateAccessToken(String requestAccessToken) throws IOException { + if (getAccessToken() == null || getAccessToken().equals(requestAccessToken)) { + try { + OAuthJSONAccessTokenResponse accessTokenResponse = + oAuthClient.accessToken(tokenRequestBuilder.buildBodyMessage()); + if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { + setAccessToken(accessTokenResponse.getAccessToken()); + return !getAccessToken().equals(requestAccessToken); + } + } catch (OAuthSystemException | OAuthProblemException e) { + throw new IOException(e); + } + } + + return false; + } + + public TokenRequestBuilder getTokenRequestBuilder() { + return tokenRequestBuilder; + } + + public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) { + this.tokenRequestBuilder = tokenRequestBuilder; + } +} diff --git a/libraries/okhttp-gson/build.gradle.mustache b/libraries/okhttp-gson/build.gradle.mustache index 69621c1a6bd..6bb7a2f5636 100644 --- a/libraries/okhttp-gson/build.gradle.mustache +++ b/libraries/okhttp-gson/build.gradle.mustache @@ -123,6 +123,7 @@ dependencies { compile 'com.squareup.okhttp:logging-interceptor:2.7.5' compile 'com.google.code.gson:gson:2.8.1' compile 'io.gsonfire:gson-fire:1.8.0' + compile group: 'org.apache.oltu.oauth2', name: 'org.apache.oltu.oauth2.client', version: '1.0.1' {{#joda}} compile 'joda-time:joda-time:2.9.9' {{/joda}} diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index 0b0903d617b..e960f01abcd 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -213,6 +213,11 @@ gson-fire ${gson-fire-version} + + org.apache.oltu.oauth2 + org.apache.oltu.oauth2.client + 1.0.1 + {{#joda}} joda-time From cf025d3ad652ad9411fff5a0cc164c3d65faab97 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Sun, 7 Oct 2018 03:56:16 +0800 Subject: [PATCH 055/370] Refactor default and example values in Java generators (#1045) * fix default, example for java okhttp * update java feign samples * update samples, doc * add new doc for dart-jaguar * update model template * update jaxrs spec model * update resteasy sample * update java samples --- api.mustache | 2 +- api_doc.mustache | 2 +- libraries/feign/api.mustache | 6 +++--- libraries/okhttp-gson/api.mustache | 8 ++++---- pojo.mustache | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/api.mustache b/api.mustache index 17f8d56ac6e..2b1ecb4ab6b 100644 --- a/api.mustache +++ b/api.mustache @@ -46,7 +46,7 @@ public class {{classname}} { * {{summary}} * {{notes}} {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}}{{/required}} {{/allParams}} {{#returnType}} * @return {{returnType}} diff --git a/api_doc.mustache b/api_doc.mustache index bbb5b66f840..7ddb1953403 100644 --- a/api_doc.mustache +++ b/api_doc.mustache @@ -62,7 +62,7 @@ try { {{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} Name | Type | Description | Notes ------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} -{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} +{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{^isContainer}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} {{/allParams}} ### Return type diff --git a/libraries/feign/api.mustache b/libraries/feign/api.mustache index dea8a6e8aef..b446223ba53 100644 --- a/libraries/feign/api.mustache +++ b/libraries/feign/api.mustache @@ -25,7 +25,7 @@ public interface {{classname}} extends ApiClient.Api { * {{summary}} * {{notes}} {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}} {{/allParams}} {{#returnType}} * @return {{returnType}} @@ -55,14 +55,14 @@ public interface {{classname}} extends ApiClient.Api { * building up this map in a fluent style. {{#allParams}} {{^isQueryParam}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}} {{/isQueryParam}} {{/allParams}} * @param queryParams Map of query parameters as name-value pairs *

The following elements may be specified in the query map:

*
    {{#queryParams}} - *
  • {{paramName}} - {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}
  • + *
  • {{paramName}} - {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}
  • {{/queryParams}} *
{{#returnType}} diff --git a/libraries/okhttp-gson/api.mustache b/libraries/okhttp-gson/api.mustache index 9af817bc272..affaec014b9 100644 --- a/libraries/okhttp-gson/api.mustache +++ b/libraries/okhttp-gson/api.mustache @@ -65,7 +65,7 @@ public class {{classname}} { {{#operation}} /** * Build call for {{operationId}}{{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}{{/allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}{{/allParams}} * @param progressListener Progress listener * @param progressRequestListener Progress request listener * @return Call to execute @@ -188,7 +188,7 @@ public class {{classname}} { /** * {{summary}} * {{notes}}{{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}{{/allParams}}{{#returnType}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}{{/allParams}}{{#returnType}} * @return {{returnType}}{{/returnType}} * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body {{#isDeprecated}} @@ -210,7 +210,7 @@ public class {{classname}} { /** * {{summary}} * {{notes}}{{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}{{/allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}{{/allParams}} * @return ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body {{#isDeprecated}} @@ -233,7 +233,7 @@ public class {{classname}} { /** * {{summary}} (asynchronously) * {{notes}}{{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}{{/allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}{{/allParams}} * @param callback The callback to be executed when the API call finishes * @return The request call * @throws ApiException If fail to process the API call, e.g. serializing the request body object diff --git a/pojo.mustache b/pojo.mustache index 21c21b1ddd3..2d08f65d6ac 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -62,7 +62,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela private {{{datatypeWithEnum}}} {{name}}{{#required}} = {{{defaultValue}}}{{/required}}{{^required}} = null{{/required}}; {{/isContainer}} {{^isContainer}} - private {{{datatypeWithEnum}}} {{name}} = {{{defaultValue}}}; + private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; {{/isContainer}} {{/vars}} From 993e1b8009398d6256f646b028430bf287a74ded Mon Sep 17 00:00:00 2001 From: Kiran-Sivakumar <43218409+Kiran-Sivakumar@users.noreply.github.com> Date: Mon, 8 Oct 2018 02:39:10 -0700 Subject: [PATCH 056/370] [Java][okhttp-gson] Fix bug when specifying grant-type (flow) for OAuth token retry (#1183) * Fix bug when specifying grant-type for OAuth token retry * Update samples * Update security samples --- libraries/okhttp-gson/ApiClient.mustache | 3 ++- .../okhttp-gson/auth/RetryingOAuth.mustache | 24 ++++++++++++++++--- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index 4ba31c8cbc0..9775e5b323d 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -54,6 +54,7 @@ import {{invokerPackage}}.auth.HttpBasicAuth; import {{invokerPackage}}.auth.ApiKeyAuth; import {{invokerPackage}}.auth.OAuth; import {{invokerPackage}}.auth.RetryingOAuth; +import {{invokerPackage}}.auth.OAuthFlow; public class ApiClient { @@ -102,7 +103,7 @@ public class ApiClient { ) { init(); - RetryingOAuth retryingOAuth = new RetryingOAuth("{{tokenUrl}}", clientId, GrantType.valueOf("{{flow}}"), clientSecret, parameters); + RetryingOAuth retryingOAuth = new RetryingOAuth("{{tokenUrl}}", clientId, OAuthFlow.{{flow}}, clientSecret, parameters); authentications.put( "{{name}}", retryingOAuth diff --git a/libraries/okhttp-gson/auth/RetryingOAuth.mustache b/libraries/okhttp-gson/auth/RetryingOAuth.mustache index b28169a6f22..4703c2488d0 100644 --- a/libraries/okhttp-gson/auth/RetryingOAuth.mustache +++ b/libraries/okhttp-gson/auth/RetryingOAuth.mustache @@ -35,15 +35,14 @@ public class RetryingOAuth extends OAuth implements Interceptor { public RetryingOAuth( String tokenUrl, String clientId, - GrantType grantType, + OAuthFlow flow, String clientSecret, Map parameters ) { this(OAuthClientRequest.tokenLocation(tokenUrl) .setClientId(clientId) - .setGrantType(grantType) .setClientSecret(clientSecret)); - + setFlow(flow); if (parameters != null) { for (String paramName : parameters.keySet()) { tokenRequestBuilder.setParameter(paramName, parameters.get(paramName)); @@ -51,6 +50,25 @@ public class RetryingOAuth extends OAuth implements Interceptor { } } + public void setFlow(OAuthFlow flow) { + switch(flow) { + case accessCode: + tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE); + break; + case implicit: + tokenRequestBuilder.setGrantType(GrantType.IMPLICIT); + break; + case password: + tokenRequestBuilder.setGrantType(GrantType.PASSWORD); + break; + case application: + tokenRequestBuilder.setGrantType(GrantType.CLIENT_CREDENTIALS); + break; + default: + break; + } + } + @Override public Response intercept(Chain chain) throws IOException { return retryingIntercept(chain, true); From 0531b9dd5679bd5ea211c8d53f24fd4e3bb11c40 Mon Sep 17 00:00:00 2001 From: mwoodland Date: Tue, 9 Oct 2018 01:34:29 +0100 Subject: [PATCH 057/370] =?UTF-8?q?Allow=20specifying/overriding=20the=20p?= =?UTF-8?q?arent=20in=20the=20pom=20file=20for=20Java=20and=20S=E2=80=A6?= =?UTF-8?q?=20(#1132)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Allow specifying/overriding the parent in the pom file for Java and Spring generators. * Don't add extra whitespace to the pom file when the parent isn't overridden. * Remove accidentally added white space. --- libraries/feign/pom.mustache | 7 +++++++ libraries/google-api-client/pom.mustache | 7 +++++++ libraries/jersey2/pom.mustache | 7 +++++++ libraries/okhttp-gson/pom.mustache | 7 +++++++ libraries/rest-assured/pom.mustache | 7 +++++++ libraries/resteasy/pom.mustache | 7 +++++++ libraries/resttemplate/pom.mustache | 7 +++++++ libraries/retrofit/pom.mustache | 7 +++++++ libraries/retrofit2/pom.mustache | 7 +++++++ libraries/vertx/pom.mustache | 7 +++++++ libraries/webclient/pom.mustache | 7 +++++++ pom.mustache | 7 +++++++ 12 files changed, 84 insertions(+) diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index bf74b39c617..32f01e5bb12 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -13,6 +13,13 @@ {{scmDeveloperConnection}} {{scmUrl}} +{{#parentOverridden}} + + {{{parentGroupId}}} + {{{parentArtifactId}}} + {{{parentVersion}}} + +{{/parentOverridden}} diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index 69aac87b279..7ff969e9c6c 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -13,6 +13,13 @@ {{scmDeveloperConnection}} {{scmUrl}} +{{#parentOverridden}} + + {{{parentGroupId}}} + {{{parentArtifactId}}} + {{{parentVersion}}} + +{{/parentOverridden}} diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 93f2d9e2c9b..57db33547c4 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -13,6 +13,13 @@ {{scmDeveloperConnection}} {{scmUrl}} +{{#parentOverridden}} + + {{{parentGroupId}}} + {{{parentArtifactId}}} + {{{parentVersion}}} + +{{/parentOverridden}} diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index e960f01abcd..0cff2363ea3 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -13,6 +13,13 @@ {{scmDeveloperConnection}} {{scmUrl}} +{{#parentOverridden}} + + {{{parentGroupId}}} + {{{parentArtifactId}}} + {{{parentVersion}}} + +{{/parentOverridden}} diff --git a/libraries/rest-assured/pom.mustache b/libraries/rest-assured/pom.mustache index aa0c15d8b38..64285da8111 100644 --- a/libraries/rest-assured/pom.mustache +++ b/libraries/rest-assured/pom.mustache @@ -13,6 +13,13 @@ {{scmDeveloperConnection}} {{scmUrl}} +{{#parentOverridden}} + + {{{parentGroupId}}} + {{{parentArtifactId}}} + {{{parentVersion}}} + +{{/parentOverridden}} diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index 540c54c6813..2950d3e748e 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -11,6 +11,13 @@ scm:git:git@github.com:openapitools/openapi-generator.git https://openapi-generator.tech +{{#parentOverridden}} + + {{{parentGroupId}}} + {{{parentArtifactId}}} + {{{parentVersion}}} + +{{/parentOverridden}} diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache index 10d84edafc2..95b3f7cb5d0 100644 --- a/libraries/resttemplate/pom.mustache +++ b/libraries/resttemplate/pom.mustache @@ -13,6 +13,13 @@ {{scmDeveloperConnection}} {{scmUrl}} +{{#parentOverridden}} + + {{{parentGroupId}}} + {{{parentArtifactId}}} + {{{parentVersion}}} + +{{/parentOverridden}} diff --git a/libraries/retrofit/pom.mustache b/libraries/retrofit/pom.mustache index 155a8128e30..c2a5eeced6f 100644 --- a/libraries/retrofit/pom.mustache +++ b/libraries/retrofit/pom.mustache @@ -13,6 +13,13 @@ {{scmDeveloperConnection}} {{scmUrl}} +{{#parentOverridden}} + + {{{parentGroupId}}} + {{{parentArtifactId}}} + {{{parentVersion}}} + +{{/parentOverridden}} diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index 3028604c360..29347aee8e6 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -13,6 +13,13 @@ {{scmDeveloperConnection}} {{scmUrl}} +{{#parentOverridden}} + + {{{parentGroupId}}} + {{{parentArtifactId}}} + {{{parentVersion}}} + +{{/parentOverridden}} diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache index b8d7e513d6b..46687cd0c7c 100644 --- a/libraries/vertx/pom.mustache +++ b/libraries/vertx/pom.mustache @@ -13,6 +13,13 @@ {{scmDeveloperConnection}} {{scmUrl}} +{{#parentOverridden}} + + {{{parentGroupId}}} + {{{parentArtifactId}}} + {{{parentVersion}}} + +{{/parentOverridden}} diff --git a/libraries/webclient/pom.mustache b/libraries/webclient/pom.mustache index 4771a9bb658..7fde2317697 100644 --- a/libraries/webclient/pom.mustache +++ b/libraries/webclient/pom.mustache @@ -13,6 +13,13 @@ {{scmDeveloperConnection}} {{scmUrl}} +{{#parentOverridden}} + + {{{parentGroupId}}} + {{{parentArtifactId}}} + {{{parentVersion}}} + +{{/parentOverridden}} diff --git a/pom.mustache b/pom.mustache index 275a5c869a4..a2703f141d0 100644 --- a/pom.mustache +++ b/pom.mustache @@ -13,6 +13,13 @@ {{scmDeveloperConnection}} {{scmUrl}} +{{#parentOverridden}} + + {{{parentGroupId}}} + {{{parentArtifactId}}} + {{{parentVersion}}} + +{{/parentOverridden}} From 7624bbf613046b777f5caea4a8483a5a35ce23e0 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Thu, 18 Oct 2018 16:29:38 +0800 Subject: [PATCH 058/370] Fix jackson-databind security issue (#1259) * fix jackson databind security issue * fix java jersey 1 dependency * fix java webclient dep --- build.gradle.mustache | 5 +-- libraries/feign/build.gradle.mustache | 5 +-- libraries/feign/build.sbt.mustache | 7 +++-- libraries/feign/pom.mustache | 5 +-- .../google-api-client/build.gradle.mustache | 5 +-- .../google-api-client/build.sbt.mustache | 6 ++-- libraries/google-api-client/pom.mustache | 3 +- libraries/jersey2/build.gradle.mustache | 5 +-- libraries/jersey2/build.sbt.mustache | 6 ++-- libraries/jersey2/pom.mustache | 5 +-- libraries/resteasy/build.gradle.mustache | 13 +++----- libraries/resteasy/build.sbt.mustache | 31 +++++++++---------- libraries/resteasy/pom.mustache | 5 +-- libraries/resttemplate/build.gradle.mustache | 5 +-- libraries/resttemplate/pom.mustache | 5 +-- libraries/retrofit2/build.gradle.mustache | 3 +- libraries/retrofit2/build.sbt.mustache | 6 ++-- libraries/retrofit2/pom.mustache | 2 +- libraries/vertx/pom.mustache | 2 +- libraries/webclient/pom.mustache | 7 +++-- 20 files changed, 69 insertions(+), 62 deletions(-) diff --git a/build.gradle.mustache b/build.gradle.mustache index 192ac3cbbbc..cd79a9afd36 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -133,7 +133,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.17" - jackson_version = "{{^threetenbp}}2.8.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" + jackson_version = "{{^threetenbp}}2.8.11{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" + jackson_databind_version = "{{^threetenbp}}2.8.11.2{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" jersey_version = "1.19.4" jodatime_version = "2.9.9" junit_version = "4.12" @@ -145,7 +146,7 @@ dependencies { compile "com.sun.jersey.contribs:jersey-multipart:$jersey_version" compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" {{#joda}} compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index b852a3d43af..59bb9c3906d 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -119,7 +119,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.21" - jackson_version = "2.8.7" + jackson_version = "2.8.11" + jackson_databind_version = "2.8.11.2" {{#threetenbp}} threepane_version = "2.6.4" {{/threetenbp}} @@ -137,7 +138,7 @@ dependencies { compile "io.github.openfeign.form:feign-form:$feign_form_version" compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" {{#joda}} compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} diff --git a/libraries/feign/build.sbt.mustache b/libraries/feign/build.sbt.mustache index f5c8355a02b..0ab575007dd 100644 --- a/libraries/feign/build.sbt.mustache +++ b/libraries/feign/build.sbt.mustache @@ -14,10 +14,11 @@ lazy val root = (project in file(".")). "io.github.openfeign" % "feign-jackson" % "{{#useFeign10}}10.0.1{{/useFeign10}}{{^useFeign10}}9.4.0{{/useFeign10}}" % "compile", "io.github.openfeign" % "feign-slf4j" % "{{#useFeign10}}10.0.1{{/useFeign10}}{{^useFeign10}}9.4.0{{/useFeign10}}" % "compile", "io.github.openfeign.form" % "feign-form" % "2.1.0" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.8.7" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.7" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.7" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.8.11" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.11" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.2" % "compile", "com.fasterxml.jackson.datatype" % "jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}" % "2.8.7" % "compile", + "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4" % "compile", "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", "com.brsanthu" % "migbase64" % "2.2" % "compile", "junit" % "junit" % "4.12" % "test", diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index 32f01e5bb12..abf00bbfaaf 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -235,7 +235,7 @@ com.fasterxml.jackson.core jackson-databind - ${jackson-version} + ${jackson-databind-version} {{#withXml}} @@ -302,7 +302,8 @@ 1.5.21 {{#useFeign10}}10.0.1{{/useFeign10}}{{^useFeign10}}9.4.0{{/useFeign10}} 2.1.0 - 2.8.9 + 2.8.11 + 2.8.11.2 {{#threetenbp}} 2.6.4 {{/threetenbp}} diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache index acbe24a53f6..99c91a9c771 100644 --- a/libraries/google-api-client/build.gradle.mustache +++ b/libraries/google-api-client/build.gradle.mustache @@ -119,7 +119,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.21" - jackson_version = "2.8.9" + jackson_version = "2.8.11" + jackson_databind_version = "2.8.11.2" google_api_client_version = "1.23.0" jersey_common_version = "2.25.1" jodatime_version = "2.9.9" @@ -135,7 +136,7 @@ dependencies { compile "org.glassfish.jersey.core:jersey-common:${jersey_common_version}" compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" {{#java8}} compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" diff --git a/libraries/google-api-client/build.sbt.mustache b/libraries/google-api-client/build.sbt.mustache index 9f1aeaf1570..ba6d1f459d0 100644 --- a/libraries/google-api-client/build.sbt.mustache +++ b/libraries/google-api-client/build.sbt.mustache @@ -12,9 +12,9 @@ lazy val root = (project in file(".")). "io.swagger" % "swagger-annotations" % "1.5.21", "com.google.api-client" % "google-api-client" % "1.23.0", "org.glassfish.jersey.core" % "jersey-common" % "2.25.1", - "com.fasterxml.jackson.core" % "jackson-core" % "2.8.9" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.9" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.8.11" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.11" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.2" % "compile", {{#withXml}} "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.8.9" % "compile", {{/withXml}} diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index 7ff969e9c6c..2dffd4837bb 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -295,7 +295,8 @@ 1.5.21 1.23.0 2.25.1 - 2.8.9 + 2.8.11 + 2.8.11.2 {{#joda}} 2.9.9 {{/joda}} diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index 2a4a56b935c..46167d5f8d9 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -118,7 +118,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.21" - jackson_version = "2.9.6" + jackson_version = "2.8.11" + jackson_databind_version = "2.8.11.2" {{#supportJava6}} jersey_version = "2.6" commons_io_version=2.5 @@ -140,7 +141,7 @@ dependencies { compile "org.glassfish.jersey.media:jersey-media-json-jackson:$jersey_version" compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" {{#joda}} compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} diff --git a/libraries/jersey2/build.sbt.mustache b/libraries/jersey2/build.sbt.mustache index cc2e9480b6a..035cce0e3ce 100644 --- a/libraries/jersey2/build.sbt.mustache +++ b/libraries/jersey2/build.sbt.mustache @@ -13,9 +13,9 @@ lazy val root = (project in file(".")). "org.glassfish.jersey.core" % "jersey-client" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, "org.glassfish.jersey.media" % "jersey-media-multipart" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, "org.glassfish.jersey.media" % "jersey-media-json-jackson" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, - "com.fasterxml.jackson.core" % "jackson-core" % "2.8.9" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.9" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.8.11" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.11" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.2" % "compile", {{#joda}} "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.8.9" % "compile", {{/joda}} diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 57db33547c4..a912ac6edf4 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -251,7 +251,7 @@ com.fasterxml.jackson.core jackson-databind - ${jackson-version} + ${jackson-databind-version} {{#withXml}} @@ -332,7 +332,8 @@ 2.5 3.6 {{/supportJava6}} - 2.8.9 + 2.8.11 + 2.8.11.2 {{#threetenbp}} 2.6.4 {{/threetenbp}} diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index ac2cb6fab8e..7f8e2422642 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -117,13 +117,13 @@ if(hasProperty('target') && target == 'android') { } ext { - swagger_annotations_version = "1.5.18" - jackson_version = "2.8.6" + swagger_annotations_version = "1.5.21" + jackson_version = "2.8.11" + jackson_databind_version = "2.8.11.2" threetenbp_version = "2.6.4" - jersey_version = "2.22.2" resteasy_version = "3.1.3.Final" {{^java8}} - jodatime_version = "2.9.4" + jodatime_version = "2.9.9" {{/java8}} {{#supportJava6}} commons_io_version=2.5 @@ -137,12 +137,9 @@ dependencies { compile "org.jboss.resteasy:resteasy-client:$resteasy_version" compile "org.jboss.resteasy:resteasy-multipart-provider:$resteasy_version" compile "org.jboss.resteasy:resteasy-jackson2-provider:$resteasy_version" - compile "org.glassfish.jersey.core:jersey-client:$jersey_version" - compile "org.glassfish.jersey.media:jersey-media-multipart:$jersey_version" - compile "org.glassfish.jersey.media:jersey-media-json-jackson:$jersey_version" compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$threetenbp_version" {{#java8}} compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" diff --git a/libraries/resteasy/build.sbt.mustache b/libraries/resteasy/build.sbt.mustache index cdfc4f848fd..7b197b46f8e 100644 --- a/libraries/resteasy/build.sbt.mustache +++ b/libraries/resteasy/build.sbt.mustache @@ -9,28 +9,25 @@ lazy val root = (project in file(".")). publishArtifact in (Compile, packageDoc) := false, resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( - "io.swagger" % "swagger-annotations" % "1.5.18", - "org.glassfish.jersey.core" % "jersey-client" % "2.22.2", - "org.glassfish.jersey.media" % "jersey-media-multipart" % "2.22.2", - "org.glassfish.jersey.media" % "jersey-media-json-jackson" % "2.22.2", - "org.jboss.resteasy" % "resteasy-client" % "3.1.3.Final", - "org.jboss.resteasy" % "resteasy-multipart-provider" % "3.1.3.Final", - "org.jboss.resteasy" % "resteasy-jackson2-provider" % "3.1.3.Final", - "com.fasterxml.jackson.core" % "jackson-core" % "2.8.6", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.6", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.6", - "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4", + "io.swagger" % "swagger-annotations" % "1.5.21" % "compile", + "org.jboss.resteasy" % "resteasy-client" % "3.1.3.Final" % "compile", + "org.jboss.resteasy" % "resteasy-multipart-provider" % "3.1.3.Final" % "compile", + "org.jboss.resteasy" % "resteasy-jackson2-provider" % "3.1.3.Final" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.8.11" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.11" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.2" % "compile", + "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4" % "compile", {{#java8}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.8.6", + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.8.6" % "compile", {{/java8}} {{^java8}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.7.5", - "joda-time" % "joda-time" % "2.9.4", - "com.brsanthu" % "migbase64" % "2.2", + "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.7.5" % "compile", + "joda-time" % "joda-time" % "2.9.9" % "compile", + "com.brsanthu" % "migbase64" % "2.2" % "compile", {{/java8}} {{#supportJava6}} - "org.apache.commons" % "commons-lang3" % "3.5", - "commons-io" % "commons-io" % "2.5", + "org.apache.commons" % "commons-lang3" % "3.5" % "compile", + "commons-io" % "commons-io" % "2.5" % "compile", {{/supportJava6}} "junit" % "junit" % "4.12" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index 2950d3e748e..c474027a274 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -187,7 +187,7 @@ com.fasterxml.jackson.core jackson-databind - ${jackson-version} + ${jackson-databind-version} {{#withXml}} @@ -266,7 +266,8 @@ UTF-8 1.5.21 3.1.3.Final - 2.8.6 + 2.8.11 + 2.8.11 2.6.4 {{^java8}} 2.9.9 diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index b50203a337a..d1110e419d2 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -119,7 +119,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.21" - jackson_version = "2.8.9" + jackson_version = "2.8.11" + jackson_databind_version = "2.8.11.2" spring_web_version = "4.3.9.RELEASE" jodatime_version = "2.9.9" junit_version = "4.12" @@ -133,7 +134,7 @@ dependencies { compile "org.springframework:spring-web:$spring_web_version" compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" {{#java8}} compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache index 95b3f7cb5d0..427a815cf4e 100644 --- a/libraries/resttemplate/pom.mustache +++ b/libraries/resttemplate/pom.mustache @@ -241,7 +241,7 @@ com.fasterxml.jackson.core jackson-databind - ${jackson-version} + ${jackson-databind-version} com.fasterxml.jackson.jaxrs @@ -297,7 +297,8 @@ UTF-8 1.5.21 4.3.9.RELEASE - 2.8.9 + 2.8.11 + 2.8.11.2 {{#joda}} 2.9.9 {{/joda}} diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index dfd1f6d9405..93518d88941 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -130,7 +130,8 @@ ext { play_version = "2.5.14" {{/play25}} {{#play26}} - jackson_version = "2.8.10" + jackson_version = "2.8.11" + jackson_databind_version = "2.8.11" play_version = "2.6.7" {{/play26}} {{/usePlayWS}} diff --git a/libraries/retrofit2/build.sbt.mustache b/libraries/retrofit2/build.sbt.mustache index e66ca784036..88e06d154b8 100644 --- a/libraries/retrofit2/build.sbt.mustache +++ b/libraries/retrofit2/build.sbt.mustache @@ -30,9 +30,9 @@ lazy val root = (project in file(".")). {{#play26}} "com.typesafe.play" % "play-ahc-ws_2.12" % "2.6.7" % "compile", "javax.validation" % "validation-api" % "1.1.0.Final" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.8.10" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.10" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.10" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.8.11" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.11" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.2" % "compile", {{/play26}} "com.squareup.retrofit2" % "converter-jackson" % "2.3.0" % "compile", {{/usePlayWS}} diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index 29347aee8e6..4ddee4d014f 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -363,7 +363,7 @@ 2.5.15 {{/play25}} {{#play26}} - 2.8.10 + 2.8.11 2.6.7 {{/play26}} {{/usePlayWS}} diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache index 46687cd0c7c..2b922cbcccb 100644 --- a/libraries/vertx/pom.mustache +++ b/libraries/vertx/pom.mustache @@ -277,7 +277,7 @@ UTF-8 3.4.2 1.5.21 - {{^threetenbp}}2.8.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} + {{^threetenbp}}2.8.11{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} 4.12
diff --git a/libraries/webclient/pom.mustache b/libraries/webclient/pom.mustache index 7fde2317697..bdd59fd4772 100644 --- a/libraries/webclient/pom.mustache +++ b/libraries/webclient/pom.mustache @@ -96,7 +96,7 @@ com.fasterxml.jackson.core jackson-databind - ${jackson-version} + ${jackson-databind-version} {{#java8}} @@ -131,12 +131,13 @@ UTF-8 1.5.20 5.0.7.RELEASE - 2.9.5 + 2.8.11 + 2.8.11.2 4.12 3.1.8.RELEASE 0.7.8.RELEASE {{#joda}} - 2.9.9 + 2.9.9 {{/joda}} From 4358a3b49ded1992a1bb1b02d2102a2cdbbf6f45 Mon Sep 17 00:00:00 2001 From: moreginger Date: Sun, 21 Oct 2018 15:01:47 +0100 Subject: [PATCH 059/370] Don't generate unused ApiException class for java/webclient. (#1165) --- libraries/webclient/api.mustache | 3 +-- libraries/webclient/api_test.mustache | 6 +----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/libraries/webclient/api.mustache b/libraries/webclient/api.mustache index 9c3f9fb140c..c29a160fc4f 100644 --- a/libraries/webclient/api.mustache +++ b/libraries/webclient/api.mustache @@ -5,8 +5,7 @@ import {{invokerPackage}}.ApiClient; {{#imports}}import {{import}}; {{/imports}} -{{^fullJavaUtil}}import java.util.ArrayList; -import java.util.HashMap; +{{^fullJavaUtil}}import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map;{{/fullJavaUtil}} diff --git a/libraries/webclient/api_test.mustache b/libraries/webclient/api_test.mustache index f1dca2f41cf..1b730bf43a7 100644 --- a/libraries/webclient/api_test.mustache +++ b/libraries/webclient/api_test.mustache @@ -2,7 +2,6 @@ package {{package}}; -import {{invokerPackage}}.ApiException; {{#imports}}import {{import}}; {{/imports}} import org.junit.Test; @@ -28,12 +27,9 @@ public class {{classname}}Test { * {{summary}} * * {{notes}} - * - * @throws ApiException - * if the Api call fails */ @Test - public void {{operationId}}Test() throws ApiException { + public void {{operationId}}Test() { {{#allParams}} {{{dataType}}} {{paramName}} = null; {{/allParams}} From 14d5d7802e8fc77c9fd71d6a16af40ac131477eb Mon Sep 17 00:00:00 2001 From: Yuen-Kuei Hsueh Date: Thu, 25 Oct 2018 11:50:12 +0800 Subject: [PATCH 060/370] [Java][Spring] Add bean vaildation for email datatype (#1115) --- model.mustache | 3 +++ pom.mustache | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/model.mustache b/model.mustache index a42a1359e4d..2154453a885 100644 --- a/model.mustache +++ b/model.mustache @@ -31,6 +31,9 @@ import android.os.Parcel; import javax.validation.constraints.*; import javax.validation.Valid; {{/useBeanValidation}} +{{#performBeanValidation}} +import org.hibernate.validator.constraints.*; +{{/performBeanValidation}} {{#models}} {{#model}} diff --git a/pom.mustache b/pom.mustache index a2703f141d0..ed6e39c78ea 100644 --- a/pom.mustache +++ b/pom.mustache @@ -313,6 +313,14 @@ provided {{/useBeanValidation}} + {{#performBeanValidation}} + + + org.hibernate + hibernate-validator + 5.4.1.Final + + {{/performBeanValidation}} {{#parcelableModel}} From 65885690debd8baaec5c38cd7b1a6d0b90cba8b9 Mon Sep 17 00:00:00 2001 From: Kiran-Sivakumar <43218409+Kiran-Sivakumar@users.noreply.github.com> Date: Sat, 3 Nov 2018 07:10:16 -0700 Subject: [PATCH 061/370] [Java][okhttp-gson] Add new ApiClient constructors for access token retry (#1319) * Add new ApiClient constructors for access token retry * Update samples * Update security samples --- libraries/okhttp-gson/ApiClient.mustache | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index 9775e5b323d..f3639393cc2 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -80,7 +80,7 @@ public class ApiClient { private HttpLoggingInterceptor loggingInterceptor; /* - * Constructor for ApiClient + * Basic constructor for ApiClient */ public ApiClient() { init(); @@ -94,13 +94,23 @@ public class ApiClient { } {{#authMethods}}{{#isOAuth}} /* - * Constructor for ApiClient to support access token retry on 401/403 + * Constructor for ApiClient to support access token retry on 401/403 configured with client ID */ - public ApiClient( - String clientId, - String clientSecret, - Map parameters - ) { + public ApiClient(String clientId) { + this(clientId, null, null); + } + + /* + * Constructor for ApiClient to support access token retry on 401/403 configured with client ID and additional parameters + */ + public ApiClient(String clientId, Map parameters) { + this(clientId, null, parameters); + } + + /* + * Constructor for ApiClient to support access token retry on 401/403 configured with client ID, secret, and additional parameters + */ + public ApiClient(String clientId, String clientSecret, Map parameters) { init(); RetryingOAuth retryingOAuth = new RetryingOAuth("{{tokenUrl}}", clientId, OAuthFlow.{{flow}}, clientSecret, parameters); From ea623c4f7f0ae932ba69a39a82b98a30406bd412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eivind=20Bergst=C3=B8l?= Date: Fri, 9 Nov 2018 16:48:26 +0100 Subject: [PATCH 062/370] Fixes an issue where code generator for Java produces not compileable (#1357) code if the yml-definition does not have any type definitions. This is normal if the api only uses simple datatypes (Int, String) for inout/output. --- JSON.mustache | 2 ++ libraries/retrofit2/JSON.mustache | 2 ++ 2 files changed, 4 insertions(+) diff --git a/JSON.mustache b/JSON.mustache index 724b428392b..e207efbc05b 100644 --- a/JSON.mustache +++ b/JSON.mustache @@ -25,7 +25,9 @@ import org.threeten.bp.OffsetDateTime; import org.threeten.bp.format.DateTimeFormatter; {{/threetenbp}} +{{#parent.length}} import {{modelPackage}}.*; +{{/parent.length}} import okio.ByteString; import java.io.IOException; diff --git a/libraries/retrofit2/JSON.mustache b/libraries/retrofit2/JSON.mustache index 7dbb56a3da1..a7e1df8598a 100644 --- a/libraries/retrofit2/JSON.mustache +++ b/libraries/retrofit2/JSON.mustache @@ -25,7 +25,9 @@ import org.threeten.bp.OffsetDateTime; import org.threeten.bp.format.DateTimeFormatter; {{/threetenbp}} +{{#parent.length}} import {{modelPackage}}.*; +{{/parent.length}} import java.io.IOException; import java.io.StringReader; From a3c58e90201591a4c1c283eed18b6b19c352c6fe Mon Sep 17 00:00:00 2001 From: William Cheng Date: Sun, 11 Nov 2018 21:33:28 +0800 Subject: [PATCH 063/370] Remove duplicated imports (#1414) * remove duplicated imports * fix model import in java * update generator docs * fix model import for retrofit2 client --- JSON.mustache | 4 ++-- libraries/retrofit2/JSON.mustache | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/JSON.mustache b/JSON.mustache index e207efbc05b..b7f458c9d12 100644 --- a/JSON.mustache +++ b/JSON.mustache @@ -25,9 +25,9 @@ import org.threeten.bp.OffsetDateTime; import org.threeten.bp.format.DateTimeFormatter; {{/threetenbp}} -{{#parent.length}} +{{#models.0}} import {{modelPackage}}.*; -{{/parent.length}} +{{/models.0}} import okio.ByteString; import java.io.IOException; diff --git a/libraries/retrofit2/JSON.mustache b/libraries/retrofit2/JSON.mustache index a7e1df8598a..9ba7567bffe 100644 --- a/libraries/retrofit2/JSON.mustache +++ b/libraries/retrofit2/JSON.mustache @@ -25,9 +25,9 @@ import org.threeten.bp.OffsetDateTime; import org.threeten.bp.format.DateTimeFormatter; {{/threetenbp}} -{{#parent.length}} +{{#models.0}} import {{modelPackage}}.*; -{{/parent.length}} +{{/models.0}} import java.io.IOException; import java.io.StringReader; From 0565a0754244412ff0ba40e92cedff21bdc3690b Mon Sep 17 00:00:00 2001 From: William Cheng Date: Mon, 19 Nov 2018 21:14:03 +0800 Subject: [PATCH 064/370] fix typo in java client docstring (#1494) --- libraries/okhttp-gson/ApiClient.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index f3639393cc2..d2d99dd4477 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -145,7 +145,7 @@ public class ApiClient { /** * Get base path * - * @return Baes path + * @return Base path */ public String getBasePath() { return basePath; From 5b20dc4b9093048a0d770e7eac75602c31b0d560 Mon Sep 17 00:00:00 2001 From: Kiran-Sivakumar <43218409+Kiran-Sivakumar@users.noreply.github.com> Date: Wed, 28 Nov 2018 01:53:36 -0800 Subject: [PATCH 065/370] [Java][okhttp-gson] Add option to employ builders for API requests (#1341) * Generate APIs that use the builder pattern * Add option to use builders for API requests * Fix template spacing * Add new sample-generation script and generated samples * Update docs * Add new sample-generation script for Windows * Replace config option with vendor extension * Remove useBuildersForApiRequests config option * Remove builders sample-generation scripts * Replace config option with vendor extension in api_test template * Remove okhttp-gson-requestBuilders sample * Rename x-builders-for-api-requests to x-group-parameters * Add modified api_doc.mustache under okhttp-gson resources * Add modified README.mustache under okhttp-gson resources * Update petstore samples * Fix FakeApiTest.java in petstore samples * Add whitespace to rerun checks * Remove whitespace to rerun tests * Fix FakeApiTest.java in parcelable petstore sample * Update versions in samples * Update versions in samples --- libraries/okhttp-gson/README.mustache | 169 ++++++++++++++++++++++++ libraries/okhttp-gson/api.mustache | 127 +++++++++++++++++- libraries/okhttp-gson/api_doc.mustache | 85 ++++++++++++ libraries/okhttp-gson/api_test.mustache | 47 +++++++ 4 files changed, 422 insertions(+), 6 deletions(-) create mode 100644 libraries/okhttp-gson/README.mustache create mode 100644 libraries/okhttp-gson/api_doc.mustache create mode 100644 libraries/okhttp-gson/api_test.mustache diff --git a/libraries/okhttp-gson/README.mustache b/libraries/okhttp-gson/README.mustache new file mode 100644 index 00000000000..441a7849436 --- /dev/null +++ b/libraries/okhttp-gson/README.mustache @@ -0,0 +1,169 @@ +# {{artifactId}} + +{{appName}} +- API version: {{appVersion}} +{{^hideGenerationTimestamp}} + - Build date: {{generatedDate}} +{{/hideGenerationTimestamp}} + +{{#appDescription}}{{{appDescription}}}{{/appDescription}} + +{{#infoUrl}} + For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) +{{/infoUrl}} + +*Automatically generated by the [OpenAPI Generator](https://openapi-generator.tech)* + + +## Requirements + +Building the API client library requires: +1. Java {{#supportJava6}}1.6{{/supportJava6}}{{^supportJava6}}{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}{{/supportJava6}}+ +2. Maven/Gradle + +## Installation + +To install the API client library to your local Maven repository, simply execute: + +```shell +mvn clean install +``` + +To deploy it to a remote Maven repository instead, configure the settings of the repository and execute: + +```shell +mvn clean deploy +``` + +Refer to the [OSSRH Guide](http://central.sonatype.org/pages/ossrh-guide.html) for more information. + +### Maven users + +Add this dependency to your project's POM: + +```xml + + {{{groupId}}} + {{{artifactId}}} + {{{artifactVersion}}} + compile + +``` + +### Gradle users + +Add this dependency to your project's build file: + +```groovy +compile "{{{groupId}}}:{{{artifactId}}}:{{{artifactVersion}}}" +``` + +### Others + +At first generate the JAR by executing: + +```shell +mvn clean package +``` + +Then manually install the following JARs: + +* `target/{{{artifactId}}}-{{{artifactVersion}}}.jar` +* `target/lib/*.jar` + +## Getting Started + +Please follow the [installation](#installation) instruction and execute the following Java code: + +```java +{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}} +import {{{invokerPackage}}}.*; +import {{{invokerPackage}}}.auth.*; +import {{{modelPackage}}}.*; +import {{{package}}}.{{{classname}}}; + +import java.io.File; +import java.util.*; + +public class {{{classname}}}Example { + + public static void main(String[] args) { + {{#hasAuthMethods}}ApiClient defaultClient = Configuration.getDefaultApiClient(); + {{#authMethods}}{{#isBasic}} + // Configure HTTP basic authorization: {{{name}}} + HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setUsername("YOUR USERNAME"); + {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasic}}{{#isApiKey}} + // Configure API key authorization: {{{name}}} + ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setApiKey("YOUR API KEY"); + // Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null) + //{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} + // Configure OAuth2 access token for authorization: {{{name}}} + OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}} + {{/authMethods}} + {{/hasAuthMethods}} + + {{{classname}}} apiInstance = new {{{classname}}}(); + {{#allParams}} + {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} + {{/allParams}} + try { + {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}{{^vendorExtensions.x-group-parameters}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}({{#requiredParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}){{#optionalParams}} + .{{{paramName}}}({{{paramName}}}){{/optionalParams}} + .execute();{{/vendorExtensions.x-group-parameters}}{{#returnType}} + System.out.println(result);{{/returnType}} + } catch (ApiException e) { + System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); + e.printStackTrace(); + } + } +} +{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} +``` + +## Documentation for API Endpoints + +All URIs are relative to *{{basePath}}* + +Class | Method | HTTP request | Description +------------ | ------------- | ------------- | ------------- +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} + +## Documentation for Models + +{{#models}}{{#model}} - [{{classname}}]({{modelDocPath}}{{classname}}.md) +{{/model}}{{/models}} + +## Documentation for Authorization + +{{^authMethods}}All endpoints do not require authorization. +{{/authMethods}}Authentication schemes defined for the API: +{{#authMethods}}### {{name}} + +{{#isApiKey}}- **Type**: API key +- **API key parameter name**: {{keyParamName}} +- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}} +{{/isApiKey}} +{{#isBasic}}- **Type**: HTTP basic authentication +{{/isBasic}} +{{#isOAuth}}- **Type**: OAuth +- **Flow**: {{flow}} +- **Authorization URL**: {{authorizationUrl}} +- **Scopes**: {{^scopes}}N/A{{/scopes}} +{{#scopes}} - {{scope}}: {{description}} +{{/scopes}} +{{/isOAuth}} + +{{/authMethods}} + +## Recommendation + +It's recommended to create an instance of `ApiClient` per thread in a multithreaded environment to avoid any potential issues. + +## Author + +{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} +{{/hasMore}}{{/apis}}{{/apiInfo}} diff --git a/libraries/okhttp-gson/api.mustache b/libraries/okhttp-gson/api.mustache index affaec014b9..16384f1fd39 100644 --- a/libraries/okhttp-gson/api.mustache +++ b/libraries/okhttp-gson/api.mustache @@ -63,7 +63,7 @@ public class {{classname}} { } {{#operation}} - /** + {{^vendorExtensions.x-group-parameters}}/** * Build call for {{operationId}}{{#allParams}} * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}{{/allParams}} * @param progressListener Progress listener @@ -81,7 +81,7 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public com.squareup.okhttp.Call {{operationId}}Call({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ProgressResponseBody.ProgressListener progressListener, final ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException { + public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} com.squareup.okhttp.Call {{operationId}}Call({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ProgressResponseBody.ProgressListener progressListener, final ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException { Object {{localVariablePrefix}}localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}new Object(){{/bodyParam}}; // create path and map variables @@ -185,6 +185,7 @@ public class {{classname}} { {{/performBeanValidation}} } + {{^vendorExtensions.x-group-parameters}} /** * {{summary}} * {{notes}}{{#allParams}} @@ -206,8 +207,9 @@ public class {{classname}} { {{#returnType}}ApiResponse<{{{returnType}}}> {{localVariablePrefix}}resp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} return {{localVariablePrefix}}resp.getData();{{/returnType}} } + {{/vendorExtensions.x-group-parameters}} - /** + {{^vendorExtensions.x-group-parameters}}/** * {{summary}} * {{notes}}{{#allParams}} * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}{{/allParams}} @@ -224,13 +226,13 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { com.squareup.okhttp.Call {{localVariablePrefix}}call = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}null, null); {{#returnType}}Type {{localVariablePrefix}}localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType(); return {{localVariablePrefix}}apiClient.execute({{localVariablePrefix}}call, {{localVariablePrefix}}localVarReturnType);{{/returnType}}{{^returnType}}return {{localVariablePrefix}}apiClient.execute({{localVariablePrefix}}call);{{/returnType}} } - /** + {{^vendorExtensions.x-group-parameters}}/** * {{summary}} (asynchronously) * {{notes}}{{#allParams}} * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}{{/allParams}} @@ -248,7 +250,7 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public com.squareup.okhttp.Call {{operationId}}Async({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ApiCallback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{localVariablePrefix}}callback) throws ApiException { + public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} com.squareup.okhttp.Call {{operationId}}Async({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ApiCallback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{localVariablePrefix}}callback) throws ApiException { ProgressResponseBody.ProgressListener progressListener = null; ProgressRequestBody.ProgressRequestListener progressRequestListener = null; @@ -274,6 +276,119 @@ public class {{classname}} { {{localVariablePrefix}}apiClient.executeAsync({{localVariablePrefix}}call, {{localVariablePrefix}}localVarReturnType, {{localVariablePrefix}}callback);{{/returnType}}{{^returnType}}{{localVariablePrefix}}apiClient.executeAsync({{localVariablePrefix}}call, {{localVariablePrefix}}callback);{{/returnType}} return {{localVariablePrefix}}call; } + {{#vendorExtensions.x-group-parameters}} + + public class API{{operationId}}Request { + {{#requiredParams}} + private final {{{dataType}}} {{localVariablePrefix}}{{paramName}}; + {{/requiredParams}} + {{#optionalParams}} + private {{{dataType}}} {{localVariablePrefix}}{{paramName}}; + {{/optionalParams}} + + private API{{operationId}}Request({{#requiredParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}) { + {{#requiredParams}} + this.{{localVariablePrefix}}{{paramName}} = {{paramName}}; + {{/requiredParams}} + } + + {{#optionalParams}} + /** + * Set {{paramName}} + * @param {{paramName}} {{description}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}) + * @return API{{operationId}}Request + */ + public API{{operationId}}Request {{paramName}}({{{dataType}}} {{paramName}}) { + this.{{localVariablePrefix}}{{paramName}} = {{paramName}}; + return this; + } + + {{/optionalParams}} + /** + * Build call for {{operationId}} + * @param progressListener Progress listener + * @param progressRequestListener Progress request listener + * @return Call to execute + * @throws ApiException If fail to serialize the request body object + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public com.squareup.okhttp.Call buildCall(final ProgressResponseBody.ProgressListener progressListener, final ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException { + return {{operationId}}Call({{#allParams}}{{localVariablePrefix}}{{paramName}}, {{/allParams}}progressListener, progressRequestListener); + } + + /** + * Execute {{operationId}} request{{#returnType}} + * @return {{returnType}}{{/returnType}} + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} execute() throws ApiException { + {{#returnType}}ApiResponse<{{{returnType}}}> {{localVariablePrefix}}resp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + return {{localVariablePrefix}}resp.getData();{{/returnType}} + } + + /** + * Execute {{operationId}} request with HTTP info returned + * @return ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> executeWithHttpInfo() throws ApiException { + return {{operationId}}WithHttpInfo({{#allParams}}{{localVariablePrefix}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + } + + /** + * Execute {{operationId}} request (asynchronously) + * @param callback The callback to be executed when the API call finishes + * @return The request call + * @throws ApiException If fail to process the API call, e.g. serializing the request body object + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public com.squareup.okhttp.Call executeAsync(final ApiCallback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> callback) throws ApiException { + return {{operationId}}Async({{#allParams}}{{localVariablePrefix}}{{paramName}}, {{/allParams}}callback); + } + } + + /** + * {{summary}} + * {{notes}}{{#requiredParams}} + * @param {{paramName}} {{description}} (required){{/requiredParams}} + * @return API{{operationId}}Request + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public API{{operationId}}Request {{operationId}}({{#requiredParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}) { + return new API{{operationId}}Request({{#requiredParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}); + } + {{/vendorExtensions.x-group-parameters}} {{/operation}} } {{/operations}} diff --git a/libraries/okhttp-gson/api_doc.mustache b/libraries/okhttp-gson/api_doc.mustache new file mode 100644 index 00000000000..1292eb3aa84 --- /dev/null +++ b/libraries/okhttp-gson/api_doc.mustache @@ -0,0 +1,85 @@ +# {{classname}}{{#description}} +{{description}}{{/description}} + +All URIs are relative to *{{basePath}}* + +Method | HTTP request | Description +------------- | ------------- | ------------- +{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}} + +{{#operations}} +{{#operation}} + +# **{{operationId}}**{{^vendorExtensions.x-group-parameters}} +> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}} +> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#requiredParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}){{#optionalParams}}.{{paramName}}({{paramName}}){{/optionalParams}}.execute();{{/vendorExtensions.x-group-parameters}} + +{{summary}}{{#notes}} + +{{notes}}{{/notes}} + +### Example +```java +// Import classes:{{#hasAuthMethods}} +//import {{{invokerPackage}}}.ApiClient;{{/hasAuthMethods}} +//import {{{invokerPackage}}}.ApiException;{{#hasAuthMethods}} +//import {{{invokerPackage}}}.Configuration; +//import {{{invokerPackage}}}.auth.*;{{/hasAuthMethods}} +//import {{{package}}}.{{{classname}}}; + +{{#hasAuthMethods}} +ApiClient defaultClient = Configuration.getDefaultApiClient(); +{{#authMethods}}{{#isBasic}} +// Configure HTTP basic authorization: {{{name}}} +HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); +{{{name}}}.setUsername("YOUR USERNAME"); +{{{name}}}.setPassword("YOUR PASSWORD");{{/isBasic}}{{#isApiKey}} +// Configure API key authorization: {{{name}}} +ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); +{{{name}}}.setApiKey("YOUR API KEY"); +// Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null) +//{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} +// Configure OAuth2 access token for authorization: {{{name}}} +OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); +{{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}} +{{/authMethods}} +{{/hasAuthMethods}} + +{{{classname}}} apiInstance = new {{{classname}}}(); +{{#allParams}} +{{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} +{{/allParams}} +try { + {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}{{^vendorExtensions.x-group-parameters}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}({{#requiredParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}){{#optionalParams}} + .{{{paramName}}}({{{paramName}}}){{/optionalParams}} + .execute();{{/vendorExtensions.x-group-parameters}}{{#returnType}} + System.out.println(result);{{/returnType}} +} catch (ApiException e) { + System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); + e.printStackTrace(); +} +``` + +### Parameters +{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} +Name | Type | Description | Notes +------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} +{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{^isContainer}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} +{{/allParams}} + +### Return type + +{{#returnType}}{{#returnTypeIsPrimitive}}**{{returnType}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{returnType}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}null (empty response body){{/returnType}} + +### Authorization + +{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{name}}](../README.md#{{name}}){{^-last}}, {{/-last}}{{/authMethods}} + +### HTTP request headers + + - **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} + - **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} + +{{/operation}} +{{/operations}} diff --git a/libraries/okhttp-gson/api_test.mustache b/libraries/okhttp-gson/api_test.mustache new file mode 100644 index 00000000000..b5693776b59 --- /dev/null +++ b/libraries/okhttp-gson/api_test.mustache @@ -0,0 +1,47 @@ +{{>licenseInfo}} + +package {{package}}; + +import {{invokerPackage}}.ApiException; +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Test; +import org.junit.Ignore; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +@Ignore +public class {{classname}}Test { + + private final {{classname}} api = new {{classname}}(); + + {{#operations}}{{#operation}} + /** + * {{summary}} + * + * {{notes}} + * + * @throws ApiException + * if the Api call fails + */ + @Test + public void {{operationId}}Test() throws ApiException { + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}{{^vendorExtensions.x-group-parameters}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}({{#requiredParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}){{#optionalParams}} + .{{paramName}}({{paramName}}){{/optionalParams}} + .execute();{{/vendorExtensions.x-group-parameters}} + + // TODO: test validations + } + {{/operation}}{{/operations}} +} From d60f85e3f5818c819206289d093b989eaec8ab03 Mon Sep 17 00:00:00 2001 From: Kiran-Sivakumar <43218409+Kiran-Sivakumar@users.noreply.github.com> Date: Tue, 4 Dec 2018 02:33:10 -0800 Subject: [PATCH 066/370] [Java][okhttp-gson] Fix bug when performing OAuth token retry (#1576) * Fix access token retry bug * Update petstore samples * Remove newline * Import Pair and List in RetryingOAuth template * Update petstore samples * Update petstore samples --- libraries/okhttp-gson/auth/RetryingOAuth.mustache | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libraries/okhttp-gson/auth/RetryingOAuth.mustache b/libraries/okhttp-gson/auth/RetryingOAuth.mustache index 4703c2488d0..11ef3c3ca61 100644 --- a/libraries/okhttp-gson/auth/RetryingOAuth.mustache +++ b/libraries/okhttp-gson/auth/RetryingOAuth.mustache @@ -1,5 +1,7 @@ package {{invokerPackage}}.auth; +import {{invokerPackage}}.Pair; + import com.squareup.okhttp.Interceptor; import com.squareup.okhttp.OkHttpClient; import com.squareup.okhttp.Request; @@ -17,6 +19,7 @@ import org.apache.oltu.oauth2.common.message.types.GrantType; import java.io.IOException; import java.net.HttpURLConnection; import java.util.Map; +import java.util.List; public class RetryingOAuth extends OAuth implements Interceptor { private OAuthClient oAuthClient; @@ -162,4 +165,10 @@ public class RetryingOAuth extends OAuth implements Interceptor { public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) { this.tokenRequestBuilder = tokenRequestBuilder; } + + // Applying authorization to parameters is performed in the retryingIntercept method + @Override + public void applyToParams(List queryParams, Map headerParams) { + // No implementation necessary + } } From e9282caf90c6ce8152bb2770f478735ee5911820 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 7 Dec 2018 23:10:35 +0800 Subject: [PATCH 067/370] remove isNotContainer (#1629) --- beanValidation.mustache | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/beanValidation.mustache b/beanValidation.mustache index 7c347758d8d..1bc9afa8f68 100644 --- a/beanValidation.mustache +++ b/beanValidation.mustache @@ -8,9 +8,9 @@ {{/isEnum}} {{/isPrimitiveType}} {{/isContainer}} -{{#isNotContainer}} +{{^isContainer}} {{^isPrimitiveType}} @Valid {{/isPrimitiveType}} -{{/isNotContainer}} +{{/isContainer}} {{>beanValidationCore}} \ No newline at end of file From 94e2b8f5eb6d58df7e2b09ef0c3f81c46dd77415 Mon Sep 17 00:00:00 2001 From: Jim Schubert Date: Fri, 14 Dec 2018 08:23:06 -0500 Subject: [PATCH 068/370] Include mavenCentral in java build.gradle (#1653) the android dep is currently missing from jcenter. This adds mavenCentral as an additional repository to the default java generator's build.gradle. --- build.gradle.mustache | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.gradle.mustache b/build.gradle.mustache index cd79a9afd36..04a9d55cfd7 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -6,6 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { + mavenCentral() jcenter() } dependencies { @@ -15,6 +16,7 @@ buildscript { } repositories { + mavenCentral() jcenter() } From 55ee5a3aab1ddd85fa5c3b3b0ddc0d98fe775008 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Sat, 15 Dec 2018 00:22:11 +0800 Subject: [PATCH 069/370] add mavencentral to build.gradle (#1674) --- libraries/feign/build.gradle.mustache | 1 + libraries/google-api-client/build.gradle.mustache | 1 + libraries/jersey2/build.gradle.mustache | 1 + libraries/okhttp-gson/build.gradle.mustache | 1 + libraries/rest-assured/build.gradle.mustache | 1 + libraries/resteasy/build.gradle.mustache | 1 + libraries/resttemplate/build.gradle.mustache | 1 + libraries/retrofit/build.gradle.mustache | 1 + libraries/retrofit2/build.gradle.mustache | 1 + libraries/vertx/build.gradle.mustache | 1 + 10 files changed, 10 insertions(+) diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index 59bb9c3906d..a5cc03fec83 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -6,6 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { + mavenCentral() jcenter() } dependencies { diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache index 99c91a9c771..b5ffd4dd328 100644 --- a/libraries/google-api-client/build.gradle.mustache +++ b/libraries/google-api-client/build.gradle.mustache @@ -6,6 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { + mavenCentral() jcenter() } dependencies { diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index 46167d5f8d9..8648acc8585 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -6,6 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { + mavenCentral() jcenter() } dependencies { diff --git a/libraries/okhttp-gson/build.gradle.mustache b/libraries/okhttp-gson/build.gradle.mustache index 6bb7a2f5636..4abdee28f2c 100644 --- a/libraries/okhttp-gson/build.gradle.mustache +++ b/libraries/okhttp-gson/build.gradle.mustache @@ -6,6 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { + mavenCentral() jcenter() } dependencies { diff --git a/libraries/rest-assured/build.gradle.mustache b/libraries/rest-assured/build.gradle.mustache index 87608f21024..af9e49e0dfb 100644 --- a/libraries/rest-assured/build.gradle.mustache +++ b/libraries/rest-assured/build.gradle.mustache @@ -6,6 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { + mavenCentral() jcenter() } dependencies { diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index 7f8e2422642..3b407024585 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -6,6 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { + mavenCentral() jcenter() } dependencies { diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index d1110e419d2..db4e6f0eb92 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -6,6 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { + mavenCentral() jcenter() } dependencies { diff --git a/libraries/retrofit/build.gradle.mustache b/libraries/retrofit/build.gradle.mustache index 45da8dd03bb..dc0acee3841 100644 --- a/libraries/retrofit/build.gradle.mustache +++ b/libraries/retrofit/build.gradle.mustache @@ -6,6 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { + mavenCentral() jcenter() } dependencies { diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index 93518d88941..5f6e9dcdae1 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -6,6 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { + mavenCentral() jcenter() } dependencies { diff --git a/libraries/vertx/build.gradle.mustache b/libraries/vertx/build.gradle.mustache index 1f2ebac4399..3f434d70abf 100644 --- a/libraries/vertx/build.gradle.mustache +++ b/libraries/vertx/build.gradle.mustache @@ -5,6 +5,7 @@ group = '{{groupId}}' version = '{{artifactVersion}}' repositories { + mavenCentral() jcenter() } From 76621c3467c574b8930d054f0f640e20b2c0ee9f Mon Sep 17 00:00:00 2001 From: William Cheng Date: Mon, 17 Dec 2018 14:42:04 +0800 Subject: [PATCH 070/370] fix java instantiated lists (#1683) --- pojo.mustache | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pojo.mustache b/pojo.mustache index 2d08f65d6ac..3a0e645b2da 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -58,12 +58,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}"; @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}}) {{/gson}} - {{#isContainer}} - private {{{datatypeWithEnum}}} {{name}}{{#required}} = {{{defaultValue}}}{{/required}}{{^required}} = null{{/required}}; - {{/isContainer}} - {{^isContainer}} private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; - {{/isContainer}} {{/vars}} {{#parcelableModel}} From 0c64a009f3126399808f97e0fca7a6b2a30eac12 Mon Sep 17 00:00:00 2001 From: Akihito Nakano Date: Sun, 23 Dec 2018 20:03:50 +0900 Subject: [PATCH 071/370] [Java] Update dependencies (#1735) * Update retrofit2 refs: https://nvd.nist.gov/vuln/detail/CVE-2018-1000850 https://nvd.nist.gov/vuln/detail/CVE-2018-1000844 * Update samples ./bin/java-petstore-all.sh * Implement okhttp3.Call#timeout refs https://github.com/square/okhttp/pull/4363 * Update samples ./bin/java-petstore-all.sh * Update Play26CallFactory * Fix indent --- libraries/retrofit2/play25/Play25CallFactory.mustache | 9 +++++++++ libraries/retrofit2/play26/Play26CallFactory.mustache | 9 +++++++++ libraries/retrofit2/pom.mustache | 2 +- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/libraries/retrofit2/play25/Play25CallFactory.mustache b/libraries/retrofit2/play25/Play25CallFactory.mustache index 93df7a2718d..fd0057a0e0b 100644 --- a/libraries/retrofit2/play25/Play25CallFactory.mustache +++ b/libraries/retrofit2/play25/Play25CallFactory.mustache @@ -1,8 +1,10 @@ package {{invokerPackage}}; import okhttp3.*; +import okio.AsyncTimeout; import okio.Buffer; import okio.BufferedSource; +import okio.Timeout; import play.libs.ws.WSClient; import play.libs.ws.WSRequest; import play.libs.ws.WSResponse; @@ -96,11 +98,13 @@ public class Play25CallFactory implements okhttp3.Call.Factory { private List filters; private final Request request; + private final AsyncTimeout timeout; public PlayWSCall(WSClient wsClient, List filters, Request request) { this.wsClient = wsClient; this.request = request; this.filters = filters; + this.timeout = new AsyncTimeout(); } @Override @@ -108,6 +112,11 @@ public class Play25CallFactory implements okhttp3.Call.Factory { return request; } + @Override + public Timeout timeout() { + return timeout; + } + @Override public void enqueue(final okhttp3.Callback responseCallback) { final Call call = this; diff --git a/libraries/retrofit2/play26/Play26CallFactory.mustache b/libraries/retrofit2/play26/Play26CallFactory.mustache index 6e4180341bf..b46b3af0eda 100644 --- a/libraries/retrofit2/play26/Play26CallFactory.mustache +++ b/libraries/retrofit2/play26/Play26CallFactory.mustache @@ -1,8 +1,10 @@ package {{invokerPackage}}; import okhttp3.*; +import okio.AsyncTimeout; import okio.Buffer; import okio.BufferedSource; +import okio.Timeout; import play.libs.ws.WSClient; import play.libs.ws.WSRequest; import play.libs.ws.WSResponse; @@ -105,11 +107,13 @@ public class Play26CallFactory implements okhttp3.Call.Factory { private Executor executor = java.util.concurrent.ForkJoinPool.commonPool(); private final Request request; + private final AsyncTimeout timeout; public PlayWSCall(WSClient wsClient, Executor executor, List filters, Request request) { this.wsClient = wsClient; this.request = request; this.filters = filters; + this.timeout = new AsyncTimeout(); if (executor != null) { this.executor = executor; @@ -121,6 +125,11 @@ public class Play26CallFactory implements okhttp3.Call.Factory { return request; } + @Override + public Timeout timeout() { + return timeout; + } + @Override public void enqueue(final okhttp3.Callback responseCallback) { final Call call = this; diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index 4ddee4d014f..b8f9aa0bd6b 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -367,7 +367,7 @@ 2.6.7 {{/play26}} {{/usePlayWS}} - 2.3.0 + 2.5.0 {{#useRxJava}} 1.3.0 {{/useRxJava}} From 9ca62a3625d99dfd7690aa15783ad4f7e8a70062 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Mon, 31 Dec 2018 10:03:05 +0800 Subject: [PATCH 072/370] Add an option to use reflection in equals, hashCode (Java client) (#1767) * add option to use reflection in equals, hashcode (java) * add model test template to java client only * update pestore samples * update java samples * update doc * update usage, remove unused file --- libraries/okhttp-gson/build.gradle.mustache | 1 + libraries/okhttp-gson/build.sbt.mustache | 1 + libraries/okhttp-gson/pom.mustache | 80 +++++++++++---------- model.mustache | 4 ++ model_test.mustache | 48 +++++++++++++ pojo.mustache | 20 +++++- 6 files changed, 114 insertions(+), 40 deletions(-) create mode 100644 model_test.mustache diff --git a/libraries/okhttp-gson/build.gradle.mustache b/libraries/okhttp-gson/build.gradle.mustache index 4abdee28f2c..160f118e304 100644 --- a/libraries/okhttp-gson/build.gradle.mustache +++ b/libraries/okhttp-gson/build.gradle.mustache @@ -125,6 +125,7 @@ dependencies { compile 'com.google.code.gson:gson:2.8.1' compile 'io.gsonfire:gson-fire:1.8.0' compile group: 'org.apache.oltu.oauth2', name: 'org.apache.oltu.oauth2.client', version: '1.0.1' + compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.8.1' {{#joda}} compile 'joda-time:joda-time:2.9.9' {{/joda}} diff --git a/libraries/okhttp-gson/build.sbt.mustache b/libraries/okhttp-gson/build.sbt.mustache index fcf788885d6..172844f9f53 100644 --- a/libraries/okhttp-gson/build.sbt.mustache +++ b/libraries/okhttp-gson/build.sbt.mustache @@ -13,6 +13,7 @@ lazy val root = (project in file(".")). "com.squareup.okhttp" % "okhttp" % "2.7.5", "com.squareup.okhttp" % "logging-interceptor" % "2.7.5", "com.google.code.gson" % "gson" % "2.8.1", + "org.apache.commons" % "commons-lang3" % "3.8.1", {{#joda}} "joda-time" % "joda-time" % "2.9.9" % "compile", {{/joda}} diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index 0cff2363ea3..6a1f7e82d37 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -225,50 +225,55 @@ org.apache.oltu.oauth2.client 1.0.1 + + org.apache.commons + commons-lang3 + ${commons-lang3-version} + {{#joda}} - - joda-time - joda-time - ${jodatime-version} - + + joda-time + joda-time + ${jodatime-version} + {{/joda}} {{#threetenbp}} - - org.threeten - threetenbp - ${threetenbp-version} - + + org.threeten + threetenbp + ${threetenbp-version} + {{/threetenbp}} {{#useBeanValidation}} - - - javax.validation - validation-api - 1.1.0.Final - provided - + + + javax.validation + validation-api + 1.1.0.Final + provided + {{/useBeanValidation}} {{#performBeanValidation}} - - - org.hibernate - hibernate-validator - 5.4.1.Final - - - javax.el - el-api - 2.2 - + + + org.hibernate + hibernate-validator + 5.4.1.Final + + + javax.el + el-api + 2.2 + {{/performBeanValidation}} {{#parcelableModel}} - - - com.google.android - android - 4.1.1.4 - provided - + + + com.google.android + android + 4.1.1.4 + provided + {{/parcelableModel}} @@ -286,11 +291,12 @@ 1.5.18 2.7.5 2.8.1 + 3.8.1 {{#joda}} - 2.9.9 + 2.9.9 {{/joda}} {{#threetenbp}} - 1.3.5 + 1.3.5 {{/threetenbp}} 1.0.0 4.12 diff --git a/model.mustache b/model.mustache index 2154453a885..08429bb58de 100644 --- a/model.mustache +++ b/model.mustache @@ -2,6 +2,10 @@ package {{package}}; +{{#useReflectionEqualsHashCode}} +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +{{/useReflectionEqualsHashCode}} {{^supportJava6}} import java.util.Objects; import java.util.Arrays; diff --git a/model_test.mustache b/model_test.mustache new file mode 100644 index 00000000000..e72796cdb93 --- /dev/null +++ b/model_test.mustache @@ -0,0 +1,48 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +{{#fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * Model tests for {{classname}} + */ +public class {{classname}}Test { + {{#models}} + {{#model}} + {{^isEnum}} + private final {{classname}} model = new {{classname}}(); + + {{/isEnum}} + /** + * Model tests for {{classname}} + */ + @Test + public void test{{classname}}() { + // TODO: test {{classname}} + } + + {{#allVars}} + /** + * Test the property '{{name}}' + */ + @Test + public void {{name}}Test() { + // TODO: test {{name}} + } + + {{/allVars}} + {{/model}} + {{/models}} +} diff --git a/pojo.mustache b/pojo.mustache index 3a0e645b2da..e021bf24b2d 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -148,6 +148,10 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela {{^supportJava6}} @Override public boolean equals(java.lang.Object o) { + {{#useReflectionEqualsHashCode}} + return EqualsBuilder.reflectionEquals(this, o); + {{/useReflectionEqualsHashCode}} + {{^useReflectionEqualsHashCode}} if (this == o) { return true; } @@ -159,11 +163,17 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela {{/hasMore}}{{/vars}}{{#parent}} && super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}} + {{/useReflectionEqualsHashCode}} } @Override public int hashCode() { + {{#useReflectionEqualsHashCode}} + return HashCodeBuilder.reflectionHashCode(this); + {{/useReflectionEqualsHashCode}} + {{^useReflectionEqualsHashCode}} return Objects.hash({{#vars}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{#hasMore}}, {{/hasMore}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); + {{/useReflectionEqualsHashCode}} } {{/supportJava6}} @@ -194,9 +204,13 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class {{classname}} {\n"); - {{#parent}}sb.append(" ").append(toIndentedString(super.toString())).append("\n");{{/parent}} - {{#vars}}sb.append(" {{name}}: ").append(toIndentedString({{name}})).append("\n"); - {{/vars}}sb.append("}"); + {{#parent}} + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + {{/parent}} + {{#vars}} + sb.append(" {{name}}: ").append(toIndentedString({{name}})).append("\n"); + {{/vars}} + sb.append("}"); return sb.toString(); } From f1d8ce8396a23db13d5fab98c2d3c652a058ce56 Mon Sep 17 00:00:00 2001 From: Marco Date: Sat, 5 Jan 2019 11:29:49 +0100 Subject: [PATCH 073/370] [java][webclient] Register Jackson modules on ObjectMapper (#911) * [java][webclient] register jackson modules on object mapper * Regenerate client * Removed findAndRegisterModules() call * ObjectMapper is initialized only if NOT provided by client * Remove (now) useless DateFormat inside buildWebClient signature and regenerate client --- libraries/webclient/ApiClient.mustache | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index 7f91fe44134..ed2dac7fa8c 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -2,6 +2,7 @@ package {{invokerPackage}}; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.core.ParameterizedTypeReference; @@ -88,16 +89,21 @@ public class ApiClient { public ApiClient() { this.dateFormat = createDefaultDateFormat(); - this.webClient = buildWebClient(new ObjectMapper(), dateFormat); + ObjectMapper mapper = new ObjectMapper(); + mapper.setDateFormat(dateFormat); + mapper.registerModule(new JavaTimeModule()); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + + this.webClient = buildWebClient(mapper); this.init(); } public ApiClient(ObjectMapper mapper, DateFormat format) { - this(buildWebClient(mapper.copy(), format), format); + this(buildWebClient(mapper.copy()), format); } public ApiClient(WebClient webClient, ObjectMapper mapper, DateFormat format) { - this(Optional.ofNullable(webClient).orElseGet(() ->buildWebClient(mapper.copy(), format)), format); + this(Optional.ofNullable(webClient).orElseGet(() ->buildWebClient(mapper.copy())), format); } private ApiClient(WebClient webClient, DateFormat format) { @@ -126,9 +132,7 @@ public class ApiClient { * Build the RestTemplate used to make HTTP requests. * @return RestTemplate */ - public static WebClient buildWebClient(ObjectMapper mapper, DateFormat dateFormat) { - mapper.setDateFormat(dateFormat); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + public static WebClient buildWebClient(ObjectMapper mapper) { ExchangeStrategies strategies = ExchangeStrategies .builder() .codecs(clientDefaultCodecsConfigurer -> { From 05083b70848369e5b31bc7a332380b412745cbc1 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Sat, 5 Jan 2019 23:30:59 +0800 Subject: [PATCH 074/370] Fix security issue with dependencies (#1820) * fix security issue with dependency * update samples * update pom and sample --- libraries/feign/build.gradle.mustache | 2 +- libraries/feign/build.sbt.mustache | 2 +- libraries/feign/pom.mustache | 2 +- libraries/google-api-client/build.gradle.mustache | 2 +- libraries/google-api-client/build.sbt.mustache | 2 +- libraries/google-api-client/pom.mustache | 2 +- libraries/jersey2/build.gradle.mustache | 2 +- libraries/jersey2/build.sbt.mustache | 2 +- libraries/jersey2/pom.mustache | 2 +- libraries/resteasy/build.gradle.mustache | 2 +- libraries/resteasy/build.sbt.mustache | 2 +- libraries/resteasy/pom.mustache | 2 +- libraries/resttemplate/build.gradle.mustache | 2 +- libraries/resttemplate/pom.mustache | 2 +- libraries/retrofit2/build.gradle.mustache | 3 ++- libraries/retrofit2/build.sbt.mustache | 2 +- libraries/retrofit2/pom.mustache | 3 ++- libraries/webclient/pom.mustache | 2 +- 18 files changed, 20 insertions(+), 18 deletions(-) diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index a5cc03fec83..c96666e2aa5 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -121,7 +121,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.21" jackson_version = "2.8.11" - jackson_databind_version = "2.8.11.2" + jackson_databind_version = "2.8.11.3" {{#threetenbp}} threepane_version = "2.6.4" {{/threetenbp}} diff --git a/libraries/feign/build.sbt.mustache b/libraries/feign/build.sbt.mustache index 0ab575007dd..2168e3e9f6e 100644 --- a/libraries/feign/build.sbt.mustache +++ b/libraries/feign/build.sbt.mustache @@ -16,7 +16,7 @@ lazy val root = (project in file(".")). "io.github.openfeign.form" % "feign-form" % "2.1.0" % "compile", "com.fasterxml.jackson.core" % "jackson-core" % "2.8.11" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.11" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.2" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.3" % "compile", "com.fasterxml.jackson.datatype" % "jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}" % "2.8.7" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4" % "compile", "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index abf00bbfaaf..ebfe5859b1f 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -303,7 +303,7 @@ {{#useFeign10}}10.0.1{{/useFeign10}}{{^useFeign10}}9.4.0{{/useFeign10}} 2.1.0 2.8.11 - 2.8.11.2 + 2.8.11.3 {{#threetenbp}} 2.6.4 {{/threetenbp}} diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache index b5ffd4dd328..62f9f6b6d4e 100644 --- a/libraries/google-api-client/build.gradle.mustache +++ b/libraries/google-api-client/build.gradle.mustache @@ -121,7 +121,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.21" jackson_version = "2.8.11" - jackson_databind_version = "2.8.11.2" + jackson_databind_version = "2.8.11.3" google_api_client_version = "1.23.0" jersey_common_version = "2.25.1" jodatime_version = "2.9.9" diff --git a/libraries/google-api-client/build.sbt.mustache b/libraries/google-api-client/build.sbt.mustache index ba6d1f459d0..10f26b64932 100644 --- a/libraries/google-api-client/build.sbt.mustache +++ b/libraries/google-api-client/build.sbt.mustache @@ -14,7 +14,7 @@ lazy val root = (project in file(".")). "org.glassfish.jersey.core" % "jersey-common" % "2.25.1", "com.fasterxml.jackson.core" % "jackson-core" % "2.8.11" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.11" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.2" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.3" % "compile", {{#withXml}} "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.8.9" % "compile", {{/withXml}} diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index 2dffd4837bb..db32695d81b 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -296,7 +296,7 @@ 1.23.0 2.25.1 2.8.11 - 2.8.11.2 + 2.8.11.3 {{#joda}} 2.9.9 {{/joda}} diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index 8648acc8585..dfd4cda7506 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -120,7 +120,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.21" jackson_version = "2.8.11" - jackson_databind_version = "2.8.11.2" + jackson_databind_version = "2.8.11.3" {{#supportJava6}} jersey_version = "2.6" commons_io_version=2.5 diff --git a/libraries/jersey2/build.sbt.mustache b/libraries/jersey2/build.sbt.mustache index 035cce0e3ce..64157fb6cb2 100644 --- a/libraries/jersey2/build.sbt.mustache +++ b/libraries/jersey2/build.sbt.mustache @@ -15,7 +15,7 @@ lazy val root = (project in file(".")). "org.glassfish.jersey.media" % "jersey-media-json-jackson" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, "com.fasterxml.jackson.core" % "jackson-core" % "2.8.11" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.11" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.2" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.3" % "compile", {{#joda}} "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.8.9" % "compile", {{/joda}} diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index a912ac6edf4..026b777ec9a 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -333,7 +333,7 @@ 3.6 {{/supportJava6}} 2.8.11 - 2.8.11.2 + 2.8.11.3 {{#threetenbp}} 2.6.4 {{/threetenbp}} diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index 3b407024585..bb64ceda849 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -120,7 +120,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.21" jackson_version = "2.8.11" - jackson_databind_version = "2.8.11.2" + jackson_databind_version = "2.8.11.3" threetenbp_version = "2.6.4" resteasy_version = "3.1.3.Final" {{^java8}} diff --git a/libraries/resteasy/build.sbt.mustache b/libraries/resteasy/build.sbt.mustache index 7b197b46f8e..5f713ff9033 100644 --- a/libraries/resteasy/build.sbt.mustache +++ b/libraries/resteasy/build.sbt.mustache @@ -15,7 +15,7 @@ lazy val root = (project in file(".")). "org.jboss.resteasy" % "resteasy-jackson2-provider" % "3.1.3.Final" % "compile", "com.fasterxml.jackson.core" % "jackson-core" % "2.8.11" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.11" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.2" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.3" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4" % "compile", {{#java8}} "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.8.6" % "compile", diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index c474027a274..07b4a40e39c 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -267,7 +267,7 @@ 1.5.21 3.1.3.Final 2.8.11 - 2.8.11 + 2.8.11.3 2.6.4 {{^java8}} 2.9.9 diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index db4e6f0eb92..d1ea2074850 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -121,7 +121,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.21" jackson_version = "2.8.11" - jackson_databind_version = "2.8.11.2" + jackson_databind_version = "2.8.11.3" spring_web_version = "4.3.9.RELEASE" jodatime_version = "2.9.9" junit_version = "4.12" diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache index 427a815cf4e..600880cb6a0 100644 --- a/libraries/resttemplate/pom.mustache +++ b/libraries/resttemplate/pom.mustache @@ -298,7 +298,7 @@ 1.5.21 4.3.9.RELEASE 2.8.11 - 2.8.11.2 + 2.8.11.3 {{#joda}} 2.9.9 {{/joda}} diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index 5f6e9dcdae1..125f276b399 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -132,7 +132,7 @@ ext { {{/play25}} {{#play26}} jackson_version = "2.8.11" - jackson_databind_version = "2.8.11" + jackson_databind_version = "2.8.11.3" play_version = "2.6.7" {{/play26}} {{/usePlayWS}} @@ -187,6 +187,7 @@ dependencies { compile "com.squareup.retrofit2:converter-jackson:$retrofit_version" compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" compile "com.fasterxml.jackson.datatype:jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}:$jackson_version" {{/usePlayWS}} diff --git a/libraries/retrofit2/build.sbt.mustache b/libraries/retrofit2/build.sbt.mustache index 88e06d154b8..4c7a766cdce 100644 --- a/libraries/retrofit2/build.sbt.mustache +++ b/libraries/retrofit2/build.sbt.mustache @@ -32,7 +32,7 @@ lazy val root = (project in file(".")). "javax.validation" % "validation-api" % "1.1.0.Final" % "compile", "com.fasterxml.jackson.core" % "jackson-core" % "2.8.11" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.11" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.2" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.3" % "compile", {{/play26}} "com.squareup.retrofit2" % "converter-jackson" % "2.3.0" % "compile", {{/usePlayWS}} diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index b8f9aa0bd6b..26ae8a95780 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -287,7 +287,7 @@ com.fasterxml.jackson.core jackson-databind - ${jackson-version} + ${jackson-databind-version} com.fasterxml.jackson.datatype @@ -354,6 +354,7 @@ 1.8.0 1.5.21 {{#usePlayWS}} + 2.8.11.3 {{#play24}} 2.6.6 2.4.11 diff --git a/libraries/webclient/pom.mustache b/libraries/webclient/pom.mustache index bdd59fd4772..d44f942930a 100644 --- a/libraries/webclient/pom.mustache +++ b/libraries/webclient/pom.mustache @@ -132,7 +132,7 @@ 1.5.20 5.0.7.RELEASE 2.8.11 - 2.8.11.2 + 2.8.11.3 4.12 3.1.8.RELEASE 0.7.8.RELEASE From 6c4619be0dafc3b6acbf8b262e9c5d2e1dbbb41a Mon Sep 17 00:00:00 2001 From: William Cheng Date: Tue, 8 Jan 2019 07:51:02 +0800 Subject: [PATCH 075/370] better handle of oauth (#1838) --- libraries/okhttp-gson/ApiClient.mustache | 13 ++++++++++--- libraries/okhttp-gson/build.gradle.mustache | 6 ++++-- libraries/okhttp-gson/build.sbt.mustache | 7 +++++-- libraries/okhttp-gson/pom.mustache | 6 ++++-- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index d2d99dd4477..33081f30a0c 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -18,9 +18,10 @@ import org.threeten.bp.LocalDate; import org.threeten.bp.OffsetDateTime; import org.threeten.bp.format.DateTimeFormatter; {{/threetenbp}} - +{{#hasOAuthMethods}} import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; import org.apache.oltu.oauth2.common.message.types.GrantType; +{{/hasOAuthMethods}} import javax.net.ssl.*; import java.io.File; @@ -92,7 +93,10 @@ public class ApiClient { // Prevent the authentications from being modified. authentications = Collections.unmodifiableMap(authentications); } - {{#authMethods}}{{#isOAuth}} + + {{#hasOAuthMethods}} + {{#oauthMethods}} + {{#-first}} /* * Constructor for ApiClient to support access token retry on 401/403 configured with client ID */ @@ -123,7 +127,10 @@ public class ApiClient { // Prevent the authentications from being modified. authentications = Collections.unmodifiableMap(authentications); } - {{/isOAuth}}{{/authMethods}} + + {{/-first}} + {{/oauthMethods}} + {{/hasOAuthMethods}} private void init() { httpClient = new OkHttpClient(); diff --git a/libraries/okhttp-gson/build.gradle.mustache b/libraries/okhttp-gson/build.gradle.mustache index 160f118e304..11919997d61 100644 --- a/libraries/okhttp-gson/build.gradle.mustache +++ b/libraries/okhttp-gson/build.gradle.mustache @@ -119,12 +119,14 @@ if(hasProperty('target') && target == 'android') { } dependencies { - compile 'io.swagger:swagger-annotations:1.5.17' + compile 'io.swagger:swagger-annotations:1.5.21' compile 'com.squareup.okhttp:okhttp:2.7.5' compile 'com.squareup.okhttp:logging-interceptor:2.7.5' - compile 'com.google.code.gson:gson:2.8.1' + compile 'com.google.code.gson:gson:2.8.5' compile 'io.gsonfire:gson-fire:1.8.0' + {{#hasOAuthMethods}} compile group: 'org.apache.oltu.oauth2', name: 'org.apache.oltu.oauth2.client', version: '1.0.1' + {{/hasOAuthMethods}} compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.8.1' {{#joda}} compile 'joda-time:joda-time:2.9.9' diff --git a/libraries/okhttp-gson/build.sbt.mustache b/libraries/okhttp-gson/build.sbt.mustache index 172844f9f53..921e4cc875a 100644 --- a/libraries/okhttp-gson/build.sbt.mustache +++ b/libraries/okhttp-gson/build.sbt.mustache @@ -9,11 +9,14 @@ lazy val root = (project in file(".")). publishArtifact in (Compile, packageDoc) := false, resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( - "io.swagger" % "swagger-annotations" % "1.5.17", + "io.swagger" % "swagger-annotations" % "1.5.21", "com.squareup.okhttp" % "okhttp" % "2.7.5", "com.squareup.okhttp" % "logging-interceptor" % "2.7.5", - "com.google.code.gson" % "gson" % "2.8.1", + "com.google.code.gson" % "gson" % "2.8.5", "org.apache.commons" % "commons-lang3" % "3.8.1", + {{#hasOAuthMethods}} + "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1", + {{/hasOAuthMethods}} {{#joda}} "joda-time" % "joda-time" % "2.9.9" % "compile", {{/joda}} diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index 6a1f7e82d37..ab8f6b2183d 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -220,11 +220,13 @@ gson-fire ${gson-fire-version} + {{#hasOAuthMethods}} org.apache.oltu.oauth2 org.apache.oltu.oauth2.client 1.0.1 + {{/hasOAuthMethods}} org.apache.commons commons-lang3 @@ -288,9 +290,9 @@ ${java.version} ${java.version} 1.8.0 - 1.5.18 + 1.5.21 2.7.5 - 2.8.1 + 2.8.5 3.8.1 {{#joda}} 2.9.9 From 50644cc809f23cd353713340fae424f006d440e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Wed, 9 Jan 2019 17:47:55 +0100 Subject: [PATCH 076/370] Support for "x-enum-descriptions" (#1752) --- modelEnum.mustache | 5 +++++ modelInnerEnum.mustache | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/modelEnum.mustache b/modelEnum.mustache index 6dd5334b771..3d21e9b2764 100644 --- a/modelEnum.mustache +++ b/modelEnum.mustache @@ -18,6 +18,11 @@ import com.google.gson.stream.JsonWriter; {{/gson}} public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} { {{#allowableValues}}{{#enumVars}} + {{#enumDescription}} + /** + * {{enumDescription}} + */ + {{/enumDescription}} {{{name}}}({{{value}}}){{^-last}}, {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}} diff --git a/modelInnerEnum.mustache b/modelInnerEnum.mustache index aef0f27b89a..71dd9a4df16 100644 --- a/modelInnerEnum.mustache +++ b/modelInnerEnum.mustache @@ -7,6 +7,11 @@ public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} { {{#allowableValues}} {{#enumVars}} + {{#enumDescription}} + /** + * {{enumDescription}} + */ + {{/enumDescription}} {{{name}}}({{{value}}}){{^-last}}, {{/-last}}{{#-last}};{{/-last}} {{/enumVars}} From b225a15967874c83bc525035ed9997104c40ae33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Thu, 10 Jan 2019 15:00:45 +0100 Subject: [PATCH 077/370] [java-client][okhttp-gson] no oauth2 usage when hasOAuthMethods is false (#1872) * Fix Javadoc error * [java-client][okhttp-gson] no oauth2 usage when hasOAuthMethods is false --- libraries/okhttp-gson/ApiClient.mustache | 8 ++++++++ libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache | 2 ++ libraries/okhttp-gson/auth/RetryingOAuth.mustache | 2 ++ 3 files changed, 12 insertions(+) diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index 33081f30a0c..14f55484815 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -53,9 +53,11 @@ import java.util.regex.Pattern; import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; import {{invokerPackage}}.auth.ApiKeyAuth; +{{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; import {{invokerPackage}}.auth.RetryingOAuth; import {{invokerPackage}}.auth.OAuthFlow; +{{/hasOAuthMethods}} public class ApiClient { @@ -117,12 +119,14 @@ public class ApiClient { public ApiClient(String clientId, String clientSecret, Map parameters) { init(); +{{#hasOAuthMethods}} RetryingOAuth retryingOAuth = new RetryingOAuth("{{tokenUrl}}", clientId, OAuthFlow.{{flow}}, clientSecret, parameters); authentications.put( "{{name}}", retryingOAuth ); httpClient.interceptors().add(retryingOAuth); +{{/hasOAuthMethods}} // Prevent the authentications from being modified. authentications = Collections.unmodifiableMap(authentications); @@ -399,12 +403,14 @@ public class ApiClient { * @param accessToken Access token */ public void setAccessToken(String accessToken) { + {{#hasOAuthMethods}} for (Authentication auth : authentications.values()) { if (auth instanceof OAuth) { ((OAuth) auth).setAccessToken(accessToken); return; } } + {{/hasOAuthMethods}} throw new RuntimeException("No OAuth2 authentication configured!"); } @@ -550,6 +556,7 @@ public class ApiClient { return this; } + {{#hasOAuthMethods}} /** * Helper method to configure the token endpoint of the first oauth found in the apiAuthorizations (there should be only one) * @return Token request builder @@ -563,6 +570,7 @@ public class ApiClient { } return null; } + {{/hasOAuthMethods}} /** * Format the given parameter object into string. diff --git a/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache b/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache index 6886c2fc358..5460132cdb1 100644 --- a/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache +++ b/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache @@ -1,3 +1,4 @@ +{{#hasOAuthMethods}} package {{invokerPackage}}.auth; import com.squareup.okhttp.OkHttpClient; @@ -66,3 +67,4 @@ public class OAuthOkHttpClient implements HttpClient { // Nothing to do here } } +{{/hasOAuthMethods}} \ No newline at end of file diff --git a/libraries/okhttp-gson/auth/RetryingOAuth.mustache b/libraries/okhttp-gson/auth/RetryingOAuth.mustache index 11ef3c3ca61..5cf6fe7e294 100644 --- a/libraries/okhttp-gson/auth/RetryingOAuth.mustache +++ b/libraries/okhttp-gson/auth/RetryingOAuth.mustache @@ -1,3 +1,4 @@ +{{#hasOAuthMethods}} package {{invokerPackage}}.auth; import {{invokerPackage}}.Pair; @@ -172,3 +173,4 @@ public class RetryingOAuth extends OAuth implements Interceptor { // No implementation necessary } } +{{/hasOAuthMethods}} \ No newline at end of file From 082f8eabb0289fafc55513917691011b91c9457c Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 16 Jan 2019 20:30:52 +0800 Subject: [PATCH 078/370] [Java] Update okhttp version to the latest (#1897) * update okhttp to latest version * update templates to use okhttp3 * update java samples * fix tests * update tests under CI/samples.ci * add tests to java client * fix bin script to restore test files * fix debugging * add more tests and minor fixes * update samples --- libraries/okhttp-gson/ApiClient.mustache | 79 +++++++++++-------- .../GzipRequestInterceptor.mustache | 2 +- .../okhttp-gson/ProgressRequestBody.mustache | 4 +- .../okhttp-gson/ProgressResponseBody.mustache | 8 +- libraries/okhttp-gson/api.mustache | 30 +++---- .../okhttp-gson/auth/HttpBasicAuth.mustache | 2 +- .../auth/OAuthOkHttpClient.mustache | 12 +-- .../okhttp-gson/auth/RetryingOAuth.mustache | 12 +-- libraries/okhttp-gson/build.gradle.mustache | 4 +- libraries/okhttp-gson/build.sbt.mustache | 4 +- libraries/okhttp-gson/pom.mustache | 6 +- 11 files changed, 86 insertions(+), 77 deletions(-) diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index 14f55484815..f6f9c774762 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -2,10 +2,10 @@ package {{invokerPackage}}; -import com.squareup.okhttp.*; -import com.squareup.okhttp.internal.http.HttpMethod; -import com.squareup.okhttp.logging.HttpLoggingInterceptor; -import com.squareup.okhttp.logging.HttpLoggingInterceptor.Level; +import okhttp3.*; +import okhttp3.internal.http.HttpMethod; +import okhttp3.logging.HttpLoggingInterceptor; +import okhttp3.logging.HttpLoggingInterceptor.Level; import okio.BufferedSink; import okio.Okio; {{#joda}} @@ -457,7 +457,7 @@ public class ApiClient { if (debugging) { loggingInterceptor = new HttpLoggingInterceptor(); loggingInterceptor.setLevel(Level.BODY); - httpClient.interceptors().add(loggingInterceptor); + httpClient = httpClient.newBuilder().addInterceptor(loggingInterceptor).build(); } else { httpClient.interceptors().remove(loggingInterceptor); loggingInterceptor = null; @@ -496,7 +496,7 @@ public class ApiClient { * @return Timeout in milliseconds */ public int getConnectTimeout() { - return httpClient.getConnectTimeout(); + return httpClient.connectTimeoutMillis(); } /** @@ -508,7 +508,7 @@ public class ApiClient { * @return Api client */ public ApiClient setConnectTimeout(int connectionTimeout) { - httpClient.setConnectTimeout(connectionTimeout, TimeUnit.MILLISECONDS); + httpClient = httpClient.newBuilder().connectTimeout(connectionTimeout, TimeUnit.MILLISECONDS).build(); return this; } @@ -518,7 +518,7 @@ public class ApiClient { * @return Timeout in milliseconds */ public int getReadTimeout() { - return httpClient.getReadTimeout(); + return httpClient.readTimeoutMillis(); } /** @@ -530,7 +530,7 @@ public class ApiClient { * @return Api client */ public ApiClient setReadTimeout(int readTimeout) { - httpClient.setReadTimeout(readTimeout, TimeUnit.MILLISECONDS); + httpClient = httpClient.newBuilder().readTimeout(readTimeout, TimeUnit.MILLISECONDS).build(); return this; } @@ -540,7 +540,7 @@ public class ApiClient { * @return Timeout in milliseconds */ public int getWriteTimeout() { - return httpClient.getWriteTimeout(); + return httpClient.writeTimeoutMillis(); } /** @@ -552,13 +552,14 @@ public class ApiClient { * @return Api client */ public ApiClient setWriteTimeout(int writeTimeout) { - httpClient.setWriteTimeout(writeTimeout, TimeUnit.MILLISECONDS); + httpClient = httpClient.newBuilder().writeTimeout(writeTimeout, TimeUnit.MILLISECONDS).build(); return this; } {{#hasOAuthMethods}} /** * Helper method to configure the token endpoint of the first oauth found in the apiAuthorizations (there should be only one) + * * @return Token request builder */ public TokenRequestBuilder getTokenEndPoint() { @@ -693,8 +694,8 @@ public class ApiClient { * @return True if the given MIME is JSON, false otherwise. */ public boolean isJsonMime(String mime) { - String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$"; - return mime != null && (mime.matches(jsonMime) || mime.equals("*/*")); + String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$"; + return mime != null && (mime.matches(jsonMime) || mime.equals("*/*")); } /** @@ -867,8 +868,8 @@ public class ApiClient { * Prepare file for download * * @param response An instance of the Response object - * @throws IOException If fail to prepare file for download * @return Prepared file for the download + * @throws IOException If fail to prepare file for download */ public File prepareDownloadFile(Response response) throws IOException { String filename = null; @@ -911,8 +912,8 @@ public class ApiClient { * * @param Type * @param call An instance of the Call object - * @throws ApiException If fail to execute the call * @return ApiResponse<T> + * @throws ApiException If fail to execute the call */ public ApiResponse execute(Call call) throws ApiException { return execute(call, null); @@ -953,22 +954,22 @@ public class ApiClient { /** * Execute HTTP call asynchronously. * - * @see #execute(Call, Type) * @param Type * @param call The callback to be executed when the API call finishes * @param returnType Return type * @param callback ApiCallback + * @see #execute(Call, Type) */ @SuppressWarnings("unchecked") public void executeAsync(Call call, final Type returnType, final ApiCallback callback) { call.enqueue(new Callback() { @Override - public void onFailure(Request request, IOException e) { + public void onFailure(Call call, IOException e) { callback.onFailure(new ApiException(e), 0, null); } @Override - public void onResponse(Response response) throws IOException { + public void onResponse(Call call, Response response) throws IOException { T result; try { result = (T) handleResponse(response, returnType); @@ -987,9 +988,9 @@ public class ApiClient { * @param Type * @param response Response * @param returnType Return type - * @throws ApiException If the response has an unsuccessful status code or - * fail to deserialize the response body * @return Type + * @throws ApiException If the response has an unsuccessful status code or + * fail to deserialize the response body */ public T handleResponse(Response response, Type returnType) throws ApiException { if (response.isSuccessful()) { @@ -999,7 +1000,7 @@ public class ApiClient { if (response.body() != null) { try { response.body().close(); - } catch (IOException e) { + } catch (Exception e) { throw new ApiException(response.message(), e, response.code(), response.headers().toMultimap()); } } @@ -1090,7 +1091,7 @@ public class ApiClient { Request request = null; - if(progressRequestListener != null && reqBody != null) { + if (progressRequestListener != null && reqBody != null) { ProgressRequestBody progressRequestBody = new ProgressRequestBody(reqBody, progressRequestListener); request = reqBuilder.method(method, progressRequestBody).build(); } else { @@ -1190,7 +1191,7 @@ public class ApiClient { * @return RequestBody */ public RequestBody buildRequestBodyFormEncoding(Map formParams) { - FormEncodingBuilder formBuilder = new FormEncodingBuilder(); + okhttp3.FormBody.Builder formBuilder = new okhttp3.FormBody.Builder(); for (Entry param : formParams.entrySet()) { formBuilder.add(param.getKey(), parameterToString(param.getValue())); } @@ -1205,7 +1206,7 @@ public class ApiClient { * @return RequestBody */ public RequestBody buildRequestBodyMultipart(Map formParams) { - MultipartBuilder mpBuilder = new MultipartBuilder().type(MultipartBuilder.FORM); + MultipartBody.Builder mpBuilder = new MultipartBody.Builder().setType(MultipartBody.FORM); for (Entry param : formParams.entrySet()) { if (param.getValue() instanceof File) { File file = (File) param.getValue(); @@ -1244,16 +1245,23 @@ public class ApiClient { TrustManager[] trustManagers = null; HostnameVerifier hostnameVerifier = null; if (!verifyingSsl) { - TrustManager trustAll = new X509TrustManager() { - @Override - public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {} - @Override - public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {} - @Override - public X509Certificate[] getAcceptedIssuers() { return null; } + trustManagers = new TrustManager[]{ + new X509TrustManager() { + @Override + public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { + } + + @Override + public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { + } + + @Override + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return new java.security.cert.X509Certificate[]{}; + } + } }; SSLContext sslContext = SSLContext.getInstance("TLS"); - trustManagers = new TrustManager[] {trustAll}; hostnameVerifier = new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { @@ -1281,11 +1289,12 @@ public class ApiClient { if (keyManagers != null || trustManagers != null) { SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(keyManagers, trustManagers, new SecureRandom()); - httpClient.setSslSocketFactory(sslContext.getSocketFactory()); + httpClient = httpClient.newBuilder().sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustManagers[0]).build(); } else { - httpClient.setSslSocketFactory(null); + httpClient = httpClient.newBuilder().sslSocketFactory(null, (X509TrustManager) trustManagers[0]).build(); } - httpClient.setHostnameVerifier(hostnameVerifier); + + httpClient = httpClient.newBuilder().hostnameVerifier(hostnameVerifier).build(); } catch (GeneralSecurityException e) { throw new RuntimeException(e); } diff --git a/libraries/okhttp-gson/GzipRequestInterceptor.mustache b/libraries/okhttp-gson/GzipRequestInterceptor.mustache index 61a5b7b0ba2..b633aa8f586 100644 --- a/libraries/okhttp-gson/GzipRequestInterceptor.mustache +++ b/libraries/okhttp-gson/GzipRequestInterceptor.mustache @@ -2,7 +2,7 @@ package {{invokerPackage}}; -import com.squareup.okhttp.*; +import okhttp3.*; import okio.Buffer; import okio.BufferedSink; import okio.GzipSink; diff --git a/libraries/okhttp-gson/ProgressRequestBody.mustache b/libraries/okhttp-gson/ProgressRequestBody.mustache index 0f15c1f415d..d9ceeab12ab 100644 --- a/libraries/okhttp-gson/ProgressRequestBody.mustache +++ b/libraries/okhttp-gson/ProgressRequestBody.mustache @@ -2,8 +2,8 @@ package {{invokerPackage}}; -import com.squareup.okhttp.MediaType; -import com.squareup.okhttp.RequestBody; +import okhttp3.MediaType; +import okhttp3.RequestBody; import java.io.IOException; diff --git a/libraries/okhttp-gson/ProgressResponseBody.mustache b/libraries/okhttp-gson/ProgressResponseBody.mustache index 3f53133697c..34713eca118 100644 --- a/libraries/okhttp-gson/ProgressResponseBody.mustache +++ b/libraries/okhttp-gson/ProgressResponseBody.mustache @@ -2,8 +2,8 @@ package {{invokerPackage}}; -import com.squareup.okhttp.MediaType; -import com.squareup.okhttp.ResponseBody; +import okhttp3.MediaType; +import okhttp3.ResponseBody; import java.io.IOException; @@ -34,12 +34,12 @@ public class ProgressResponseBody extends ResponseBody { } @Override - public long contentLength() throws IOException { + public long contentLength() { return responseBody.contentLength(); } @Override - public BufferedSource source() throws IOException { + public BufferedSource source() { if (bufferedSource == null) { bufferedSource = Okio.buffer(source(responseBody.source())); } diff --git a/libraries/okhttp-gson/api.mustache b/libraries/okhttp-gson/api.mustache index 16384f1fd39..3f60a15b45f 100644 --- a/libraries/okhttp-gson/api.mustache +++ b/libraries/okhttp-gson/api.mustache @@ -81,7 +81,7 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} com.squareup.okhttp.Call {{operationId}}Call({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ProgressResponseBody.ProgressListener progressListener, final ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException { + public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} okhttp3.Call {{operationId}}Call({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ProgressResponseBody.ProgressListener progressListener, final ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException { Object {{localVariablePrefix}}localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}new Object(){{/bodyParam}}; // create path and map variables @@ -125,15 +125,15 @@ public class {{classname}} { {{localVariablePrefix}}localVarHeaderParams.put("Content-Type", {{localVariablePrefix}}localVarContentType); if (progressListener != null) { - apiClient.getHttpClient().networkInterceptors().add(new com.squareup.okhttp.Interceptor() { + apiClient.setHttpClient(apiClient.getHttpClient().newBuilder().addNetworkInterceptor(new okhttp3.Interceptor() { @Override - public com.squareup.okhttp.Response intercept(com.squareup.okhttp.Interceptor.Chain chain) throws IOException { - com.squareup.okhttp.Response originalResponse = chain.proceed(chain.request()); + public okhttp3.Response intercept(okhttp3.Interceptor.Chain chain) throws IOException { + okhttp3.Response originalResponse = chain.proceed(chain.request()); return originalResponse.newBuilder() - .body(new ProgressResponseBody(originalResponse.body(), progressListener)) - .build(); + .body(new ProgressResponseBody(originalResponse.body(), progressListener)) + .build(); } - }); + }).build()); } String[] {{localVariablePrefix}}localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; @@ -144,7 +144,7 @@ public class {{classname}} { @Deprecated {{/isDeprecated}} @SuppressWarnings("rawtypes") - private com.squareup.okhttp.Call {{operationId}}ValidateBeforeCall({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ProgressResponseBody.ProgressListener progressListener, final ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException { + private okhttp3.Call {{operationId}}ValidateBeforeCall({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ProgressResponseBody.ProgressListener progressListener, final ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException { {{^performBeanValidation}} {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set @@ -153,7 +153,7 @@ public class {{classname}} { } {{/required}}{{/allParams}} - com.squareup.okhttp.Call {{localVariablePrefix}}call = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}progressListener, progressRequestListener); + okhttp3.Call {{localVariablePrefix}}call = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}progressListener, progressRequestListener); return {{localVariablePrefix}}call; {{/performBeanValidation}} @@ -168,7 +168,7 @@ public class {{classname}} { parameterValues); if (violations.size() == 0) { - com.squareup.okhttp.Call {{localVariablePrefix}}call = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}progressListener, progressRequestListener); + okhttp3.Call {{localVariablePrefix}}call = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}progressListener, progressRequestListener); return {{localVariablePrefix}}call; } else { @@ -227,7 +227,7 @@ public class {{classname}} { @Deprecated {{/isDeprecated}} public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { - com.squareup.okhttp.Call {{localVariablePrefix}}call = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}null, null); + okhttp3.Call {{localVariablePrefix}}call = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}null, null); {{#returnType}}Type {{localVariablePrefix}}localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType(); return {{localVariablePrefix}}apiClient.execute({{localVariablePrefix}}call, {{localVariablePrefix}}localVarReturnType);{{/returnType}}{{^returnType}}return {{localVariablePrefix}}apiClient.execute({{localVariablePrefix}}call);{{/returnType}} } @@ -250,7 +250,7 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} com.squareup.okhttp.Call {{operationId}}Async({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ApiCallback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{localVariablePrefix}}callback) throws ApiException { + public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} okhttp3.Call {{operationId}}Async({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ApiCallback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{localVariablePrefix}}callback) throws ApiException { ProgressResponseBody.ProgressListener progressListener = null; ProgressRequestBody.ProgressRequestListener progressRequestListener = null; @@ -271,7 +271,7 @@ public class {{classname}} { }; } - com.squareup.okhttp.Call {{localVariablePrefix}}call = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}progressListener, progressRequestListener); + okhttp3.Call {{localVariablePrefix}}call = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}progressListener, progressRequestListener); {{#returnType}}Type {{localVariablePrefix}}localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType(); {{localVariablePrefix}}apiClient.executeAsync({{localVariablePrefix}}call, {{localVariablePrefix}}localVarReturnType, {{localVariablePrefix}}callback);{{/returnType}}{{^returnType}}{{localVariablePrefix}}apiClient.executeAsync({{localVariablePrefix}}call, {{localVariablePrefix}}callback);{{/returnType}} return {{localVariablePrefix}}call; @@ -317,7 +317,7 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public com.squareup.okhttp.Call buildCall(final ProgressResponseBody.ProgressListener progressListener, final ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException { + public okhttp3.Call buildCall(final ProgressResponseBody.ProgressListener progressListener, final ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException { return {{operationId}}Call({{#allParams}}{{localVariablePrefix}}{{paramName}}, {{/allParams}}progressListener, progressRequestListener); } @@ -364,7 +364,7 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public com.squareup.okhttp.Call executeAsync(final ApiCallback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> callback) throws ApiException { + public okhttp3.Call executeAsync(final ApiCallback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> callback) throws ApiException { return {{operationId}}Async({{#allParams}}{{localVariablePrefix}}{{paramName}}, {{/allParams}}callback); } } diff --git a/libraries/okhttp-gson/auth/HttpBasicAuth.mustache b/libraries/okhttp-gson/auth/HttpBasicAuth.mustache index 320903b0319..6356e227a1e 100644 --- a/libraries/okhttp-gson/auth/HttpBasicAuth.mustache +++ b/libraries/okhttp-gson/auth/HttpBasicAuth.mustache @@ -4,7 +4,7 @@ package {{invokerPackage}}.auth; import {{invokerPackage}}.Pair; -import com.squareup.okhttp.Credentials; +import okhttp3.Credentials; import java.util.Map; import java.util.List; diff --git a/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache b/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache index 5460132cdb1..46b2021c958 100644 --- a/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache +++ b/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache @@ -1,11 +1,11 @@ {{#hasOAuthMethods}} package {{invokerPackage}}.auth; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.MediaType; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.RequestBody; -import com.squareup.okhttp.Response; +import okhttp3.OkHttpClient; +import okhttp3.MediaType; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; import org.apache.oltu.oauth2.client.HttpClient; import org.apache.oltu.oauth2.client.request.OAuthClientRequest; @@ -67,4 +67,4 @@ public class OAuthOkHttpClient implements HttpClient { // Nothing to do here } } -{{/hasOAuthMethods}} \ No newline at end of file +{{/hasOAuthMethods}} diff --git a/libraries/okhttp-gson/auth/RetryingOAuth.mustache b/libraries/okhttp-gson/auth/RetryingOAuth.mustache index 5cf6fe7e294..d3f6d90abba 100644 --- a/libraries/okhttp-gson/auth/RetryingOAuth.mustache +++ b/libraries/okhttp-gson/auth/RetryingOAuth.mustache @@ -3,10 +3,10 @@ package {{invokerPackage}}.auth; import {{invokerPackage}}.Pair; -import com.squareup.okhttp.Interceptor; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.Response; +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; import org.apache.oltu.oauth2.client.OAuthClient; import org.apache.oltu.oauth2.client.request.OAuthBearerClientRequest; @@ -99,7 +99,7 @@ public class RetryingOAuth extends OAuth implements Interceptor { String requestAccessToken = getAccessToken(); try { oAuthRequest = - new OAuthBearerClientRequest(request.urlString()). + new OAuthBearerClientRequest(request.url().toString()). setAccessToken(requestAccessToken). buildHeaderMessage(); } catch (OAuthSystemException e) { @@ -173,4 +173,4 @@ public class RetryingOAuth extends OAuth implements Interceptor { // No implementation necessary } } -{{/hasOAuthMethods}} \ No newline at end of file +{{/hasOAuthMethods}} diff --git a/libraries/okhttp-gson/build.gradle.mustache b/libraries/okhttp-gson/build.gradle.mustache index 11919997d61..d4e2dc5f62e 100644 --- a/libraries/okhttp-gson/build.gradle.mustache +++ b/libraries/okhttp-gson/build.gradle.mustache @@ -120,8 +120,8 @@ if(hasProperty('target') && target == 'android') { dependencies { compile 'io.swagger:swagger-annotations:1.5.21' - compile 'com.squareup.okhttp:okhttp:2.7.5' - compile 'com.squareup.okhttp:logging-interceptor:2.7.5' + compile 'com.squareup.okhttp3:okhttp:3.12.1' + compile 'com.squareup.okhttp3:logging-interceptor:3.12.1' compile 'com.google.code.gson:gson:2.8.5' compile 'io.gsonfire:gson-fire:1.8.0' {{#hasOAuthMethods}} diff --git a/libraries/okhttp-gson/build.sbt.mustache b/libraries/okhttp-gson/build.sbt.mustache index 921e4cc875a..d3c8cd23532 100644 --- a/libraries/okhttp-gson/build.sbt.mustache +++ b/libraries/okhttp-gson/build.sbt.mustache @@ -10,8 +10,8 @@ lazy val root = (project in file(".")). resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( "io.swagger" % "swagger-annotations" % "1.5.21", - "com.squareup.okhttp" % "okhttp" % "2.7.5", - "com.squareup.okhttp" % "logging-interceptor" % "2.7.5", + "com.squareup.okhttp3" % "okhttp" % "3.12.1", + "com.squareup.okhttp3" % "logging-interceptor" % "3.12.1", "com.google.code.gson" % "gson" % "2.8.5", "org.apache.commons" % "commons-lang3" % "3.8.1", {{#hasOAuthMethods}} diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index ab8f6b2183d..0cbdeb29fd8 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -201,12 +201,12 @@ ${swagger-core-version} - com.squareup.okhttp + com.squareup.okhttp3 okhttp ${okhttp-version} - com.squareup.okhttp + com.squareup.okhttp3 logging-interceptor ${okhttp-version} @@ -291,7 +291,7 @@ ${java.version} 1.8.0 1.5.21 - 2.7.5 + 3.12.1 2.8.5 3.8.1 {{#joda}} From 4651a19e59e14fdfe995d7b4058d94b5482a59df Mon Sep 17 00:00:00 2001 From: eddy Date: Sun, 20 Jan 2019 16:01:48 +0100 Subject: [PATCH 079/370] SCM and license parameters are now also for resteasy clients available. (#1934) --- libraries/resteasy/pom.mustache | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index 07b4a40e39c..ab5332b4cb6 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -7,9 +7,9 @@ {{artifactId}} {{artifactVersion}} - scm:git:git@github.com:openapitools/openapi-generator.git - scm:git:git@github.com:openapitools/openapi-generator.git - https://openapi-generator.tech + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} {{#parentOverridden}} @@ -19,6 +19,23 @@ {{/parentOverridden}} + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + From 3d6ad91104ea98986784e3a699ce547d8fdb3281 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 25 Jan 2019 21:05:13 +0800 Subject: [PATCH 080/370] Fix customized source folder in Java client (#1978) * fix customized source folder in java client * update samples --- libraries/okhttp-gson/build.gradle.mustache | 9 ++++++++- libraries/okhttp-gson/pom.mustache | 6 ++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/libraries/okhttp-gson/build.gradle.mustache b/libraries/okhttp-gson/build.gradle.mustache index d4e2dc5f62e..c18a2fb9a40 100644 --- a/libraries/okhttp-gson/build.gradle.mustache +++ b/libraries/okhttp-gson/build.gradle.mustache @@ -1,5 +1,8 @@ apply plugin: 'idea' apply plugin: 'eclipse' +{{#sourceFolder}} +apply plugin: 'java' +{{/sourceFolder}} group = '{{groupId}}' version = '{{artifactVersion}}' @@ -18,8 +21,12 @@ buildscript { repositories { jcenter() } +{{#sourceFolder}} +sourceSets { + main.java.srcDirs = ['{{sourceFolder}}'] +} - +{{/sourceFolder}} if(hasProperty('target') && target == 'android') { apply plugin: 'com.android.library' diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index 0cbdeb29fd8..9f9c4b874ca 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -121,8 +121,7 @@ - - src/main/java + {{{sourceFolder}}} @@ -134,8 +133,7 @@ - - src/test/java + src/test/java From 46f8283a5dbf9fd2939314e2f2153e0b08706e06 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Mon, 28 Jan 2019 11:05:37 +0800 Subject: [PATCH 081/370] [Java] Generate OAuth related files only if OAuth security schema is used (#1907) * optionally include oauth files in java client * fix java templates * fix tests * fix CI issues --- ApiClient.mustache | 4 +++ libraries/feign/ApiClient.mustache | 24 +++++++++----- libraries/jersey2/ApiClient.mustache | 4 +++ libraries/resteasy/ApiClient.mustache | 4 +++ libraries/resttemplate/ApiClient.mustache | 4 +++ libraries/retrofit/ApiClient.mustache | 39 +++++++++++++---------- libraries/retrofit2/ApiClient.mustache | 8 +++++ libraries/vertx/ApiClient.mustache | 4 +++ libraries/webclient/ApiClient.mustache | 4 +++ 9 files changed, 71 insertions(+), 24 deletions(-) diff --git a/ApiClient.mustache b/ApiClient.mustache index 544d05e3c74..722b51424f9 100644 --- a/ApiClient.mustache +++ b/ApiClient.mustache @@ -52,7 +52,9 @@ import java.text.DateFormat; import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; import {{invokerPackage}}.auth.ApiKeyAuth; +{{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; +{{/hasOAuthMethods}} {{>generatedAnnotation}} public class ApiClient { @@ -261,6 +263,7 @@ public class ApiClient { throw new RuntimeException("No API key authentication configured!"); } + {{#hasOAuthMethods}} /** * Helper method to set access token for the first OAuth2 authentication. * @param accessToken Access token @@ -275,6 +278,7 @@ public class ApiClient { throw new RuntimeException("No OAuth2 authentication configured!"); } + {{/hasOAuthMethods}} /** * Set the User-Agent header's value (by adding to the default header map). * @param userAgent User agent diff --git a/libraries/feign/ApiClient.mustache b/libraries/feign/ApiClient.mustache index fa1dea42e8a..b812bc05dfb 100644 --- a/libraries/feign/ApiClient.mustache +++ b/libraries/feign/ApiClient.mustache @@ -29,7 +29,9 @@ import feign.jackson.JacksonDecoder; import feign.jackson.JacksonEncoder; import feign.slf4j.Slf4jLogger; import {{invokerPackage}}.auth.*; +{{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth.AccessTokenListener; +{{/hasOAuthMethods}} {{>generatedAnnotation}} public class ApiClient { @@ -104,6 +106,7 @@ public class ApiClient { this.setCredentials(username, password); } + {{#hasOAuthMethods}} /** * Helper constructor for single password oauth2 * @param authName @@ -112,15 +115,16 @@ public class ApiClient { * @param username * @param password */ - public ApiClient(String authName, String clientId, String secret, String username, String password) { - this(authName); - this.getTokenEndPoint() - .setClientId(clientId) - .setClientSecret(secret) - .setUsername(username) - .setPassword(password); - } + public ApiClient(String authName, String clientId, String secret, String username, String password) { + this(authName); + this.getTokenEndPoint() + .setClientId(clientId) + .setClientSecret(secret) + .setUsername(username) + .setPassword(password); + } + {{/hasOAuthMethods}} public String getBasePath() { return basePath; } @@ -248,15 +252,18 @@ public class ApiClient { basicAuth.setCredentials(username, password); return; } + {{#hasOAuthMethods}} if (apiAuthorization instanceof OAuth) { OAuth oauth = (OAuth) apiAuthorization; oauth.getTokenRequestBuilder().setUsername(username).setPassword(password); return; } + {{/hasOAuthMethods}} } throw new RuntimeException("No Basic authentication or OAuth configured!"); } + {{#hasOAuthMethods}} /** * Helper method to configure the token endpoint of the first oauth found in the apiAuthorizations (there should be only one) * @return Token request builder @@ -336,6 +343,7 @@ public class ApiClient { } } + {{/hasOAuthMethods}} /** * Gets request interceptor based on authentication name * @param authName Authentiation name diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index da375a01057..10e0ef6a0c1 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -54,7 +54,9 @@ import java.util.regex.Pattern; import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; import {{invokerPackage}}.auth.ApiKeyAuth; +{{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; +{{/hasOAuthMethods}} {{>generatedAnnotation}} public class ApiClient { @@ -190,6 +192,7 @@ public class ApiClient { throw new RuntimeException("No API key authentication configured!"); } + {{#hasOAuthMethods}} /** * Helper method to set access token for the first OAuth2 authentication. * @param accessToken Access token @@ -204,6 +207,7 @@ public class ApiClient { throw new RuntimeException("No OAuth2 authentication configured!"); } + {{/hasOAuthMethods}} /** * Set the User-Agent header's value (by adding to the default header map). * @param userAgent Http user agent diff --git a/libraries/resteasy/ApiClient.mustache b/libraries/resteasy/ApiClient.mustache index 96ff0f77653..457abc0e1d8 100644 --- a/libraries/resteasy/ApiClient.mustache +++ b/libraries/resteasy/ApiClient.mustache @@ -42,7 +42,9 @@ import org.jboss.resteasy.spi.ResteasyProviderFactory; import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; import {{invokerPackage}}.auth.ApiKeyAuth; +{{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; +{{/hasOAuthMethods}} {{>generatedAnnotation}} public class ApiClient { @@ -200,6 +202,7 @@ public class ApiClient { throw new RuntimeException("No API key authentication configured!"); } + {{#hasOAuthMethods}} /** * Helper method to set access token for the first OAuth2 authentication. * @param accessToken the access token @@ -214,6 +217,7 @@ public class ApiClient { throw new RuntimeException("No OAuth2 authentication configured!"); } + {{/hasOAuthMethods}} /** * Set the User-Agent header's value (by adding to the default header map). * @param userAgent the User-Agent header value diff --git a/libraries/resttemplate/ApiClient.mustache b/libraries/resttemplate/ApiClient.mustache index 11a042ab347..323bae4e6d1 100644 --- a/libraries/resttemplate/ApiClient.mustache +++ b/libraries/resttemplate/ApiClient.mustache @@ -67,7 +67,9 @@ import java.util.TimeZone; import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; import {{invokerPackage}}.auth.ApiKeyAuth; +{{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; +{{/hasOAuthMethods}} {{>generatedAnnotation}} @Component("{{invokerPackage}}.ApiClient") @@ -239,6 +241,7 @@ public class ApiClient { throw new RuntimeException("No API key authentication configured!"); } + {{#hasOAuthMethods}} /** * Helper method to set access token for the first OAuth2 authentication. * @param accessToken the access token @@ -253,6 +256,7 @@ public class ApiClient { throw new RuntimeException("No OAuth2 authentication configured!"); } + {{/hasOAuthMethods}} /** * Set the User-Agent header's value (by adding to the default header map). * @param userAgent the user agent string diff --git a/libraries/retrofit/ApiClient.mustache b/libraries/retrofit/ApiClient.mustache index 7c45e926bcf..ed7a041dfd8 100644 --- a/libraries/retrofit/ApiClient.mustache +++ b/libraries/retrofit/ApiClient.mustache @@ -34,10 +34,11 @@ import com.squareup.okhttp.OkHttpClient; import {{invokerPackage}}.auth.HttpBasicAuth; import {{invokerPackage}}.auth.ApiKeyAuth; +{{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; import {{invokerPackage}}.auth.OAuth.AccessTokenListener; import {{invokerPackage}}.auth.OAuthFlow; - +{{/hasOAuthMethods}} public class ApiClient { @@ -104,6 +105,7 @@ public class ApiClient { this.setCredentials(username, password); } + {{#hasOAuthMethods}} /** * Helper constructor for single password oauth2 * @param authName Authentication name @@ -120,21 +122,22 @@ public class ApiClient { .setUsername(username) .setPassword(password); } - - public void createDefaultAdapter() { - Gson gson = new GsonBuilder() - .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ") - .registerTypeAdapter(DateTime.class, new DateTimeTypeAdapter()) - .registerTypeAdapter(LocalDate.class, new LocalDateTypeAdapter()) - .create(); - - okClient = new OkHttpClient(); - - adapterBuilder = new RestAdapter - .Builder() - .setEndpoint("{{{basePath}}}") - .setClient(new OkClient(okClient)) - .setConverter(new GsonConverterWrapper(gson)); + + {{/hasOAuthMethods}} + public void createDefaultAdapter() { + Gson gson = new GsonBuilder() + .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ") + .registerTypeAdapter(DateTime.class, new DateTimeTypeAdapter()) + .registerTypeAdapter(LocalDate.class, new LocalDateTypeAdapter()) + .create(); + + okClient = new OkHttpClient(); + + adapterBuilder = new RestAdapter + .Builder() + .setEndpoint("{{{basePath}}}") + .setClient(new OkClient(okClient)) + .setConverter(new GsonConverterWrapper(gson)); } public S createService(Class serviceClass) { @@ -168,14 +171,17 @@ public class ApiClient { basicAuth.setCredentials(username, password); return; } + {{#hasOAuthMethods}} if (apiAuthorization instanceof OAuth) { OAuth oauth = (OAuth) apiAuthorization; oauth.getTokenRequestBuilder().setUsername(username).setPassword(password); return; } + {{/hasOAuthMethods}} } } + {{#hasOAuthMethods}} /** * Helper method to configure the token endpoint of the first oauth found in the apiAuthorizations (there should be only one) * @return Token request builder @@ -253,6 +259,7 @@ public class ApiClient { } } } + {{/hasOAuthMethods}} /** * Adds an authorization to be used by the client diff --git a/libraries/retrofit2/ApiClient.mustache b/libraries/retrofit2/ApiClient.mustache index 66d3056e540..727078358c8 100644 --- a/libraries/retrofit2/ApiClient.mustache +++ b/libraries/retrofit2/ApiClient.mustache @@ -27,9 +27,11 @@ import retrofit2.converter.gson.GsonConverterFactory; import retrofit2.converter.scalars.ScalarsConverterFactory; import {{invokerPackage}}.auth.HttpBasicAuth; import {{invokerPackage}}.auth.ApiKeyAuth; +{{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; import {{invokerPackage}}.auth.OAuth.AccessTokenListener; import {{invokerPackage}}.auth.OAuthFlow; +{{/hasOAuthMethods}} import java.io.IOException; import java.lang.annotation.Annotation; @@ -110,6 +112,7 @@ public class ApiClient { this.setCredentials(username, password); } + {{#hasOAuthMethods}} /** * Helper constructor for single password oauth2 * @param authName Authentication name @@ -127,6 +130,7 @@ public class ApiClient { .setPassword(password); } + {{/hasOAuthMethods}} public void createDefaultAdapter() { json = new JSON(); okBuilder = new OkHttpClient.Builder(); @@ -218,15 +222,18 @@ public class ApiClient { basicAuth.setCredentials(username, password); return this; } + {{#hasOAuthMethods}} if (apiAuthorization instanceof OAuth) { OAuth oauth = (OAuth) apiAuthorization; oauth.getTokenRequestBuilder().setUsername(username).setPassword(password); return this; } + {{/hasOAuthMethods}} } return this; } + {{#hasOAuthMethods}} /** * Helper method to configure the token endpoint of the first oauth found in the apiAuthorizations (there should be only one) * @return Token request builder @@ -310,6 +317,7 @@ public class ApiClient { } return this; } + {{/hasOAuthMethods}} /** * Adds an authorization to be used by the client diff --git a/libraries/vertx/ApiClient.mustache b/libraries/vertx/ApiClient.mustache index 3bcf3ede667..9ef6b240d6c 100644 --- a/libraries/vertx/ApiClient.mustache +++ b/libraries/vertx/ApiClient.mustache @@ -3,7 +3,9 @@ package {{invokerPackage}}; import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; import {{invokerPackage}}.auth.ApiKeyAuth; +{{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; +{{/hasOAuthMethods}} import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.type.TypeReference; @@ -219,6 +221,7 @@ public class ApiClient { throw new RuntimeException("No API key authentication configured!"); } + {{#hasOAuthMethods}} /** * Helper method to set access token for the first OAuth2 authentication. * @@ -234,6 +237,7 @@ public class ApiClient { throw new RuntimeException("No OAuth2 authentication configured!"); } + {{/hasOAuthMethods}} /** * Format the given Date object into string. * diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index ed2dac7fa8c..51870fa4925 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -60,7 +60,9 @@ import java.util.TimeZone; import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; import {{invokerPackage}}.auth.ApiKeyAuth; +{{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; +{{/hasOAuthMethods}} {{>generatedAnnotation}} public class ApiClient { @@ -236,6 +238,7 @@ public class ApiClient { throw new RuntimeException("No API key authentication configured!"); } + {{#hasOAuthMethods}} /** * Helper method to set access token for the first OAuth2 authentication. * @param accessToken the access token @@ -250,6 +253,7 @@ public class ApiClient { throw new RuntimeException("No OAuth2 authentication configured!"); } + {{/hasOAuthMethods}} /** * Set the User-Agent header's value (by adding to the default header map). * @param userAgent the user agent string From edc756dff3660c85f20152684f7e3526e68b7810 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 8 Feb 2019 11:51:26 +0800 Subject: [PATCH 082/370] Remove localVarPrefix from Java client (#2045) * remove localVarPrefix from java client * rename local varaible * update samples --- libraries/okhttp-gson/api.mustache | 132 ++++++++++++++--------------- 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/libraries/okhttp-gson/api.mustache b/libraries/okhttp-gson/api.mustache index 3f60a15b45f..6e2c3714c0e 100644 --- a/libraries/okhttp-gson/api.mustache +++ b/libraries/okhttp-gson/api.mustache @@ -44,30 +44,30 @@ import java.util.Map; {{#operations}} public class {{classname}} { - private ApiClient {{localVariablePrefix}}apiClient; + private ApiClient localVarApiClient; public {{classname}}() { this(Configuration.getDefaultApiClient()); } public {{classname}}(ApiClient apiClient) { - this.{{localVariablePrefix}}apiClient = apiClient; + this.localVarApiClient = apiClient; } public ApiClient getApiClient() { - return {{localVariablePrefix}}apiClient; + return localVarApiClient; } public void setApiClient(ApiClient apiClient) { - this.{{localVariablePrefix}}apiClient = apiClient; + this.localVarApiClient = apiClient; } {{#operation}} {{^vendorExtensions.x-group-parameters}}/** * Build call for {{operationId}}{{#allParams}} * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}{{/allParams}} - * @param progressListener Progress listener - * @param progressRequestListener Progress request listener + * @param _progressListener Progress listener + * @param _progressRequestListener Progress request listener * @return Call to execute * @throws ApiException If fail to serialize the request body object {{#isDeprecated}} @@ -81,70 +81,70 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} okhttp3.Call {{operationId}}Call({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ProgressResponseBody.ProgressListener progressListener, final ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException { - Object {{localVariablePrefix}}localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}new Object(){{/bodyParam}}; + public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} okhttp3.Call {{operationId}}Call({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ProgressResponseBody.ProgressListener _progressListener, final ProgressRequestBody.ProgressRequestListener _progressRequestListener) throws ApiException { + Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}new Object(){{/bodyParam}}; // create path and map variables - String {{localVariablePrefix}}localVarPath = "{{{path}}}"{{#pathParams}} - .replaceAll("\\{" + "{{baseName}}" + "\\}", {{localVariablePrefix}}apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; + String localVarPath = "{{{path}}}"{{#pathParams}} + .replaceAll("\\{" + "{{baseName}}" + "\\}", localVarApiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; - {{javaUtilPrefix}}List {{localVariablePrefix}}localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); - {{javaUtilPrefix}}List {{localVariablePrefix}}localVarCollectionQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}List localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}List localVarCollectionQueryParams = new {{javaUtilPrefix}}ArrayList(); {{#queryParams}} if ({{paramName}} != null) { - {{localVariablePrefix}}{{#collectionFormat}}localVarCollectionQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPairs("{{{collectionFormat}}}", {{/collectionFormat}}{{^collectionFormat}}localVarQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPair({{/collectionFormat}}"{{baseName}}", {{paramName}})); + {{#collectionFormat}}localVarCollectionQueryParams.addAll(localVarApiClient.parameterToPairs("{{{collectionFormat}}}", {{/collectionFormat}}{{^collectionFormat}}localVarQueryParams.addAll(localVarApiClient.parameterToPair({{/collectionFormat}}"{{baseName}}", {{paramName}})); } {{/queryParams}} - {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); {{#headerParams}} if ({{paramName}} != null) { - {{localVariablePrefix}}localVarHeaderParams.put("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}})); + localVarHeaderParams.put("{{baseName}}", localVarApiClient.parameterToString({{paramName}})); } {{/headerParams}} - {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarFormParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarFormParams = new {{javaUtilPrefix}}HashMap(); {{#formParams}} if ({{paramName}} != null) { - {{localVariablePrefix}}localVarFormParams.put("{{baseName}}", {{paramName}}); + localVarFormParams.put("{{baseName}}", {{paramName}}); } {{/formParams}} - final String[] {{localVariablePrefix}}localVarAccepts = { + final String[] localVarAccepts = { {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }; - final String {{localVariablePrefix}}localVarAccept = {{localVariablePrefix}}apiClient.selectHeaderAccept({{localVariablePrefix}}localVarAccepts); - if ({{localVariablePrefix}}localVarAccept != null) { - {{localVariablePrefix}}localVarHeaderParams.put("Accept", {{localVariablePrefix}}localVarAccept); + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); } - final String[] {{localVariablePrefix}}localVarContentTypes = { + final String[] localVarContentTypes = { {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} }; - final String {{localVariablePrefix}}localVarContentType = {{localVariablePrefix}}apiClient.selectHeaderContentType({{localVariablePrefix}}localVarContentTypes); - {{localVariablePrefix}}localVarHeaderParams.put("Content-Type", {{localVariablePrefix}}localVarContentType); + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + localVarHeaderParams.put("Content-Type", localVarContentType); - if (progressListener != null) { - apiClient.setHttpClient(apiClient.getHttpClient().newBuilder().addNetworkInterceptor(new okhttp3.Interceptor() { + if (_progressListener != null) { + localVarApiClient.setHttpClient(localVarApiClient.getHttpClient().newBuilder().addNetworkInterceptor(new okhttp3.Interceptor() { @Override public okhttp3.Response intercept(okhttp3.Interceptor.Chain chain) throws IOException { okhttp3.Response originalResponse = chain.proceed(chain.request()); return originalResponse.newBuilder() - .body(new ProgressResponseBody(originalResponse.body(), progressListener)) + .body(new ProgressResponseBody(originalResponse.body(), _progressListener)) .build(); } }).build()); } - String[] {{localVariablePrefix}}localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; - return {{localVariablePrefix}}apiClient.buildCall({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarCollectionQueryParams, {{localVariablePrefix}}localVarPostBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAuthNames, progressRequestListener); + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + return localVarApiClient.buildCall(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAuthNames, _progressRequestListener); } {{#isDeprecated}} @Deprecated {{/isDeprecated}} @SuppressWarnings("rawtypes") - private okhttp3.Call {{operationId}}ValidateBeforeCall({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ProgressResponseBody.ProgressListener progressListener, final ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException { + private okhttp3.Call {{operationId}}ValidateBeforeCall({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ProgressResponseBody.ProgressListener _progressListener, final ProgressRequestBody.ProgressRequestListener _progressRequestListener) throws ApiException { {{^performBeanValidation}} {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set @@ -153,8 +153,8 @@ public class {{classname}} { } {{/required}}{{/allParams}} - okhttp3.Call {{localVariablePrefix}}call = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}progressListener, progressRequestListener); - return {{localVariablePrefix}}call; + okhttp3.Call localVarCall = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}_progressListener, _progressRequestListener); + return localVarCall; {{/performBeanValidation}} {{#performBeanValidation}} @@ -168,8 +168,8 @@ public class {{classname}} { parameterValues); if (violations.size() == 0) { - okhttp3.Call {{localVariablePrefix}}call = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}progressListener, progressRequestListener); - return {{localVariablePrefix}}call; + okhttp3.Call localVarCall = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}_progressListener, _progressRequestListener); + return localVarCall; } else { throw new BeanValidationException((Set) violations); @@ -204,8 +204,8 @@ public class {{classname}} { @Deprecated {{/isDeprecated}} public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { - {{#returnType}}ApiResponse<{{{returnType}}}> {{localVariablePrefix}}resp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} - return {{localVariablePrefix}}resp.getData();{{/returnType}} + {{#returnType}}ApiResponse<{{{returnType}}}> localVarResp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + return localVarResp.getData();{{/returnType}} } {{/vendorExtensions.x-group-parameters}} @@ -227,16 +227,16 @@ public class {{classname}} { @Deprecated {{/isDeprecated}} public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { - okhttp3.Call {{localVariablePrefix}}call = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}null, null); - {{#returnType}}Type {{localVariablePrefix}}localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType(); - return {{localVariablePrefix}}apiClient.execute({{localVariablePrefix}}call, {{localVariablePrefix}}localVarReturnType);{{/returnType}}{{^returnType}}return {{localVariablePrefix}}apiClient.execute({{localVariablePrefix}}call);{{/returnType}} + okhttp3.Call localVarCall = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}null, null); + {{#returnType}}Type localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType(); + return localVarApiClient.execute(localVarCall, localVarReturnType);{{/returnType}}{{^returnType}}return localVarApiClient.execute(localVarCall);{{/returnType}} } {{^vendorExtensions.x-group-parameters}}/** * {{summary}} (asynchronously) * {{notes}}{{#allParams}} * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}{{/allParams}} - * @param callback The callback to be executed when the API call finishes + * @param _callback The callback to be executed when the API call finishes * @return The request call * @throws ApiException If fail to process the API call, e.g. serializing the request body object {{#isDeprecated}} @@ -250,45 +250,45 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} okhttp3.Call {{operationId}}Async({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ApiCallback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{localVariablePrefix}}callback) throws ApiException { + public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} okhttp3.Call {{operationId}}Async({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ApiCallback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> _callback) throws ApiException { - ProgressResponseBody.ProgressListener progressListener = null; - ProgressRequestBody.ProgressRequestListener progressRequestListener = null; + ProgressResponseBody.ProgressListener _progressListener = null; + ProgressRequestBody.ProgressRequestListener _progressRequestListener = null; - if (callback != null) { - progressListener = new ProgressResponseBody.ProgressListener() { + if (_callback != null) { + _progressListener = new ProgressResponseBody.ProgressListener() { @Override public void update(long bytesRead, long contentLength, boolean done) { - callback.onDownloadProgress(bytesRead, contentLength, done); + _callback.onDownloadProgress(bytesRead, contentLength, done); } }; - progressRequestListener = new ProgressRequestBody.ProgressRequestListener() { + _progressRequestListener = new ProgressRequestBody.ProgressRequestListener() { @Override public void onRequestProgress(long bytesWritten, long contentLength, boolean done) { - callback.onUploadProgress(bytesWritten, contentLength, done); + _callback.onUploadProgress(bytesWritten, contentLength, done); } }; } - okhttp3.Call {{localVariablePrefix}}call = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}progressListener, progressRequestListener); - {{#returnType}}Type {{localVariablePrefix}}localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType(); - {{localVariablePrefix}}apiClient.executeAsync({{localVariablePrefix}}call, {{localVariablePrefix}}localVarReturnType, {{localVariablePrefix}}callback);{{/returnType}}{{^returnType}}{{localVariablePrefix}}apiClient.executeAsync({{localVariablePrefix}}call, {{localVariablePrefix}}callback);{{/returnType}} - return {{localVariablePrefix}}call; + okhttp3.Call localVarCall = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}_progressListener, _progressRequestListener); + {{#returnType}}Type localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType(); + localVarApiClient.executeAsync(localVarCall, localVarReturnType, _callback);{{/returnType}}{{^returnType}}localVarApiClient.executeAsync(localVarCall, _callback);{{/returnType}} + return localVarCall; } {{#vendorExtensions.x-group-parameters}} public class API{{operationId}}Request { {{#requiredParams}} - private final {{{dataType}}} {{localVariablePrefix}}{{paramName}}; + private final {{{dataType}}} {{paramName}}; {{/requiredParams}} {{#optionalParams}} - private {{{dataType}}} {{localVariablePrefix}}{{paramName}}; + private {{{dataType}}} {{paramName}}; {{/optionalParams}} private API{{operationId}}Request({{#requiredParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}) { {{#requiredParams}} - this.{{localVariablePrefix}}{{paramName}} = {{paramName}}; + this.{{paramName}} = {{paramName}}; {{/requiredParams}} } @@ -299,15 +299,15 @@ public class {{classname}} { * @return API{{operationId}}Request */ public API{{operationId}}Request {{paramName}}({{{dataType}}} {{paramName}}) { - this.{{localVariablePrefix}}{{paramName}} = {{paramName}}; + this.{{paramName}} = {{paramName}}; return this; } {{/optionalParams}} /** * Build call for {{operationId}} - * @param progressListener Progress listener - * @param progressRequestListener Progress request listener + * @param _progressListener Progress listener + * @param _progressRequestListener Progress request listener * @return Call to execute * @throws ApiException If fail to serialize the request body object {{#isDeprecated}} @@ -317,8 +317,8 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public okhttp3.Call buildCall(final ProgressResponseBody.ProgressListener progressListener, final ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException { - return {{operationId}}Call({{#allParams}}{{localVariablePrefix}}{{paramName}}, {{/allParams}}progressListener, progressRequestListener); + public okhttp3.Call buildCall(final ProgressResponseBody.ProgressListener _progressListener, final ProgressRequestBody.ProgressRequestListener _progressRequestListener) throws ApiException { + return {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}_progressListener, _progressRequestListener); } /** @@ -333,8 +333,8 @@ public class {{classname}} { @Deprecated {{/isDeprecated}} public {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} execute() throws ApiException { - {{#returnType}}ApiResponse<{{{returnType}}}> {{localVariablePrefix}}resp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} - return {{localVariablePrefix}}resp.getData();{{/returnType}} + {{#returnType}}ApiResponse<{{{returnType}}}> localVarResp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + return localVarResp.getData();{{/returnType}} } /** @@ -349,12 +349,12 @@ public class {{classname}} { @Deprecated {{/isDeprecated}} public ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> executeWithHttpInfo() throws ApiException { - return {{operationId}}WithHttpInfo({{#allParams}}{{localVariablePrefix}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); } /** * Execute {{operationId}} request (asynchronously) - * @param callback The callback to be executed when the API call finishes + * @param _callback The callback to be executed when the API call finishes * @return The request call * @throws ApiException If fail to process the API call, e.g. serializing the request body object {{#isDeprecated}} @@ -364,8 +364,8 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public okhttp3.Call executeAsync(final ApiCallback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> callback) throws ApiException { - return {{operationId}}Async({{#allParams}}{{localVariablePrefix}}{{paramName}}, {{/allParams}}callback); + public okhttp3.Call executeAsync(final ApiCallback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> _callback) throws ApiException { + return {{operationId}}Async({{#allParams}}{{paramName}}, {{/allParams}}_callback); } } From f000f34e0d1e3d1a6453d9aa63965e436dacd7c8 Mon Sep 17 00:00:00 2001 From: davidwcarlson Date: Sat, 9 Feb 2019 06:51:44 -0800 Subject: [PATCH 083/370] fix 457 Support for Bearer Auth (#1930) * fix #457 by introducing an HttpBearerAuth object See https://github.com/OpenAPITools/openapi-generator/issues/457 Also https://github.com/OpenAPITools/openapi-generator/issues/1446 for typescript, https://github.com/OpenAPITools/openapi-generator/issues/1577 for python Specs defined as follows currently generate BasicAuth and send an "Authorization: Basic [base64Encode(username + ":" + password)]" header components: securitySchemes: bearer: type: http scheme: bearer This change will generate code which uses a new HttpBearerAuth class, which will send a "Authorization: [scheme] [accessToken]" header. This change is slightly larger and more impactful than simply using OAuth for bearerBearer, but it allows for scheme values other than bearer. This fix was enabled by the recent commit of https://github.com/OpenAPITools/openapi-generator/commit/80ca67cfdac0008282ef756cc069f275883a1c44 This PR is an alternative to https://github.com/OpenAPITools/openapi-generator/pull/1972 * update petstore samples * Update HttpBearerAuth mustache templates and samples * correct the expected number of generated java client files * update the retrofit2 HttpBearerAuth template and samples * Add resttemplate-specific HttpBearerAuth mustache and samples * add vertx-specific HttpBearerAuth template and samples * add java webclient-specific HttpBearerAuth template and samples --- ApiClient.mustache | 20 ++++++++- auth/HttpBearerAuth.mustache | 45 +++++++++++++++++++ libraries/feign/auth/HttpBearerAuth.mustache | 43 ++++++++++++++++++ libraries/jersey2/ApiClient.mustache | 20 ++++++++- .../resttemplate/auth/HttpBearerAuth.mustache | 38 ++++++++++++++++ .../retrofit/auth/HttpBearerAuth.mustache | 42 +++++++++++++++++ .../retrofit2/auth/HttpBearerAuth.mustache | 42 +++++++++++++++++ libraries/vertx/auth/HttpBearerAuth.mustache | 39 ++++++++++++++++ .../webclient/auth/HttpBearerAuth.mustache | 39 ++++++++++++++++ 9 files changed, 324 insertions(+), 4 deletions(-) create mode 100644 auth/HttpBearerAuth.mustache create mode 100644 libraries/feign/auth/HttpBearerAuth.mustache create mode 100644 libraries/resttemplate/auth/HttpBearerAuth.mustache create mode 100644 libraries/retrofit/auth/HttpBearerAuth.mustache create mode 100644 libraries/retrofit2/auth/HttpBearerAuth.mustache create mode 100644 libraries/vertx/auth/HttpBearerAuth.mustache create mode 100644 libraries/webclient/auth/HttpBearerAuth.mustache diff --git a/ApiClient.mustache b/ApiClient.mustache index 722b51424f9..91f479bd581 100644 --- a/ApiClient.mustache +++ b/ApiClient.mustache @@ -51,6 +51,7 @@ import java.text.DateFormat; import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.HttpBearerAuth; import {{invokerPackage}}.auth.ApiKeyAuth; {{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; @@ -102,8 +103,9 @@ public class ApiClient { setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); // Setup authentications (key: authentication name, value: authentication). - authentications = new HashMap();{{#authMethods}}{{#isBasic}} - authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} // Prevent the authentications from being modified. @@ -279,6 +281,20 @@ public class ApiClient { } {{/hasOAuthMethods}} + /** + * Helper method to set access token for the first Bearer authentication. + * @param bearerToken Bearer token + */ + public void setBearerToken(String bearerToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBearerAuth) { + ((HttpBearerAuth) auth).setBearerToken(bearerToken); + return; + } + } + throw new RuntimeException("No Bearer authentication configured!"); + } + /** * Set the User-Agent header's value (by adding to the default header map). * @param userAgent User agent diff --git a/auth/HttpBearerAuth.mustache b/auth/HttpBearerAuth.mustache new file mode 100644 index 00000000000..fe30391d547 --- /dev/null +++ b/auth/HttpBearerAuth.mustache @@ -0,0 +1,45 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; + +import java.util.Map; +import java.util.List; + +{{>generatedAnnotation}} +public class HttpBearerAuth implements Authentication { + private final String scheme; + private String bearerToken; + + public HttpBearerAuth(String scheme) { + this.scheme = scheme; + } + + /** + * Gets the token, which together with the scheme, will be sent as the value of the Authorization header. + */ + public String getBearerToken() { + return bearerToken; + } + + /** + * Sets the token, which together with the scheme, will be sent as the value of the Authorization header. + */ + public void setBearerToken(String bearerToken) { + this.bearerToken = bearerToken; + } + + @Override + public void applyToParams(List queryParams, Map headerParams) { + if(bearerToken == null) { + return; + } + + headerParams.put("Authorization", (scheme != null ? upperCaseBearer(scheme) + " " : "") + bearerToken); + } + + private static String upperCaseBearer(String scheme) { + return ("bearer".equalsIgnoreCase(scheme)) ? "Bearer" : scheme; + } +} diff --git a/libraries/feign/auth/HttpBearerAuth.mustache b/libraries/feign/auth/HttpBearerAuth.mustache new file mode 100644 index 00000000000..2240a5518b5 --- /dev/null +++ b/libraries/feign/auth/HttpBearerAuth.mustache @@ -0,0 +1,43 @@ +package {{invokerPackage}}.auth; + +import feign.RequestInterceptor; +import feign.RequestTemplate; + +/** + * An interceptor that adds the request header needed to use HTTP bearer authentication. + */ +public class HttpBearerAuth implements RequestInterceptor { + private final String scheme; + private String bearerToken; + + public HttpBearerAuth(String scheme) { + this.scheme = scheme; + } + + /** + * Gets the token, which together with the scheme, will be sent as the value of the Authorization header. + */ + public String getBearerToken() { + return bearerToken; + } + + /** + * Sets the token, which together with the scheme, will be sent as the value of the Authorization header. + */ + public void setBearerToken(String bearerToken) { + this.bearerToken = bearerToken; + } + + @Override + public void apply(RequestTemplate template) { + if(bearerToken == null) { + return; + } + + template.header("Authorization", (scheme != null ? upperCaseBearer(scheme) + " " : "") + bearerToken); + } + + private static String upperCaseBearer(String scheme) { + return ("bearer".equalsIgnoreCase(scheme)) ? "Bearer" : scheme; + } +} diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 10e0ef6a0c1..2de4af24edc 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -53,6 +53,7 @@ import java.util.regex.Pattern; import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.HttpBearerAuth; import {{invokerPackage}}.auth.ApiKeyAuth; {{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; @@ -84,8 +85,9 @@ public class ApiClient { setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); // Setup authentications (key: authentication name, value: authentication). - authentications = new HashMap();{{#authMethods}}{{#isBasic}} - authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} // Prevent the authentications from being modified. @@ -193,6 +195,20 @@ public class ApiClient { } {{#hasOAuthMethods}} + /** + * Helper method to set bearer token for the first Bearer authentication. + * @param bearerToken Bearer token + */ + public void setBearerToken(String bearerToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBearerAuth) { + ((HttpBearerAuth) auth).setBearerToken(bearerToken); + return; + } + } + throw new RuntimeException("No Bearer authentication configured!"); + } + /** * Helper method to set access token for the first OAuth2 authentication. * @param accessToken Access token diff --git a/libraries/resttemplate/auth/HttpBearerAuth.mustache b/libraries/resttemplate/auth/HttpBearerAuth.mustache new file mode 100644 index 00000000000..0426b7a6984 --- /dev/null +++ b/libraries/resttemplate/auth/HttpBearerAuth.mustache @@ -0,0 +1,38 @@ +package {{invokerPackage}}.auth; + +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; + +import org.springframework.http.HttpHeaders; +import org.springframework.util.Base64Utils; +import org.springframework.util.MultiValueMap; + +{{>generatedAnnotation}} +public class HttpBearerAuth implements Authentication { + private final String scheme; + private String bearerToken; + + public HttpBearerAuth(String scheme) { + this.scheme = scheme; + } + + public String getBearerToken() { + return bearerToken; + } + + public void setBearerToken(String bearerToken) { + this.bearerToken = bearerToken; + } + + @Override + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams) { + if (bearerToken == null) { + return; + } + headerParams.add(HttpHeaders.AUTHORIZATION, (scheme != null ? upperCaseBearer(scheme) + " " : "") + bearerToken); + } + + private static String upperCaseBearer(String scheme) { + return ("bearer".equalsIgnoreCase(scheme)) ? "Bearer" : scheme; + } +} diff --git a/libraries/retrofit/auth/HttpBearerAuth.mustache b/libraries/retrofit/auth/HttpBearerAuth.mustache new file mode 100644 index 00000000000..9b910c461cb --- /dev/null +++ b/libraries/retrofit/auth/HttpBearerAuth.mustache @@ -0,0 +1,42 @@ +package {{invokerPackage}}.auth; + +import java.io.IOException; + +import com.squareup.okhttp.Interceptor; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; + +public class HttpBearerAuth implements Interceptor { + private final String scheme; + private String bearerToken; + + public HttpBearerAuth(String scheme) { + this.scheme = scheme; + } + + public String getBearerToken() { + return bearerToken; + } + + public void setBearerToken(String bearerToken) { + this.bearerToken = bearerToken; + } + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + + // If the request already have an authorization (eg. Basic auth), do nothing + if (request.header("Authorization") == null && bearerToken != null) { + request = request.newBuilder() + .addHeader("Authorization", (scheme != null ? upperCaseBearer(scheme) + " " : "") + bearerToken) + .build(); + } + return chain.proceed(request); + } + + private static String upperCaseBearer(String scheme) { + return ("bearer".equalsIgnoreCase(scheme)) ? "Bearer" : scheme; + } + +} diff --git a/libraries/retrofit2/auth/HttpBearerAuth.mustache b/libraries/retrofit2/auth/HttpBearerAuth.mustache new file mode 100644 index 00000000000..da1bef57a52 --- /dev/null +++ b/libraries/retrofit2/auth/HttpBearerAuth.mustache @@ -0,0 +1,42 @@ +package {{invokerPackage}}.auth; + +import java.io.IOException; + +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +public class HttpBearerAuth implements Interceptor { + private final String scheme; + private String bearerToken; + + public HttpBearerAuth(String scheme) { + this.scheme = scheme; + } + + public String getBearerToken() { + return bearerToken; + } + + public void setBearerToken(String bearerToken) { + this.bearerToken = bearerToken; + } + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + + // If the request already have an authorization (eg. Basic auth), do nothing + if (request.header("Authorization") == null && bearerToken != null) { + request = request.newBuilder() + .addHeader("Authorization", (scheme != null ? upperCaseBearer(scheme) + " " : "") + bearerToken) + .build(); + } + return chain.proceed(request); + } + + private static String upperCaseBearer(String scheme) { + return ("bearer".equalsIgnoreCase(scheme)) ? "Bearer" : scheme; + } + +} diff --git a/libraries/vertx/auth/HttpBearerAuth.mustache b/libraries/vertx/auth/HttpBearerAuth.mustache new file mode 100644 index 00000000000..3dfc23800a6 --- /dev/null +++ b/libraries/vertx/auth/HttpBearerAuth.mustache @@ -0,0 +1,39 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import io.vertx.core.MultiMap; +import java.util.Base64; +import java.nio.charset.StandardCharsets; +import java.util.List; + +{{>generatedAnnotation}} +public class HttpBearerAuth implements Authentication { + private final String scheme; + private String bearerToken; + + public HttpBearerAuth(String scheme) { + this.scheme = scheme; + } + + public String getBearerToken() { + return bearerToken; + } + + public void setBearerToken(String bearerToken) { + this.bearerToken = bearerToken; + } + + @Override + public void applyToParams(List queryParams, MultiMap headerParams) { + if (bearerToken == null) { + return; + } + headerParams.add("Authorization", (scheme != null ? upperCaseBearer(scheme) + " " : "") + bearerToken); + } + + private static String upperCaseBearer(String scheme) { + return ("bearer".equalsIgnoreCase(scheme)) ? "Bearer" : scheme; + } +} diff --git a/libraries/webclient/auth/HttpBearerAuth.mustache b/libraries/webclient/auth/HttpBearerAuth.mustache new file mode 100644 index 00000000000..67d5c6c56d0 --- /dev/null +++ b/libraries/webclient/auth/HttpBearerAuth.mustache @@ -0,0 +1,39 @@ +package {{invokerPackage}}.auth; + +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; + +import org.springframework.http.HttpHeaders; +import org.springframework.util.Base64Utils; +import org.springframework.util.MultiValueMap; + +{{>generatedAnnotation}} +public class HttpBearerAuth implements Authentication { + private final String scheme; + private String bearerToken; + + public HttpBearerAuth(String scheme) { + this.scheme = scheme; + } + + public String getBearerToken() { + return bearerToken; + } + + public void setBearerToken(String bearerToken) { + this.bearerToken = bearerToken; + } + + @Override + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams) { + if (bearerToken == null) { + return; + } + headerParams.add(HttpHeaders.AUTHORIZATION, (scheme != null ? upperCaseBearer(scheme) + " " : "") + bearerToken); + } + + private static String upperCaseBearer(String scheme) { + return ("bearer".equalsIgnoreCase(scheme)) ? "Bearer" : scheme; + } + +} From 7ce3dd4f9b4560e361ae42340b611e6445b3b929 Mon Sep 17 00:00:00 2001 From: Jacob Weber Date: Mon, 18 Feb 2019 05:30:56 -0800 Subject: [PATCH 084/370] okhttp-gson: allow array parameters in path using collectionFormat (#2137) * okhttp-gson: allow array parameters in path using collectionFormat * run bin/java-petstore-okhttp-gson-parcelable.sh --- libraries/okhttp-gson/ApiClient.mustache | 34 ++++++++++++++++++++++++ libraries/okhttp-gson/api.mustache | 2 +- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index f6f9c774762..c998ecde892 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -671,6 +671,40 @@ public class ApiClient { return params; } + /** + * Formats the specified collection path parameter to a string value. + * + * @param collectionFormat The collection format of the parameter. + * @param value The value of the parameter. + * @return String representation of the parameter + */ + public String collectionPathParameterToString(String collectionFormat, Collection value) { + // create the value based on the collection format + if ("multi".equals(collectionFormat)) { + // not valid for path params + return parameterToString(value); + } + + // collectionFormat is assumed to be "csv" by default + String delimiter = ","; + + if ("ssv".equals(collectionFormat)) { + delimiter = " "; + } else if ("tsv".equals(collectionFormat)) { + delimiter = "\t"; + } else if ("pipes".equals(collectionFormat)) { + delimiter = "|"; + } + + StringBuilder sb = new StringBuilder() ; + for (Object item : value) { + sb.append(delimiter); + sb.append(parameterToString(item)); + } + + return sb.substring(delimiter.length()); + } + /** * Sanitize filename by removing path. * e.g. ../../sun.gif becomes sun.gif diff --git a/libraries/okhttp-gson/api.mustache b/libraries/okhttp-gson/api.mustache index 6e2c3714c0e..a06c2e35d59 100644 --- a/libraries/okhttp-gson/api.mustache +++ b/libraries/okhttp-gson/api.mustache @@ -86,7 +86,7 @@ public class {{classname}} { // create path and map variables String localVarPath = "{{{path}}}"{{#pathParams}} - .replaceAll("\\{" + "{{baseName}}" + "\\}", localVarApiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; + .replaceAll("\\{" + "{{baseName}}" + "\\}", localVarApiClient.escapeString({{#collectionFormat}}localVarApiClient.collectionPathParameterToString("{{{collectionFormat}}}", {{{paramName}}}){{/collectionFormat}}{{^collectionFormat}}{{{paramName}}}.toString(){{/collectionFormat}})){{/pathParams}}; {{javaUtilPrefix}}List localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); {{javaUtilPrefix}}List localVarCollectionQueryParams = new {{javaUtilPrefix}}ArrayList(); From b03e2dda230f39ad11bd5d2ea8e403fe07c1b575 Mon Sep 17 00:00:00 2001 From: victor-xplore Date: Tue, 19 Feb 2019 15:00:27 +0100 Subject: [PATCH 085/370] rest-template: allow array parameters in path using collectionFormat (#2177) * 2125: java-resttemplate: Support collection formats in pathParams * run ./bin/java-petstore-resttemplate.sh run ./bin/java-petstore-resttemplate-withxml.sh --- libraries/resttemplate/ApiClient.mustache | 58 ++++++++++++++++------- libraries/resttemplate/api.mustache | 10 ++-- 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/libraries/resttemplate/ApiClient.mustache b/libraries/resttemplate/ApiClient.mustache index 323bae4e6d1..cdf398a0d58 100644 --- a/libraries/resttemplate/ApiClient.mustache +++ b/libraries/resttemplate/ApiClient.mustache @@ -86,11 +86,11 @@ public class ApiClient { return StringUtils.collectionToDelimitedString(collection, separator); } } - + private boolean debugging = false; - + private HttpHeaders defaultHeaders = new HttpHeaders(); - + private String basePath = "{{basePath}}"; private RestTemplate restTemplate; @@ -99,20 +99,20 @@ public class ApiClient { private HttpStatus statusCode; private MultiValueMap responseHeaders; - + private DateFormat dateFormat; public ApiClient() { this.restTemplate = buildRestTemplate(); init(); } - + @Autowired public ApiClient(RestTemplate restTemplate) { this.restTemplate = restTemplate; init(); } - + protected void init() { // Use RFC3339 format for date and datetime. // See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14 @@ -132,7 +132,7 @@ public class ApiClient { // Prevent the authentications from being modified. authentications = Collections.unmodifiableMap(authentications); } - + /** * Get the current base path * @return String the base path @@ -281,7 +281,7 @@ public class ApiClient { defaultHeaders.add(name, value); return this; } - + public void setDebugging(boolean debugging) { List currentInterceptors = this.restTemplate.getInterceptors(); if(debugging) { @@ -339,7 +339,7 @@ public class ApiClient { {{/threetenbp}} return this; } - + /** * Parse the given string into Date object. */ @@ -382,6 +382,28 @@ public class ApiClient { } } + /** + * Formats the specified collection path parameter to a string value. + * + * @param collectionFormat The collection format of the parameter. + * @param value The value of the parameter. + * @return String representation of the parameter + */ + public String collectionPathParameterToString(CollectionFormat collectionFormat, Collection values) { + // create the value based on the collection format + if (CollectionFormat.MULTI.equals(collectionFormat)) { + // not valid for path params + return parameterToString(values); + } + + // collectionFormat is assumed to be "csv" by default + if(collectionFormat == null) { + collectionFormat = CollectionFormat.CSV; + } + + return collectionFormat.collectionToString(values); + } + /** * Converts a parameter to a {@link MultiValueMap} for use in REST requests * @param collectionFormat The format to convert to @@ -531,7 +553,7 @@ public class ApiClient { */ public T invokeAPI(String path, HttpMethod method, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { updateParamsForAuth(authNames, queryParams, headerParams); - + final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(path); if (queryParams != null) { //encode the query parameters in case they contain unsafe characters @@ -548,14 +570,14 @@ public class ApiClient { } builder.queryParams(queryParams); } - + URI uri; try { uri = new URI(builder.build().toUriString()); } catch(URISyntaxException ex) { throw new RestClientException("Could not build URL: " + builder.toUriString(), ex); } - + final BodyBuilder requestBuilder = RequestEntity.method(method, uri); if(accept != null) { requestBuilder.accept(accept.toArray(new MediaType[accept.size()])); @@ -563,14 +585,14 @@ public class ApiClient { if(contentType != null) { requestBuilder.contentType(contentType); } - + addHeadersToRequest(headerParams, requestBuilder); addHeadersToRequest(defaultHeaders, requestBuilder); - + RequestEntity requestEntity = requestBuilder.body(selectBody(body, formParams, contentType)); ResponseEntity responseEntity = restTemplate.exchange(requestEntity, returnType); - + statusCode = responseEntity.getStatusCode(); responseHeaders = responseEntity.getHeaders(); @@ -586,7 +608,7 @@ public class ApiClient { throw new RestClientException("API returned " + statusCode + " and it wasn't handled by the RestTemplate error handler"); } } - + /** * Add headers to the request that is being built * @param headers The headers to add @@ -649,7 +671,7 @@ public class ApiClient { auth.applyToParams(queryParams, headerParams); } } - + private class ApiClientHttpRequestInterceptor implements ClientHttpRequestInterceptor { private final Log log = LogFactory.getLog(ApiClientHttpRequestInterceptor.class); @@ -688,7 +710,7 @@ public class ApiClient { builder.setLength(builder.length() - 1); // Get rid of trailing comma return builder.toString(); } - + private String bodyToString(InputStream body) throws IOException { StringBuilder builder = new StringBuilder(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(body, StandardCharsets.UTF_8)); diff --git a/libraries/resttemplate/api.mustache b/libraries/resttemplate/api.mustache index beede4b55b1..e52b822b106 100644 --- a/libraries/resttemplate/api.mustache +++ b/libraries/resttemplate/api.mustache @@ -71,20 +71,20 @@ public class {{classname}} { {{/required}}{{/allParams}}{{#hasPathParams}} // create path and map variables final Map uriVariables = new HashMap();{{#pathParams}} - uriVariables.put("{{baseName}}", {{{paramName}}});{{/pathParams}}{{/hasPathParams}} + uriVariables.put("{{baseName}}", {{#collectionFormat}}apiClient.collectionPathParameterToString(ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase()), {{{paramName}}}){{/collectionFormat}}{{^collectionFormat}}{{{paramName}}}{{/collectionFormat}});{{/pathParams}}{{/hasPathParams}} String {{localVariablePrefix}}path = UriComponentsBuilder.fromPath("{{{path}}}"){{#hasPathParams}}.buildAndExpand(uriVariables){{/hasPathParams}}{{^hasPathParams}}.build(){{/hasPathParams}}.toUriString(); - + final MultiValueMap {{localVariablePrefix}}queryParams = new LinkedMultiValueMap(); final HttpHeaders {{localVariablePrefix}}headerParams = new HttpHeaders(); final MultiValueMap {{localVariablePrefix}}formParams = new LinkedMultiValueMap();{{#hasQueryParams}} - + {{#queryParams}}{{localVariablePrefix}}queryParams.putAll({{localVariablePrefix}}apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{#hasMore}} {{/hasMore}}{{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}} - + {{#headerParams}}if ({{paramName}} != null) {{localVariablePrefix}}headerParams.add("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}}));{{#hasMore}} {{/hasMore}}{{/headerParams}}{{/hasHeaderParams}}{{#hasFormParams}} - + {{#formParams}}if ({{paramName}} != null) {{localVariablePrefix}}formParams.add("{{baseName}}", {{#isFile}}new FileSystemResource({{paramName}}){{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} {{/hasMore}}{{/formParams}}{{/hasFormParams}} From 231dd18d1f78f26f0d761827bb33a2b9ea65338f Mon Sep 17 00:00:00 2001 From: Lukas Steinbrecher Date: Tue, 19 Feb 2019 15:47:22 +0100 Subject: [PATCH 086/370] Enable error handling in Java WebClient library, fixes #1243 (#1244) * enable error handling in Java WebClient library, fixes #1243 * remove custom error handling logic in Java WebClient library, fixes #1243 --- libraries/webclient/ApiClient.mustache | 35 ++------------------------ 1 file changed, 2 insertions(+), 33 deletions(-) diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index 51870fa4925..bb7a3261c2e 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -478,22 +478,7 @@ public class ApiClient { */ public Mono invokeAPI(String path, HttpMethod method, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { final WebClient.RequestBodySpec requestBuilder = prepareRequest(path, method, queryParams, body, headerParams, formParams, accept, contentType, authNames); - - return requestBuilder.exchange() - .flatMap(response -> { - HttpStatus statusCode = response.statusCode(); - if (response.statusCode() == HttpStatus.NO_CONTENT) { - return Mono.empty(); - } else if (statusCode.is2xxSuccessful()) { - if (returnType == null) { - return Mono.empty(); - } else { - return response.bodyToMono(returnType); - } - } else { - return Mono.error(new RestClientException("API returned " + statusCode + " and it wasn't handled by the RestTemplate error handler")); - } - }); + return requestBuilder.retrieve().bodyToMono(returnType); } /** @@ -514,23 +499,7 @@ public class ApiClient { */ public Flux invokeFluxAPI(String path, HttpMethod method, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { final WebClient.RequestBodySpec requestBuilder = prepareRequest(path, method, queryParams, body, headerParams, formParams, accept, contentType, authNames); - - return requestBuilder.exchange() - .flatMapMany(response -> { - HttpStatus statusCode = response.statusCode(); - ClientResponse.Headers headers = response.headers(); - if (response.statusCode() == HttpStatus.NO_CONTENT) { - return Flux.empty(); - } else if (statusCode.is2xxSuccessful()) { - if (returnType == null) { - return Flux.empty(); - } else { - return response.bodyToFlux(returnType); - } - } else { - return Flux.error(new RestClientException("API returned " + statusCode + " and it wasn't handled by the RestTemplate error handler")); - } - }); + return requestBuilder.retrieve().bodyToFlux(returnType); } private WebClient.RequestBodySpec prepareRequest(String path, HttpMethod method, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames) { From 08c00b2d3ff04a422e64f3511d5823ee7b41f82d Mon Sep 17 00:00:00 2001 From: Vincent Devos <46601673+karismann@users.noreply.github.com> Date: Thu, 7 Mar 2019 10:00:30 +0100 Subject: [PATCH 087/370] [Java] Bean Validation for decimalmin/max incorrect when exclusive set (#2115) the exclusiveMinimum openApi properties is not mapped in bean validation annotation templates --- beanValidationCore.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beanValidationCore.mustache b/beanValidationCore.mustache index 8bcdce3df16..d107c037b9a 100644 --- a/beanValidationCore.mustache +++ b/beanValidationCore.mustache @@ -17,4 +17,4 @@ isInteger set isLong set }}{{#isLong}}{{#minimum}} @Min({{minimum}}L){{/minimum}}{{#maximum}} @Max({{maximum}}L){{/maximum}}{{/isLong}}{{! Not Integer, not Long => we have a decimal value! -}}{{^isInteger}}{{^isLong}}{{#minimum}} @DecimalMin("{{minimum}}"){{/minimum}}{{#maximum}} @DecimalMax("{{maximum}}"){{/maximum}}{{/isLong}}{{/isInteger}} \ No newline at end of file +}}{{^isInteger}}{{^isLong}}{{#minimum}} @DecimalMin({{#exclusiveMinimum}}value={{/exclusiveMinimum}}"{{minimum}}"{{#exclusiveMinimum}},inclusive=false{{/exclusiveMinimum}}){{/minimum}}{{#maximum}} @DecimalMax({{#exclusiveMinimum}}value={{/exclusiveMinimum}}"{{maximum}}"{{#exclusiveMinimum}},inclusive=false{{/exclusiveMinimum}}){{/maximum}}{{/isLong}}{{/isInteger}} \ No newline at end of file From 0ad939403cbc5020a2a9a4fea1be6772ae4ff499 Mon Sep 17 00:00:00 2001 From: Elliot Lee Date: Mon, 11 Mar 2019 18:27:47 -0700 Subject: [PATCH 088/370] [Java] Update Javadocs for HttpBearerAuth (#2364) --- auth/HttpBearerAuth.mustache | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/auth/HttpBearerAuth.mustache b/auth/HttpBearerAuth.mustache index fe30391d547..1d195865439 100644 --- a/auth/HttpBearerAuth.mustache +++ b/auth/HttpBearerAuth.mustache @@ -18,6 +18,8 @@ public class HttpBearerAuth implements Authentication { /** * Gets the token, which together with the scheme, will be sent as the value of the Authorization header. + * + * @return The bearer token */ public String getBearerToken() { return bearerToken; @@ -25,6 +27,8 @@ public class HttpBearerAuth implements Authentication { /** * Sets the token, which together with the scheme, will be sent as the value of the Authorization header. + * + * @param bearerToken The bearer token to send in the Authorization header */ public void setBearerToken(String bearerToken) { this.bearerToken = bearerToken; From 5d9a42139eceb96e642efd79daf9fa7ff1225898 Mon Sep 17 00:00:00 2001 From: Jens Oberender Date: Tue, 12 Mar 2019 04:57:57 +0100 Subject: [PATCH 089/370] Port of @ngaya-ll 's pull request from swagger to openapi. (#2356) See https://github.com/swagger-api/swagger-codegen/pull/8053 --- libraries/okhttp-gson/ApiClient.mustache | 45 ++++++++++++---- .../okhttp-gson/ProgressRequestBody.mustache | 12 ++--- .../okhttp-gson/ProgressResponseBody.mustache | 12 ++--- libraries/okhttp-gson/api.mustache | 52 ++++--------------- 4 files changed, 54 insertions(+), 67 deletions(-) diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index c998ecde892..bdae7a66aa7 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -136,7 +136,9 @@ public class ApiClient { {{/oauthMethods}} {{/hasOAuthMethods}} private void init() { - httpClient = new OkHttpClient(); + OkHttpClient.Builder builder = new OkHttpClient.Builder(); + builder.addInterceptor(getProgressInterceptor()); + httpClient = builder.build(); {{#useGzipFeature}} // Enable gzip request compression @@ -189,7 +191,7 @@ public class ApiClient { * @return Api Client */ public ApiClient setHttpClient(OkHttpClient httpClient) { - this.httpClient = httpClient; + this.httpClient = httpClient.newBuilder().addInterceptor(getProgressInterceptor()).build(); return this; } @@ -1066,12 +1068,12 @@ public class ApiClient { * @param headerParams The header parameters * @param formParams The form parameters * @param authNames The authentications to apply - * @param progressRequestListener Progress request listener + * @param callback Callback for upload/download progress * @return The HTTP call * @throws ApiException If fail to serialize the request body object */ - public Call buildCall(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map formParams, String[] authNames, ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException { - Request request = buildRequest(path, method, queryParams, collectionQueryParams, body, headerParams, formParams, authNames, progressRequestListener); + public Call buildCall(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map formParams, String[] authNames, ApiCallback callback) throws ApiException { + Request request = buildRequest(path, method, queryParams, collectionQueryParams, body, headerParams, formParams, authNames, callback); return httpClient.newCall(request); } @@ -1087,11 +1089,11 @@ public class ApiClient { * @param headerParams The header parameters * @param formParams The form parameters * @param authNames The authentications to apply - * @param progressRequestListener Progress request listener + * @param callback Callback for upload/download progress * @return The HTTP request * @throws ApiException If fail to serialize the request body object */ - public Request buildRequest(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map formParams, String[] authNames, ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException { + public Request buildRequest(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map formParams, String[] authNames, ApiCallback callback) throws ApiException { updateParamsForAuth(authNames, queryParams, headerParams); final String url = buildUrl(path, queryParams, collectionQueryParams); @@ -1123,10 +1125,14 @@ public class ApiClient { reqBody = serialize(body, contentType); } + // Associate callback with request (if not null) so interceptor can + // access it when creating ProgressResponseBody + reqBuilder.tag(callback); + Request request = null; - if (progressRequestListener != null && reqBody != null) { - ProgressRequestBody progressRequestBody = new ProgressRequestBody(reqBody, progressRequestListener); + if (callback != null && reqBody != null) { + ProgressRequestBody progressRequestBody = new ProgressRequestBody(reqBody, callback); request = reqBuilder.method(method, progressRequestBody).build(); } else { request = reqBuilder.method(method, reqBody).build(); @@ -1270,6 +1276,27 @@ public class ApiClient { } } + /** + * Get network interceptor to add it to the httpClient to track download progress for + * async requests. + */ + private Interceptor getProgressInterceptor() { + return new Interceptor() { + @Override + public Response intercept(Interceptor.Chain chain) throws IOException { + final Request request = chain.request(); + final Response originalResponse = chain.proceed(request); + if (request.tag() instanceof ApiCallback) { + final ApiCallback callback = (ApiCallback) request.tag(); + return originalResponse.newBuilder() + .body(new ProgressResponseBody(originalResponse.body(), callback)) + .build(); + } + return originalResponse; + } + }; + } + /** * Apply SSL related settings to httpClient according to the current values of * verifyingSsl and sslCaCert. diff --git a/libraries/okhttp-gson/ProgressRequestBody.mustache b/libraries/okhttp-gson/ProgressRequestBody.mustache index d9ceeab12ab..71e1e2b4cbe 100644 --- a/libraries/okhttp-gson/ProgressRequestBody.mustache +++ b/libraries/okhttp-gson/ProgressRequestBody.mustache @@ -15,17 +15,13 @@ import okio.Sink; public class ProgressRequestBody extends RequestBody { - public interface ProgressRequestListener { - void onRequestProgress(long bytesWritten, long contentLength, boolean done); - } - private final RequestBody requestBody; - private final ProgressRequestListener progressListener; + private final ApiCallback callback; - public ProgressRequestBody(RequestBody requestBody, ProgressRequestListener progressListener) { + public ProgressRequestBody(RequestBody requestBody, ApiCallback callback) { this.requestBody = requestBody; - this.progressListener = progressListener; + this.callback = callback; } @Override @@ -59,7 +55,7 @@ public class ProgressRequestBody extends RequestBody { } bytesWritten += byteCount; - progressListener.onRequestProgress(bytesWritten, contentLength, bytesWritten == contentLength); + callback.onUploadProgress(bytesWritten, contentLength, bytesWritten == contentLength); } }; } diff --git a/libraries/okhttp-gson/ProgressResponseBody.mustache b/libraries/okhttp-gson/ProgressResponseBody.mustache index 34713eca118..50f2eba395a 100644 --- a/libraries/okhttp-gson/ProgressResponseBody.mustache +++ b/libraries/okhttp-gson/ProgressResponseBody.mustache @@ -15,17 +15,13 @@ import okio.Source; public class ProgressResponseBody extends ResponseBody { - public interface ProgressListener { - void update(long bytesRead, long contentLength, boolean done); - } - private final ResponseBody responseBody; - private final ProgressListener progressListener; + private final ApiCallback callback; private BufferedSource bufferedSource; - public ProgressResponseBody(ResponseBody responseBody, ProgressListener progressListener) { + public ProgressResponseBody(ResponseBody responseBody, ApiCallback callback) { this.responseBody = responseBody; - this.progressListener = progressListener; + this.callback = callback; } @Override @@ -55,7 +51,7 @@ public class ProgressResponseBody extends ResponseBody { long bytesRead = super.read(sink, byteCount); // read() returns the number of bytes read, or -1 if this source is exhausted. totalBytesRead += bytesRead != -1 ? bytesRead : 0; - progressListener.update(totalBytesRead, responseBody.contentLength(), bytesRead == -1); + callback.onDownloadProgress(totalBytesRead, responseBody.contentLength(), bytesRead == -1); return bytesRead; } }; diff --git a/libraries/okhttp-gson/api.mustache b/libraries/okhttp-gson/api.mustache index a06c2e35d59..cf90c4ee1db 100644 --- a/libraries/okhttp-gson/api.mustache +++ b/libraries/okhttp-gson/api.mustache @@ -66,8 +66,7 @@ public class {{classname}} { {{^vendorExtensions.x-group-parameters}}/** * Build call for {{operationId}}{{#allParams}} * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}{{/allParams}} - * @param _progressListener Progress listener - * @param _progressRequestListener Progress request listener + * @param _callback Callback for upload/download progress * @return Call to execute * @throws ApiException If fail to serialize the request body object {{#isDeprecated}} @@ -81,7 +80,7 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} okhttp3.Call {{operationId}}Call({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ProgressResponseBody.ProgressListener _progressListener, final ProgressRequestBody.ProgressRequestListener _progressRequestListener) throws ApiException { + public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} okhttp3.Call {{operationId}}Call({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ApiCallback _callback) throws ApiException { Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}new Object(){{/bodyParam}}; // create path and map variables @@ -124,27 +123,15 @@ public class {{classname}} { final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); localVarHeaderParams.put("Content-Type", localVarContentType); - if (_progressListener != null) { - localVarApiClient.setHttpClient(localVarApiClient.getHttpClient().newBuilder().addNetworkInterceptor(new okhttp3.Interceptor() { - @Override - public okhttp3.Response intercept(okhttp3.Interceptor.Chain chain) throws IOException { - okhttp3.Response originalResponse = chain.proceed(chain.request()); - return originalResponse.newBuilder() - .body(new ProgressResponseBody(originalResponse.body(), _progressListener)) - .build(); - } - }).build()); - } - String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; - return localVarApiClient.buildCall(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAuthNames, _progressRequestListener); + return localVarApiClient.buildCall(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAuthNames, _callback); } {{#isDeprecated}} @Deprecated {{/isDeprecated}} @SuppressWarnings("rawtypes") - private okhttp3.Call {{operationId}}ValidateBeforeCall({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ProgressResponseBody.ProgressListener _progressListener, final ProgressRequestBody.ProgressRequestListener _progressRequestListener) throws ApiException { + private okhttp3.Call {{operationId}}ValidateBeforeCall({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ApiCallback _callback) throws ApiException { {{^performBeanValidation}} {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set @@ -153,7 +140,7 @@ public class {{classname}} { } {{/required}}{{/allParams}} - okhttp3.Call localVarCall = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}_progressListener, _progressRequestListener); + okhttp3.Call localVarCall = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}_callback); return localVarCall; {{/performBeanValidation}} @@ -168,7 +155,7 @@ public class {{classname}} { parameterValues); if (violations.size() == 0) { - okhttp3.Call localVarCall = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}_progressListener, _progressRequestListener); + okhttp3.Call localVarCall = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}_callback); return localVarCall; } else { @@ -227,7 +214,7 @@ public class {{classname}} { @Deprecated {{/isDeprecated}} public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { - okhttp3.Call localVarCall = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}null, null); + okhttp3.Call localVarCall = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}null); {{#returnType}}Type localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType(); return localVarApiClient.execute(localVarCall, localVarReturnType);{{/returnType}}{{^returnType}}return localVarApiClient.execute(localVarCall);{{/returnType}} } @@ -252,26 +239,7 @@ public class {{classname}} { {{/isDeprecated}} public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} okhttp3.Call {{operationId}}Async({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ApiCallback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> _callback) throws ApiException { - ProgressResponseBody.ProgressListener _progressListener = null; - ProgressRequestBody.ProgressRequestListener _progressRequestListener = null; - - if (_callback != null) { - _progressListener = new ProgressResponseBody.ProgressListener() { - @Override - public void update(long bytesRead, long contentLength, boolean done) { - _callback.onDownloadProgress(bytesRead, contentLength, done); - } - }; - - _progressRequestListener = new ProgressRequestBody.ProgressRequestListener() { - @Override - public void onRequestProgress(long bytesWritten, long contentLength, boolean done) { - _callback.onUploadProgress(bytesWritten, contentLength, done); - } - }; - } - - okhttp3.Call localVarCall = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}_progressListener, _progressRequestListener); + okhttp3.Call localVarCall = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}_callback); {{#returnType}}Type localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType(); localVarApiClient.executeAsync(localVarCall, localVarReturnType, _callback);{{/returnType}}{{^returnType}}localVarApiClient.executeAsync(localVarCall, _callback);{{/returnType}} return localVarCall; @@ -317,8 +285,8 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public okhttp3.Call buildCall(final ProgressResponseBody.ProgressListener _progressListener, final ProgressRequestBody.ProgressRequestListener _progressRequestListener) throws ApiException { - return {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}_progressListener, _progressRequestListener); + public okhttp3.Call buildCall(final ApiCallback _callback) throws ApiException { + return {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}_callback); } /** From e844ac8609e01e7013eee5fbe49e7b14903fc3e9 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Thu, 14 Mar 2019 16:35:08 +0800 Subject: [PATCH 090/370] update java okhttp dependencies (#2368) --- libraries/okhttp-gson/build.gradle.mustache | 6 +++--- libraries/okhttp-gson/build.sbt.mustache | 6 +++--- libraries/okhttp-gson/pom.mustache | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/okhttp-gson/build.gradle.mustache b/libraries/okhttp-gson/build.gradle.mustache index c18a2fb9a40..613c81a48be 100644 --- a/libraries/okhttp-gson/build.gradle.mustache +++ b/libraries/okhttp-gson/build.gradle.mustache @@ -127,10 +127,10 @@ if(hasProperty('target') && target == 'android') { dependencies { compile 'io.swagger:swagger-annotations:1.5.21' - compile 'com.squareup.okhttp3:okhttp:3.12.1' - compile 'com.squareup.okhttp3:logging-interceptor:3.12.1' + compile 'com.squareup.okhttp3:okhttp:3.13.1' + compile 'com.squareup.okhttp3:logging-interceptor:3.13.1' compile 'com.google.code.gson:gson:2.8.5' - compile 'io.gsonfire:gson-fire:1.8.0' + compile 'io.gsonfire:gson-fire:1.8.3' {{#hasOAuthMethods}} compile group: 'org.apache.oltu.oauth2', name: 'org.apache.oltu.oauth2.client', version: '1.0.1' {{/hasOAuthMethods}} diff --git a/libraries/okhttp-gson/build.sbt.mustache b/libraries/okhttp-gson/build.sbt.mustache index d3c8cd23532..f83f149e920 100644 --- a/libraries/okhttp-gson/build.sbt.mustache +++ b/libraries/okhttp-gson/build.sbt.mustache @@ -10,8 +10,8 @@ lazy val root = (project in file(".")). resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( "io.swagger" % "swagger-annotations" % "1.5.21", - "com.squareup.okhttp3" % "okhttp" % "3.12.1", - "com.squareup.okhttp3" % "logging-interceptor" % "3.12.1", + "com.squareup.okhttp3" % "okhttp" % "3.13.1", + "com.squareup.okhttp3" % "logging-interceptor" % "3.13.1", "com.google.code.gson" % "gson" % "2.8.5", "org.apache.commons" % "commons-lang3" % "3.8.1", {{#hasOAuthMethods}} @@ -23,7 +23,7 @@ lazy val root = (project in file(".")). {{#threetenbp}} "org.threeten" % "threetenbp" % "1.3.5" % "compile", {{/threetenbp}} - "io.gsonfire" % "gson-fire" % "1.8.0" % "compile", + "io.gsonfire" % "gson-fire" % "1.8.3" % "compile", "junit" % "junit" % "4.12" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index 9f9c4b874ca..e3efc5851e8 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -287,9 +287,9 @@ {{#supportJava6}}1.6{{/supportJava6}}{{^supportJava6}}{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}{{/supportJava6}} ${java.version} ${java.version} - 1.8.0 + 1.8.3 1.5.21 - 3.12.1 + 3.13.1 2.8.5 3.8.1 {{#joda}} From e3cb1d1fe5a99601df25352b185684967baba96d Mon Sep 17 00:00:00 2001 From: Vincent Devos <46601673+karismann@users.noreply.github.com> Date: Sun, 17 Mar 2019 10:40:11 +0100 Subject: [PATCH 091/370] [GRADLE] upgrade to 2.16 in java/scala/androit client to fix Vulnerability (#2416) --- gradle-wrapper.jar | Bin 53639 -> 55190 bytes gradle-wrapper.properties.mustache | 3 +- gradlew.bat.mustache | 12 ++--- gradlew.mustache | 72 +++++++++++++++++------------ 4 files changed, 46 insertions(+), 41 deletions(-) diff --git a/gradle-wrapper.jar b/gradle-wrapper.jar index 2c6137b87896c8f70315ae454e00a969ef5f6019..87b738cbd051603d91cc39de6cb000dd98fe6b02 100644 GIT binary patch literal 55190 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 z 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 F{{tUq7iIte diff --git a/gradle-wrapper.properties.mustache b/gradle-wrapper.properties.mustache index b7a36473955..e496c054f69 100644 --- a/gradle-wrapper.properties.mustache +++ b/gradle-wrapper.properties.mustache @@ -1,6 +1,5 @@ -#Tue May 17 23:08:05 CST 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.6-bin.zip diff --git a/gradlew.bat.mustache b/gradlew.bat.mustache index 5f192121eb4..f9553162f12 100644 --- a/gradlew.bat.mustache +++ b/gradlew.bat.mustache @@ -8,14 +8,14 @@ @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome @@ -49,7 +49,6 @@ goto fail @rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. @@ -60,11 +59,6 @@ set _SKIP=2 if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ :execute @rem Setup the command line diff --git a/gradlew.mustache b/gradlew.mustache index 9d82f789151..af6708ff229 100755 --- a/gradlew.mustache +++ b/gradlew.mustache @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh ############################################################################## ## @@ -6,20 +6,38 @@ ## ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m"' + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { +warn () { echo "$*" } -die ( ) { +die () { echo echo "$*" echo @@ -30,6 +48,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,26 +59,11 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -85,7 +89,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then @@ -150,11 +154,19 @@ if $cygwin ; then esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +exec "$JAVACMD" "$@" From 92152002351b2820370f2fd4204e4ec392185354 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Mon, 18 Mar 2019 10:46:33 +0800 Subject: [PATCH 092/370] [Java][C#][JS] remove localVariablePrefix (#2423) * remove localVariablePrefix from template * remove local variable prefix option from java gen * remove local var from c#, js * update doc --- api.mustache | 44 ++++++++++++------------ libraries/google-api-client/api.mustache | 8 ++--- libraries/jersey2/api.mustache | 42 +++++++++++----------- libraries/resteasy/api.mustache | 42 +++++++++++----------- libraries/resttemplate/api.mustache | 38 ++++++++++---------- libraries/vertx/apiImpl.mustache | 36 +++++++++---------- libraries/vertx/api_test.mustache | 2 +- libraries/webclient/api.mustache | 38 ++++++++++---------- 8 files changed, 125 insertions(+), 125 deletions(-) diff --git a/api.mustache b/api.mustache index 2b1ecb4ab6b..fa23d312502 100644 --- a/api.mustache +++ b/api.mustache @@ -23,22 +23,22 @@ import java.util.Map; {{>generatedAnnotation}} {{#operations}} public class {{classname}} { - private ApiClient {{localVariablePrefix}}apiClient; + private ApiClient apiClient; public {{classname}}() { this(Configuration.getDefaultApiClient()); } public {{classname}}(ApiClient apiClient) { - this.{{localVariablePrefix}}apiClient = apiClient; + this.apiClient = apiClient; } public ApiClient getApiClient() { - return {{localVariablePrefix}}apiClient; + return apiClient; } public void setApiClient(ApiClient apiClient) { - this.{{localVariablePrefix}}apiClient = apiClient; + this.apiClient = apiClient; } {{#operation}} @@ -64,7 +64,7 @@ public class {{classname}} { @Deprecated {{/isDeprecated}} public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { - Object {{localVariablePrefix}}localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { @@ -72,44 +72,44 @@ public class {{classname}} { } {{/required}}{{/allParams}} // create path and map variables - String {{localVariablePrefix}}localVarPath = "{{{path}}}"{{#pathParams}} - .replaceAll("\\{" + "{{baseName}}" + "\\}", {{localVariablePrefix}}apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; + String localVarPath = "{{{path}}}"{{#pathParams}} + .replaceAll("\\{" + "{{baseName}}" + "\\}", apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; // query params - {{javaUtilPrefix}}List {{localVariablePrefix}}localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); - {{javaUtilPrefix}}List {{localVariablePrefix}}localVarCollectionQueryParams = new {{javaUtilPrefix}}ArrayList(); - {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); - {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarFormParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}List localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}List localVarCollectionQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}Map localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarFormParams = new {{javaUtilPrefix}}HashMap(); {{#queryParams}} - {{localVariablePrefix}}{{#collectionFormat}}localVarCollectionQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPairs("{{{collectionFormat}}}", {{/collectionFormat}}{{^collectionFormat}}localVarQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPair({{/collectionFormat}}"{{baseName}}", {{paramName}})); + {{#collectionFormat}}localVarCollectionQueryParams.addAll(apiClient.parameterToPairs("{{{collectionFormat}}}", {{/collectionFormat}}{{^collectionFormat}}localVarQueryParams.addAll(apiClient.parameterToPair({{/collectionFormat}}"{{baseName}}", {{paramName}})); {{/queryParams}} {{#headerParams}}if ({{paramName}} != null) - {{localVariablePrefix}}localVarHeaderParams.put("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}})); + localVarHeaderParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); {{/headerParams}} {{#formParams}}if ({{paramName}} != null) - {{localVariablePrefix}}localVarFormParams.put("{{baseName}}", {{paramName}}); + localVarFormParams.put("{{baseName}}", {{paramName}}); {{/formParams}} - final String[] {{localVariablePrefix}}localVarAccepts = { + final String[] localVarAccepts = { {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }; - final String {{localVariablePrefix}}localVarAccept = {{localVariablePrefix}}apiClient.selectHeaderAccept({{localVariablePrefix}}localVarAccepts); + final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); - final String[] {{localVariablePrefix}}localVarContentTypes = { + final String[] localVarContentTypes = { {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} }; - final String {{localVariablePrefix}}localVarContentType = {{localVariablePrefix}}apiClient.selectHeaderContentType({{localVariablePrefix}}localVarContentTypes); + final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); - String[] {{localVariablePrefix}}localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; {{#returnType}} - GenericType<{{{returnType}}}> {{localVariablePrefix}}localVarReturnType = new GenericType<{{{returnType}}}>() {}; - return {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarCollectionQueryParams, {{localVariablePrefix}}localVarPostBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccept, {{localVariablePrefix}}localVarContentType, {{localVariablePrefix}}localVarAuthNames, {{localVariablePrefix}}localVarReturnType); + GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {}; + return apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType); {{/returnType}}{{^returnType}} - {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarCollectionQueryParams, {{localVariablePrefix}}localVarPostBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccept, {{localVariablePrefix}}localVarContentType, {{localVariablePrefix}}localVarAuthNames, null); + apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, null); {{/returnType}} } {{/operation}} diff --git a/libraries/google-api-client/api.mustache b/libraries/google-api-client/api.mustache index 46ecf3af355..6a9c10c02ea 100644 --- a/libraries/google-api-client/api.mustache +++ b/libraries/google-api-client/api.mustache @@ -24,22 +24,22 @@ import java.util.ArrayList; {{>generatedAnnotation}} {{#operations}} public class {{classname}} { - private ApiClient {{localVariablePrefix}}apiClient; + private ApiClient apiClient; public {{classname}}() { this(new ApiClient()); } public {{classname}}(ApiClient apiClient) { - this.{{localVariablePrefix}}apiClient = apiClient; + this.apiClient = apiClient; } public ApiClient getApiClient() { - return {{localVariablePrefix}}apiClient; + return apiClient; } public void setApiClient(ApiClient apiClient) { - this.{{localVariablePrefix}}apiClient = apiClient; + this.apiClient = apiClient; } {{#operation}} diff --git a/libraries/jersey2/api.mustache b/libraries/jersey2/api.mustache index 985834fe2c1..a275689bba5 100644 --- a/libraries/jersey2/api.mustache +++ b/libraries/jersey2/api.mustache @@ -21,22 +21,22 @@ import java.util.Map; {{>generatedAnnotation}} {{#operations}} public class {{classname}} { - private ApiClient {{localVariablePrefix}}apiClient; + private ApiClient apiClient; public {{classname}}() { this(Configuration.getDefaultApiClient()); } public {{classname}}(ApiClient apiClient) { - this.{{localVariablePrefix}}apiClient = apiClient; + this.apiClient = apiClient; } public ApiClient getApiClient() { - return {{localVariablePrefix}}apiClient; + return apiClient; } public void setApiClient(ApiClient apiClient) { - this.{{localVariablePrefix}}apiClient = apiClient; + this.apiClient = apiClient; } {{#operation}} @@ -91,7 +91,7 @@ public class {{classname}} { @Deprecated {{/isDeprecated}} public ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { - Object {{localVariablePrefix}}localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}new Object(){{/bodyParam}}; + Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}new Object(){{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { @@ -99,43 +99,43 @@ public class {{classname}} { } {{/required}}{{/allParams}} // create path and map variables - String {{localVariablePrefix}}localVarPath = "{{{path}}}"{{#pathParams}} - .replaceAll("\\{" + "{{baseName}}" + "\\}", {{localVariablePrefix}}apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; + String localVarPath = "{{{path}}}"{{#pathParams}} + .replaceAll("\\{" + "{{baseName}}" + "\\}", apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; // query params - {{javaUtilPrefix}}List {{localVariablePrefix}}localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); - {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); - {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarFormParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}List localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}Map localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarFormParams = new {{javaUtilPrefix}}HashMap(); {{#queryParams}} - {{localVariablePrefix}}localVarQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); + localVarQueryParams.addAll(apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); {{/queryParams}} {{#headerParams}}if ({{paramName}} != null) - {{localVariablePrefix}}localVarHeaderParams.put("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}})); + localVarHeaderParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); {{/headerParams}} {{#formParams}}if ({{paramName}} != null) - {{localVariablePrefix}}localVarFormParams.put("{{baseName}}", {{paramName}}); + localVarFormParams.put("{{baseName}}", {{paramName}}); {{/formParams}} - final String[] {{localVariablePrefix}}localVarAccepts = { + final String[] localVarAccepts = { {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }; - final String {{localVariablePrefix}}localVarAccept = {{localVariablePrefix}}apiClient.selectHeaderAccept({{localVariablePrefix}}localVarAccepts); + final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); - final String[] {{localVariablePrefix}}localVarContentTypes = { + final String[] localVarContentTypes = { {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} }; - final String {{localVariablePrefix}}localVarContentType = {{localVariablePrefix}}apiClient.selectHeaderContentType({{localVariablePrefix}}localVarContentTypes); + final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); - String[] {{localVariablePrefix}}localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; {{#returnType}} - GenericType<{{{returnType}}}> {{localVariablePrefix}}localVarReturnType = new GenericType<{{{returnType}}}>() {}; - return {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarPostBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccept, {{localVariablePrefix}}localVarContentType, {{localVariablePrefix}}localVarAuthNames, {{localVariablePrefix}}localVarReturnType); + GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {}; + return apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType); {{/returnType}}{{^returnType}} - return {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarPostBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccept, {{localVariablePrefix}}localVarContentType, {{localVariablePrefix}}localVarAuthNames, null); + return apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, null); {{/returnType}} } {{/operation}} diff --git a/libraries/resteasy/api.mustache b/libraries/resteasy/api.mustache index a4d0f9f239d..f6806af6b5f 100644 --- a/libraries/resteasy/api.mustache +++ b/libraries/resteasy/api.mustache @@ -20,22 +20,22 @@ import java.util.Map; {{>generatedAnnotation}} {{#operations}} public class {{classname}} { - private ApiClient {{localVariablePrefix}}apiClient; + private ApiClient apiClient; public {{classname}}() { this(Configuration.getDefaultApiClient()); } public {{classname}}(ApiClient apiClient) { - this.{{localVariablePrefix}}apiClient = apiClient; + this.apiClient = apiClient; } public ApiClient getApiClient() { - return {{localVariablePrefix}}apiClient; + return apiClient; } public void setApiClient(ApiClient apiClient) { - this.{{localVariablePrefix}}apiClient = apiClient; + this.apiClient = apiClient; } {{#operation}} @@ -57,7 +57,7 @@ public class {{classname}} { @Deprecated {{/isDeprecated}} public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { - Object {{localVariablePrefix}}localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}new Object(){{/bodyParam}}; + Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}new Object(){{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { @@ -65,43 +65,43 @@ public class {{classname}} { } {{/required}}{{/allParams}} // create path and map variables - String {{localVariablePrefix}}localVarPath = "{{{path}}}".replaceAll("\\{format\\}","json"){{#pathParams}} - .replaceAll("\\{" + "{{baseName}}" + "\\}", {{localVariablePrefix}}apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; + String localVarPath = "{{{path}}}".replaceAll("\\{format\\}","json"){{#pathParams}} + .replaceAll("\\{" + "{{baseName}}" + "\\}", apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; // query params - {{javaUtilPrefix}}List {{localVariablePrefix}}localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); - {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); - {{javaUtilPrefix}}Map {{localVariablePrefix}}localVarFormParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}List localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}Map localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarFormParams = new {{javaUtilPrefix}}HashMap(); {{#queryParams}} - {{localVariablePrefix}}localVarQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); + localVarQueryParams.addAll(apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); {{/queryParams}} {{#headerParams}}if ({{paramName}} != null) - {{localVariablePrefix}}localVarHeaderParams.put("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}})); + localVarHeaderParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); {{/headerParams}} {{#formParams}}if ({{paramName}} != null) - {{localVariablePrefix}}localVarFormParams.put("{{baseName}}", {{paramName}}); + localVarFormParams.put("{{baseName}}", {{paramName}}); {{/formParams}} - final String[] {{localVariablePrefix}}localVarAccepts = { + final String[] localVarAccepts = { {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }; - final String {{localVariablePrefix}}localVarAccept = {{localVariablePrefix}}apiClient.selectHeaderAccept({{localVariablePrefix}}localVarAccepts); + final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); - final String[] {{localVariablePrefix}}localVarContentTypes = { + final String[] localVarContentTypes = { {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} }; - final String {{localVariablePrefix}}localVarContentType = {{localVariablePrefix}}apiClient.selectHeaderContentType({{localVariablePrefix}}localVarContentTypes); + final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); - String[] {{localVariablePrefix}}localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; {{#returnType}} - GenericType<{{{returnType}}}> {{localVariablePrefix}}localVarReturnType = new GenericType<{{{returnType}}}>() {}; - return {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarPostBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccept, {{localVariablePrefix}}localVarContentType, {{localVariablePrefix}}localVarAuthNames, {{localVariablePrefix}}localVarReturnType); + GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {}; + return apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType); {{/returnType}}{{^returnType}} - {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarPostBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccept, {{localVariablePrefix}}localVarContentType, {{localVariablePrefix}}localVarAuthNames, null); + apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, null); {{/returnType}} } {{/operation}} diff --git a/libraries/resttemplate/api.mustache b/libraries/resttemplate/api.mustache index e52b822b106..040d776efe9 100644 --- a/libraries/resttemplate/api.mustache +++ b/libraries/resttemplate/api.mustache @@ -29,7 +29,7 @@ import org.springframework.http.MediaType; @Component("{{package}}.{{classname}}") {{#operations}} public class {{classname}} { - private ApiClient {{localVariablePrefix}}apiClient; + private ApiClient apiClient; public {{classname}}() { this(new ApiClient()); @@ -37,15 +37,15 @@ public class {{classname}} { @Autowired public {{classname}}(ApiClient apiClient) { - this.{{localVariablePrefix}}apiClient = apiClient; + this.apiClient = apiClient; } public ApiClient getApiClient() { - return {{localVariablePrefix}}apiClient; + return apiClient; } public void setApiClient(ApiClient apiClient) { - this.{{localVariablePrefix}}apiClient = apiClient; + this.apiClient = apiClient; } {{#operation}} @@ -62,7 +62,7 @@ public class {{classname}} { {{/externalDocs}} */ public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { - Object {{localVariablePrefix}}postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + Object postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { @@ -72,36 +72,36 @@ public class {{classname}} { // create path and map variables final Map uriVariables = new HashMap();{{#pathParams}} uriVariables.put("{{baseName}}", {{#collectionFormat}}apiClient.collectionPathParameterToString(ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase()), {{{paramName}}}){{/collectionFormat}}{{^collectionFormat}}{{{paramName}}}{{/collectionFormat}});{{/pathParams}}{{/hasPathParams}} - String {{localVariablePrefix}}path = UriComponentsBuilder.fromPath("{{{path}}}"){{#hasPathParams}}.buildAndExpand(uriVariables){{/hasPathParams}}{{^hasPathParams}}.build(){{/hasPathParams}}.toUriString(); + String path = UriComponentsBuilder.fromPath("{{{path}}}"){{#hasPathParams}}.buildAndExpand(uriVariables){{/hasPathParams}}{{^hasPathParams}}.build(){{/hasPathParams}}.toUriString(); - final MultiValueMap {{localVariablePrefix}}queryParams = new LinkedMultiValueMap(); - final HttpHeaders {{localVariablePrefix}}headerParams = new HttpHeaders(); - final MultiValueMap {{localVariablePrefix}}formParams = new LinkedMultiValueMap();{{#hasQueryParams}} + final MultiValueMap queryParams = new LinkedMultiValueMap(); + final HttpHeaders headerParams = new HttpHeaders(); + final MultiValueMap formParams = new LinkedMultiValueMap();{{#hasQueryParams}} - {{#queryParams}}{{localVariablePrefix}}queryParams.putAll({{localVariablePrefix}}apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{#hasMore}} + {{#queryParams}}queryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{#hasMore}} {{/hasMore}}{{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}} {{#headerParams}}if ({{paramName}} != null) - {{localVariablePrefix}}headerParams.add("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}}));{{#hasMore}} + headerParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{#hasMore}} {{/hasMore}}{{/headerParams}}{{/hasHeaderParams}}{{#hasFormParams}} {{#formParams}}if ({{paramName}} != null) - {{localVariablePrefix}}formParams.add("{{baseName}}", {{#isFile}}new FileSystemResource({{paramName}}){{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} + formParams.add("{{baseName}}", {{#isFile}}new FileSystemResource({{paramName}}){{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} {{/hasMore}}{{/formParams}}{{/hasFormParams}} - final String[] {{localVariablePrefix}}accepts = { {{#hasProduces}} + final String[] accepts = { {{#hasProduces}} {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} {{/hasProduces}}}; - final List {{localVariablePrefix}}accept = {{localVariablePrefix}}apiClient.selectHeaderAccept({{localVariablePrefix}}accepts); - final String[] {{localVariablePrefix}}contentTypes = { {{#hasConsumes}} + final List accept = apiClient.selectHeaderAccept(accepts); + final String[] contentTypes = { {{#hasConsumes}} {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} {{/hasConsumes}}}; - final MediaType {{localVariablePrefix}}contentType = {{localVariablePrefix}}apiClient.selectHeaderContentType({{localVariablePrefix}}contentTypes); + final MediaType contentType = apiClient.selectHeaderContentType(contentTypes); - String[] {{localVariablePrefix}}authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + String[] authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; - {{#returnType}}ParameterizedTypeReference<{{{returnType}}}> {{localVariablePrefix}}returnType = new ParameterizedTypeReference<{{{returnType}}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference {{localVariablePrefix}}returnType = new ParameterizedTypeReference() {};{{/returnType}} - {{#returnType}}return {{/returnType}}{{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}path, HttpMethod.{{httpMethod}}, {{localVariablePrefix}}queryParams, {{localVariablePrefix}}postBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames, {{localVariablePrefix}}returnType); + {{#returnType}}ParameterizedTypeReference<{{{returnType}}}> returnType = new ParameterizedTypeReference<{{{returnType}}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference returnType = new ParameterizedTypeReference() {};{{/returnType}} + {{#returnType}}return {{/returnType}}apiClient.invokeAPI(path, HttpMethod.{{httpMethod}}, queryParams, postBody, headerParams, formParams, accept, contentType, authNames, returnType); } {{/operation}} } diff --git a/libraries/vertx/apiImpl.mustache b/libraries/vertx/apiImpl.mustache index 37893a8888f..2cdac042865 100644 --- a/libraries/vertx/apiImpl.mustache +++ b/libraries/vertx/apiImpl.mustache @@ -21,22 +21,22 @@ import {{invokerPackage}}.Pair; {{#operations}} public class {{classname}}Impl implements {{classname}} { - private ApiClient {{localVariablePrefix}}apiClient; + private ApiClient apiClient; public {{classname}}Impl() { this(null); } public {{classname}}Impl(ApiClient apiClient) { - this.{{localVariablePrefix}}apiClient = apiClient != null ? apiClient : Configuration.getDefaultApiClient(); + this.apiClient = apiClient != null ? apiClient : Configuration.getDefaultApiClient(); } public ApiClient getApiClient() { - return {{localVariablePrefix}}apiClient; + return apiClient; } public void setApiClient(ApiClient apiClient) { - this.{{localVariablePrefix}}apiClient = apiClient; + this.apiClient = apiClient; } {{#operation}} @@ -49,7 +49,7 @@ public class {{classname}}Impl implements {{classname}} { * @param resultHandler Asynchronous result handler */ public void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}Handler> resultHandler) { - Object {{localVariablePrefix}}localVarBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + Object localVarBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { @@ -58,33 +58,33 @@ public class {{classname}}Impl implements {{classname}} { } {{/required}}{{/allParams}} // create path and map variables - String {{localVariablePrefix}}localVarPath = "{{{path}}}"{{#pathParams}}.replaceAll("\\{" + "{{baseName}}" + "\\}", {{{paramName}}}.toString()){{/pathParams}}; + String localVarPath = "{{{path}}}"{{#pathParams}}.replaceAll("\\{" + "{{baseName}}" + "\\}", {{{paramName}}}.toString()){{/pathParams}}; // query params - List {{localVariablePrefix}}localVarQueryParams = new ArrayList<>(); + List localVarQueryParams = new ArrayList<>(); {{#queryParams}} - {{localVariablePrefix}}localVarQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); + localVarQueryParams.addAll(apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); {{/queryParams}} // header params - MultiMap {{localVariablePrefix}}localVarHeaderParams = MultiMap.caseInsensitiveMultiMap(); + MultiMap localVarHeaderParams = MultiMap.caseInsensitiveMultiMap(); {{#headerParams}}if ({{paramName}} != null) - {{localVariablePrefix}}localVarHeaderParams.add("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}})); + localVarHeaderParams.add("{{baseName}}", apiClient.parameterToString({{paramName}})); {{/headerParams}} // form params // TODO: sending files within multipart/form-data is not supported yet (because of vertx web-client) - Map {{localVariablePrefix}}localVarFormParams = new HashMap<>(); - {{#formParams}}if ({{paramName}} != null) {{localVariablePrefix}}localVarFormParams.put("{{baseName}}", {{paramName}}); + Map localVarFormParams = new HashMap<>(); + {{#formParams}}if ({{paramName}} != null) localVarFormParams.put("{{baseName}}", {{paramName}}); {{/formParams}} - String[] {{localVariablePrefix}}localVarAccepts = { {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }; - String[] {{localVariablePrefix}}localVarContentTypes = { {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} }; - String[] {{localVariablePrefix}}localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + String[] localVarAccepts = { {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }; + String[] localVarContentTypes = { {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} }; + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; {{#returnType}} - TypeReference<{{{returnType}}}> {{localVariablePrefix}}localVarReturnType = new TypeReference<{{{returnType}}}>() {}; - {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccepts, {{localVariablePrefix}}localVarContentTypes, {{localVariablePrefix}}localVarAuthNames, {{localVariablePrefix}}localVarReturnType, resultHandler);{{/returnType}}{{^returnType}} - {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccepts, {{localVariablePrefix}}localVarContentTypes, {{localVariablePrefix}}localVarAuthNames, null, resultHandler);{{/returnType}} + TypeReference<{{{returnType}}}> localVarReturnType = new TypeReference<{{{returnType}}}>() {}; + apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarBody, localVarHeaderParams, localVarFormParams, localVarAccepts, localVarContentTypes, localVarAuthNames, localVarReturnType, resultHandler);{{/returnType}}{{^returnType}} + apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarBody, localVarHeaderParams, localVarFormParams, localVarAccepts, localVarContentTypes, localVarAuthNames, null, resultHandler);{{/returnType}} } {{/operation}} } diff --git a/libraries/vertx/api_test.mustache b/libraries/vertx/api_test.mustache index 753df13cd1d..77010f248c1 100644 --- a/libraries/vertx/api_test.mustache +++ b/libraries/vertx/api_test.mustache @@ -67,4 +67,4 @@ public class {{classname}}Test { }); } {{/operation}}{{/operations}} -} \ No newline at end of file +} diff --git a/libraries/webclient/api.mustache b/libraries/webclient/api.mustache index c29a160fc4f..33da1d14576 100644 --- a/libraries/webclient/api.mustache +++ b/libraries/webclient/api.mustache @@ -28,7 +28,7 @@ import reactor.core.publisher.Flux; {{>generatedAnnotation}} {{#operations}} public class {{classname}} { - private ApiClient {{localVariablePrefix}}apiClient; + private ApiClient apiClient; public {{classname}}() { this(new ApiClient()); @@ -36,15 +36,15 @@ public class {{classname}} { @Autowired public {{classname}}(ApiClient apiClient) { - this.{{localVariablePrefix}}apiClient = apiClient; + this.apiClient = apiClient; } public ApiClient getApiClient() { - return {{localVariablePrefix}}apiClient; + return apiClient; } public void setApiClient(ApiClient apiClient) { - this.{{localVariablePrefix}}apiClient = apiClient; + this.apiClient = apiClient; } {{#operation}} @@ -61,7 +61,7 @@ public class {{classname}} { {{/externalDocs}} */ public {{#returnType}}{{#isListContainer}}Flux<{{{returnBaseType}}}>{{/isListContainer}}{{^isListContainer}}Mono<{{{returnType}}}>{{/isListContainer}} {{/returnType}}{{^returnType}}Mono {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { - Object {{localVariablePrefix}}postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + Object postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { @@ -71,36 +71,36 @@ public class {{classname}} { // create path and map variables final Map uriVariables = new HashMap();{{#pathParams}} uriVariables.put("{{baseName}}", {{{paramName}}});{{/pathParams}}{{/hasPathParams}} - String {{localVariablePrefix}}path = UriComponentsBuilder.fromPath("{{{path}}}"){{#hasPathParams}}.buildAndExpand(uriVariables){{/hasPathParams}}{{^hasPathParams}}.build(){{/hasPathParams}}.toUriString(); + String path = UriComponentsBuilder.fromPath("{{{path}}}"){{#hasPathParams}}.buildAndExpand(uriVariables){{/hasPathParams}}{{^hasPathParams}}.build(){{/hasPathParams}}.toUriString(); - final MultiValueMap {{localVariablePrefix}}queryParams = new LinkedMultiValueMap(); - final HttpHeaders {{localVariablePrefix}}headerParams = new HttpHeaders(); - final MultiValueMap {{localVariablePrefix}}formParams = new LinkedMultiValueMap();{{#hasQueryParams}} + final MultiValueMap queryParams = new LinkedMultiValueMap(); + final HttpHeaders headerParams = new HttpHeaders(); + final MultiValueMap formParams = new LinkedMultiValueMap();{{#hasQueryParams}} - {{#queryParams}}{{localVariablePrefix}}queryParams.putAll({{localVariablePrefix}}apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{#hasMore}} + {{#queryParams}}queryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{#hasMore}} {{/hasMore}}{{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}} {{#headerParams}}if ({{paramName}} != null) - {{localVariablePrefix}}headerParams.add("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}}));{{#hasMore}} + headerParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{#hasMore}} {{/hasMore}}{{/headerParams}}{{/hasHeaderParams}}{{#hasFormParams}} {{#formParams}}if ({{paramName}} != null) - {{localVariablePrefix}}formParams.add("{{baseName}}", {{#isFile}}new FileSystemResource({{paramName}}){{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} + formParams.add("{{baseName}}", {{#isFile}}new FileSystemResource({{paramName}}){{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} {{/hasMore}}{{/formParams}}{{/hasFormParams}} - final String[] {{localVariablePrefix}}accepts = { {{#hasProduces}} + final String[] accepts = { {{#hasProduces}} {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} {{/hasProduces}}}; - final List {{localVariablePrefix}}accept = {{localVariablePrefix}}apiClient.selectHeaderAccept({{localVariablePrefix}}accepts); - final String[] {{localVariablePrefix}}contentTypes = { {{#hasConsumes}} + final List accept = apiClient.selectHeaderAccept(accepts); + final String[] contentTypes = { {{#hasConsumes}} {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} {{/hasConsumes}}}; - final MediaType {{localVariablePrefix}}contentType = {{localVariablePrefix}}apiClient.selectHeaderContentType({{localVariablePrefix}}contentTypes); + final MediaType contentType = apiClient.selectHeaderContentType(contentTypes); - String[] {{localVariablePrefix}}authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + String[] authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; - {{#returnType}}ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}> {{localVariablePrefix}}returnType = new ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference {{localVariablePrefix}}returnType = new ParameterizedTypeReference() {};{{/returnType}} - return {{localVariablePrefix}}apiClient.{{#isListContainer}}invokeFluxAPI{{/isListContainer}}{{^isListContainer}}invokeAPI{{/isListContainer}}({{localVariablePrefix}}path, HttpMethod.{{httpMethod}}, {{localVariablePrefix}}queryParams, {{localVariablePrefix}}postBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames, {{localVariablePrefix}}returnType); + {{#returnType}}ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}> returnType = new ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference returnType = new ParameterizedTypeReference() {};{{/returnType}} + return apiClient.{{#isListContainer}}invokeFluxAPI{{/isListContainer}}{{^isListContainer}}invokeAPI{{/isListContainer}}(path, HttpMethod.{{httpMethod}}, queryParams, postBody, headerParams, formParams, accept, contentType, authNames, returnType); } {{/operation}} } From 159e59ef6153202d468c7735b4473b7f55ef0f9f Mon Sep 17 00:00:00 2001 From: Jens Oberender Date: Mon, 18 Mar 2019 04:04:43 +0100 Subject: [PATCH 093/370] Fix for the added interceptor and when the http client is set several times, which leads to a stack overflow because of too many interceptors. (#2420) Also added tests for that. --- libraries/okhttp-gson/ApiClient.mustache | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index bdae7a66aa7..22efcd9e936 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -137,7 +137,7 @@ public class ApiClient { {{/hasOAuthMethods}} private void init() { OkHttpClient.Builder builder = new OkHttpClient.Builder(); - builder.addInterceptor(getProgressInterceptor()); + builder.addNetworkInterceptor(getProgressInterceptor()); httpClient = builder.build(); {{#useGzipFeature}} @@ -187,11 +187,22 @@ public class ApiClient { /** * Set HTTP client * - * @param httpClient An instance of OkHttpClient + * @param newHttpClient An instance of OkHttpClient * @return Api Client */ - public ApiClient setHttpClient(OkHttpClient httpClient) { - this.httpClient = httpClient.newBuilder().addInterceptor(getProgressInterceptor()).build(); + public ApiClient setHttpClient(OkHttpClient newHttpClient) { + if(!httpClient.equals(newHttpClient)) { + OkHttpClient.Builder builder = newHttpClient.newBuilder(); + Iterator networkInterceptorIterator = httpClient.networkInterceptors().iterator(); + while(networkInterceptorIterator.hasNext()) { + builder.addNetworkInterceptor(networkInterceptorIterator.next()); + } + Iterator interceptorIterator = httpClient.interceptors().iterator(); + while(interceptorIterator.hasNext()) { + builder.addInterceptor(interceptorIterator.next()); + } + this.httpClient = builder.build(); + } return this; } From 0a9cc6528938b1feb3cb57cbd9a3c13de0a52b13 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Mon, 18 Mar 2019 20:58:14 +0800 Subject: [PATCH 094/370] fix java doc issue (#2435) --- libraries/okhttp-gson/ApiClient.mustache | 2 +- libraries/okhttp-gson/api.mustache | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index 22efcd9e936..3c4559359c3 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -190,7 +190,7 @@ public class ApiClient { * @param newHttpClient An instance of OkHttpClient * @return Api Client */ - public ApiClient setHttpClient(OkHttpClient newHttpClient) { + public ApiClient setHttpClient(OkHttpClient newHttpClient) { if(!httpClient.equals(newHttpClient)) { OkHttpClient.Builder builder = newHttpClient.newBuilder(); Iterator networkInterceptorIterator = httpClient.networkInterceptors().iterator(); diff --git a/libraries/okhttp-gson/api.mustache b/libraries/okhttp-gson/api.mustache index cf90c4ee1db..3705e654e09 100644 --- a/libraries/okhttp-gson/api.mustache +++ b/libraries/okhttp-gson/api.mustache @@ -274,8 +274,7 @@ public class {{classname}} { {{/optionalParams}} /** * Build call for {{operationId}} - * @param _progressListener Progress listener - * @param _progressRequestListener Progress request listener + * @param _callback ApiCallback API callback * @return Call to execute * @throws ApiException If fail to serialize the request body object {{#isDeprecated}} From 7ce49433b8495984318fe51bb5b387ec5b42e002 Mon Sep 17 00:00:00 2001 From: davidwcarlson <516753+davidwcarlson@users.noreply.github.com> Date: Sat, 23 Mar 2019 03:38:00 -0700 Subject: [PATCH 095/370] java-jersey2 - Always render setBearerToken regardless of whether OAuth2 is in use. (#2479) --- libraries/jersey2/ApiClient.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 2de4af24edc..9b19457b04c 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -194,7 +194,6 @@ public class ApiClient { throw new RuntimeException("No API key authentication configured!"); } - {{#hasOAuthMethods}} /** * Helper method to set bearer token for the first Bearer authentication. * @param bearerToken Bearer token @@ -209,6 +208,7 @@ public class ApiClient { throw new RuntimeException("No Bearer authentication configured!"); } + {{#hasOAuthMethods}} /** * Helper method to set access token for the first OAuth2 authentication. * @param accessToken Access token From 729fba80de1f4ba89b0e419e39476e691bb3608a Mon Sep 17 00:00:00 2001 From: Alok Prateek Date: Mon, 25 Mar 2019 19:18:22 +0530 Subject: [PATCH 096/370] [#2441] Update documentation mustache templates for proper linting. (#2458) * [#2441] Update documentation mustache files for PHP client This commit fixes issues with Markdown/CommonMark parsing by linting and enforcing consistent style.[#2441] Issues with generated markdown files as reported by markdownlint for node.js are: - MD001 heading-increment/header-increment - Heading levels should only increment by one level at a time - MD002 first-heading-h1/first-header-h1 - First heading should be a top level heading - MD007 ul-indent - Unordered list indentation - MD009 no-trailing-spaces - Trailing spaces - MD010 no-hard-tabs - Hard tabs - MD011 no-reversed-links - Reversed link syntax - MD025 single-h1 - Multiple top level headings in the same document - MD031 blanks-around-fences - Fenced code blocks should be surrounded by blank lines - MD032 blanks-around-lists - Lists should be surrounded by blank lines - MD040 fenced-code-language - Fenced code blocks should have a language specified - MD041 first-line-h1 - First line in file should be a top level heading * [#2441] Update documentation mustache files for ruby client This commit fixes issues with Markdown/CommonMark parsing by linting and enforcing consistent style.[#2441] Issues with generated markdown files as reported by markdownlint for node.js are: - MD001 heading-increment/header-increment - Heading levels should only increment by one level at a time - MD002 first-heading-h1/first-header-h1 - First heading should be a top level heading - MD007 ul-indent - Unordered list indentation - MD009 no-trailing-spaces - Trailing spaces - MD010 no-hard-tabs - Hard tabs - MD011 no-reversed-links - Reversed link syntax - MD025 single-h1 - Multiple top level headings in the same document - MD031 blanks-around-fences - Fenced code blocks should be surrounded by blank lines - MD032 blanks-around-lists - Lists should be surrounded by blank lines - MD040 fenced-code-language - Fenced code blocks should have a language specified - MD041 first-line-h1 - First line in file should be a top level heading * [#2441] Update documentation mustache files for javascript client This commit fixes issues with Markdown/CommonMark parsing by linting and enforcing consistent style.[#2441] Issues with generated markdown files as reported by markdownlint for node.js are: - MD001 heading-increment/header-increment - Heading levels should only increment by one level at a time - MD002 first-heading-h1/first-header-h1 - First heading should be a top level heading - MD007 ul-indent - Unordered list indentation - MD009 no-trailing-spaces - Trailing spaces - MD010 no-hard-tabs - Hard tabs - MD011 no-reversed-links - Reversed link syntax - MD025 single-h1 - Multiple top level headings in the same document - MD031 blanks-around-fences - Fenced code blocks should be surrounded by blank lines - MD032 blanks-around-lists - Lists should be surrounded by blank lines - MD040 fenced-code-language - Fenced code blocks should have a language specified - MD041 first-line-h1 - First line in file should be a top level heading * [#2441] Update documentation mustache files for Java client This commit fixes issues with Markdown/CommonMark parsing by linting and enforcing consistent style.[#2441] Issues with generated markdown files as reported by markdownlint for node.js are: - MD001 heading-increment/header-increment - Heading levels should only increment by one level at a time - MD002 first-heading-h1/first-header-h1 - First heading should be a top level heading - MD007 ul-indent - Unordered list indentation - MD009 no-trailing-spaces - Trailing spaces - MD010 no-hard-tabs - Hard tabs - MD011 no-reversed-links - Reversed link syntax - MD025 single-h1 - Multiple top level headings in the same document - MD031 blanks-around-fences - Fenced code blocks should be surrounded by blank lines - MD032 blanks-around-lists - Lists should be surrounded by blank lines - MD040 fenced-code-language - Fenced code blocks should have a language specified - MD041 first-line-h1 - First line in file should be a top level heading * [#2441] Update documentation mustache files for GO client This commit fixes issues with Markdown/CommonMark parsing by linting and enforcing consistent style.[#2441] Issues with generated markdown files as reported by markdownlint for node.js are: - MD001 heading-increment/header-increment - Heading levels should only increment by one level at a time - MD002 first-heading-h1/first-header-h1 - First heading should be a top level heading - MD007 ul-indent - Unordered list indentation - MD009 no-trailing-spaces - Trailing spaces - MD010 no-hard-tabs - Hard tabs - MD011 no-reversed-links - Reversed link syntax - MD025 single-h1 - Multiple top level headings in the same document - MD031 blanks-around-fences - Fenced code blocks should be surrounded by blank lines - MD032 blanks-around-lists - Lists should be surrounded by blank lines - MD040 fenced-code-language - Fenced code blocks should have a language specified - MD041 first-line-h1 - First line in file should be a top level heading * [#2441] Update documentation mustache files for Rust client This commit fixes issues with Markdown/CommonMark parsing by linting and enforcing consistent style.[#2441] Issues with generated markdown files as reported by markdownlint for node.js are: - MD001 heading-increment/header-increment - Heading levels should only increment by one level at a time - MD002 first-heading-h1/first-header-h1 - First heading should be a top level heading - MD007 ul-indent - Unordered list indentation - MD009 no-trailing-spaces - Trailing spaces - MD010 no-hard-tabs - Hard tabs - MD011 no-reversed-links - Reversed link syntax - MD025 single-h1 - Multiple top level headings in the same document - MD031 blanks-around-fences - Fenced code blocks should be surrounded by blank lines - MD032 blanks-around-lists - Lists should be surrounded by blank lines - MD040 fenced-code-language - Fenced code blocks should have a language specified - MD041 first-line-h1 - First line in file should be a top level heading * [#2441] Update documentation mustache files for C# client This commit fixes issues with Markdown/CommonMark parsing by linting and enforcing consistent style.[#2441] Issues with generated markdown files as reported by markdownlint for node.js are: - MD001 heading-increment/header-increment - Heading levels should only increment by one level at a time - MD002 first-heading-h1/first-header-h1 - First heading should be a top level heading - MD007 ul-indent - Unordered list indentation - MD009 no-trailing-spaces - Trailing spaces - MD010 no-hard-tabs - Hard tabs - MD011 no-reversed-links - Reversed link syntax - MD025 single-h1 - Multiple top level headings in the same document - MD031 blanks-around-fences - Fenced code blocks should be surrounded by blank lines - MD032 blanks-around-lists - Lists should be surrounded by blank lines - MD040 fenced-code-language - Fenced code blocks should have a language specified - MD041 first-line-h1 - First line in file should be a top level heading * [#2441] Update documentation mustache files for Android client This commit fixes issues with Markdown/CommonMark parsing by linting and enforcing consistent style.[#2441] Issues with generated markdown files as reported by markdownlint for node.js are: - MD001 heading-increment/header-increment - Heading levels should only increment by one level at a time - MD002 first-heading-h1/first-header-h1 - First heading should be a top level heading - MD007 ul-indent - Unordered list indentation - MD009 no-trailing-spaces - Trailing spaces - MD010 no-hard-tabs - Hard tabs - MD011 no-reversed-links - Reversed link syntax - MD025 single-h1 - Multiple top level headings in the same document - MD031 blanks-around-fences - Fenced code blocks should be surrounded by blank lines - MD032 blanks-around-lists - Lists should be surrounded by blank lines - MD040 fenced-code-language - Fenced code blocks should have a language specified - MD041 first-line-h1 - First line in file should be a top level heading * Update README.mustache * [#2441] Update documentation mustache files for Ada client This commit fixes issues with Markdown/CommonMark parsing by linting and enforcing consistent style.[#2441] * [#2441] Update documentation mustache files for Apex client This commit fixes issues with Markdown/CommonMark parsing by linting and enforcing consistent style.[#2441] * [#2441] Update documentation mustache files for bash This commit fixes issues with Markdown/CommonMark parsing by linting and enforcing consistent style.[#2441] --- README.mustache | 22 +++++++++++++++------- api_doc.mustache | 12 ++++++++---- model_doc.mustache | 1 + pojo_doc.mustache | 4 +++- 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/README.mustache b/README.mustache index 45cf63f7b6a..1a487fc280a 100644 --- a/README.mustache +++ b/README.mustache @@ -1,9 +1,11 @@ # {{artifactId}} {{appName}} + - API version: {{appVersion}} {{^hideGenerationTimestamp}} - - Build date: {{generatedDate}} + +- Build date: {{generatedDate}} {{/hideGenerationTimestamp}} {{#appDescription}}{{{appDescription}}}{{/appDescription}} @@ -14,10 +16,10 @@ *Automatically generated by the [OpenAPI Generator](https://openapi-generator.tech)* - ## Requirements Building the API client library requires: + 1. Java {{#supportJava6}}1.6{{/supportJava6}}{{^supportJava6}}{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}{{/supportJava6}}+ 2. Maven/Gradle @@ -68,8 +70,8 @@ mvn clean package Then manually install the following JARs: -* `target/{{{artifactId}}}-{{{artifactVersion}}}.jar` -* `target/lib/*.jar` +- `target/{{{artifactId}}}-{{{artifactVersion}}}.jar` +- `target/lib/*.jar` ## Getting Started @@ -141,13 +143,19 @@ Class | Method | HTTP request | Description {{/authMethods}}Authentication schemes defined for the API: {{#authMethods}}### {{name}} -{{#isApiKey}}- **Type**: API key +{{#isApiKey}} + +- **Type**: API key - **API key parameter name**: {{keyParamName}} - **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}} {{/isApiKey}} -{{#isBasic}}- **Type**: HTTP basic authentication +{{#isBasic}} + +- **Type**: HTTP basic authentication {{/isBasic}} -{{#isOAuth}}- **Type**: OAuth +{{#isOAuth}} + +- **Type**: OAuth - **Flow**: {{flow}} - **Authorization URL**: {{authorizationUrl}} - **Scopes**: {{^scopes}}N/A{{/scopes}} diff --git a/api_doc.mustache b/api_doc.mustache index 7ddb1953403..bffe140b315 100644 --- a/api_doc.mustache +++ b/api_doc.mustache @@ -1,4 +1,5 @@ # {{classname}}{{#description}} + {{description}}{{/description}} All URIs are relative to *{{basePath}}* @@ -10,8 +11,9 @@ Method | HTTP request | Description {{#operations}} {{#operation}} - -# **{{operationId}}** + +## {{operationId}} + > {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) {{summary}}{{#notes}} @@ -19,6 +21,7 @@ Method | HTTP request | Description {{notes}}{{/notes}} ### Example + ```java // Import classes:{{#hasAuthMethods}} //import {{{invokerPackage}}}.ApiClient;{{/hasAuthMethods}} @@ -59,6 +62,7 @@ try { ``` ### Parameters + {{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} Name | Type | Description | Notes ------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} @@ -75,8 +79,8 @@ Name | Type | Description | Notes ### HTTP request headers - - **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} - - **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} +- **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} +- **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} {{/operation}} {{/operations}} diff --git a/model_doc.mustache b/model_doc.mustache index 658df8d5322..9a7fe146a4e 100644 --- a/model_doc.mustache +++ b/model_doc.mustache @@ -1,3 +1,4 @@ {{#models}}{{#model}} + {{#isEnum}}{{>enum_outer_doc}}{{/isEnum}}{{^isEnum}}{{>pojo_doc}}{{/isEnum}} {{/model}}{{/models}} diff --git a/pojo_doc.mustache b/pojo_doc.mustache index 07b73cc6f5f..f297c5bc9f5 100644 --- a/pojo_doc.mustache +++ b/pojo_doc.mustache @@ -1,14 +1,16 @@ # {{classname}} ## Properties + Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- {{#vars}}**{{name}}** | {{#isEnum}}[**{{datatypeWithEnum}}**](#{{datatypeWithEnum}}){{/isEnum}}{{^isEnum}}{{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}}{{/isEnum}} | {{description}} | {{^required}} [optional]{{/required}}{{#readOnly}} [readonly]{{/readOnly}} {{/vars}} {{#vars}}{{#isEnum}} - + ## Enum: {{datatypeWithEnum}} + Name | Value ---- | -----{{#allowableValues}}{{#enumVars}} {{name}} | {{value}}{{/enumVars}}{{/allowableValues}} From 6ba87cf81f8ac60daff99b63934d55d0e11a4ce2 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Tue, 26 Mar 2019 18:52:34 +0800 Subject: [PATCH 097/370] Update Java Vertx client dependency (#2507) * update java vertx client dep * update java client description * update sample --- libraries/vertx/build.gradle.mustache | 3 ++- libraries/vertx/pom.mustache | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/vertx/build.gradle.mustache b/libraries/vertx/build.gradle.mustache index 3f434d70abf..d7652437be7 100644 --- a/libraries/vertx/build.gradle.mustache +++ b/libraries/vertx/build.gradle.mustache @@ -29,6 +29,7 @@ task execute(type:JavaExec) { ext { swagger_annotations_version = "1.5.21" jackson_version = "{{^threetenbp}}2.8.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" + jackson_databind_version = "{{^threetenbp}}2.8.11.3{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" vertx_version = "3.4.2" junit_version = "4.12" } @@ -39,7 +40,7 @@ dependencies { compile "io.vertx:vertx-rx-java:$vertx_version" compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" {{#joda}} compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache index 2b922cbcccb..5af4dc1ba9b 100644 --- a/libraries/vertx/pom.mustache +++ b/libraries/vertx/pom.mustache @@ -234,7 +234,7 @@ com.fasterxml.jackson.core jackson-databind - ${jackson-version} + ${jackson-databind} {{#joda}} @@ -278,6 +278,7 @@ 3.4.2 1.5.21 {{^threetenbp}}2.8.11{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} + {{^threetenbp}}2.8.11.3{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} 4.12 From 1ab69731e9b5b06e971a58bd8669276e5e8937b4 Mon Sep 17 00:00:00 2001 From: Michael Stummvoll Date: Wed, 27 Mar 2019 02:58:56 +0100 Subject: [PATCH 098/370] Fix JavaDoc errors in ApiClient for resttemplate (#2515) --- libraries/resttemplate/ApiClient.mustache | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libraries/resttemplate/ApiClient.mustache b/libraries/resttemplate/ApiClient.mustache index cdf398a0d58..4bc1e243843 100644 --- a/libraries/resttemplate/ApiClient.mustache +++ b/libraries/resttemplate/ApiClient.mustache @@ -342,6 +342,8 @@ public class ApiClient { /** * Parse the given string into Date object. + * @param str the string to parse + * @return the Date parsed from the string */ public Date parseDate(String str) { try { @@ -353,6 +355,8 @@ public class ApiClient { /** * Format the given Date object into string. + * @param date the date to format + * @return the formatted date as string */ public String formatDate(Date date) { return dateFormat.format(date); @@ -386,7 +390,7 @@ public class ApiClient { * Formats the specified collection path parameter to a string value. * * @param collectionFormat The collection format of the parameter. - * @param value The value of the parameter. + * @param values The values of the parameter. * @return String representation of the parameter */ public String collectionPathParameterToString(CollectionFormat collectionFormat, Collection values) { From 3a035b070a3571256bdcfaa7b5f0a366cad1abd1 Mon Sep 17 00:00:00 2001 From: davidwcarlson <516753+davidwcarlson@users.noreply.github.com> Date: Tue, 26 Mar 2019 23:07:43 -0700 Subject: [PATCH 099/370] Instantiate HttpBearerToken authentications if so declared and add helper methods. (#2485) --- ApiClient.mustache | 1 + libraries/feign/ApiClient.mustache | 22 ++++++++++++++++--- libraries/resttemplate/ApiClient.mustache | 20 +++++++++++++++-- libraries/retrofit/ApiClient.mustache | 22 ++++++++++++++++--- libraries/retrofit2/ApiClient.mustache | 22 +++++++++++++++++-- libraries/retrofit2/play24/ApiClient.mustache | 5 +++-- libraries/vertx/ApiClient.mustache | 20 +++++++++++++++-- libraries/webclient/ApiClient.mustache | 20 +++++++++++++++-- 8 files changed, 116 insertions(+), 16 deletions(-) diff --git a/ApiClient.mustache b/ApiClient.mustache index 91f479bd581..66d9c572088 100644 --- a/ApiClient.mustache +++ b/ApiClient.mustache @@ -281,6 +281,7 @@ public class ApiClient { } {{/hasOAuthMethods}} + /** * Helper method to set access token for the first Bearer authentication. * @param bearerToken Bearer token diff --git a/libraries/feign/ApiClient.mustache b/libraries/feign/ApiClient.mustache index b812bc05dfb..b121f4e3cf6 100644 --- a/libraries/feign/ApiClient.mustache +++ b/libraries/feign/ApiClient.mustache @@ -57,10 +57,11 @@ public class ApiClient { {{#hasAuthMethods}} RequestInterceptor auth; {{#authMethods}}if ("{{name}}".equals(authName)) { - {{#isBasic}} + {{#isBasic}}{{#isBasicBasic}} auth = new HttpBasicAuth(); - {{/isBasic}} - {{#isApiKey}} + {{/isBasicBasic}}{{^isBasicBasic}} + auth = new HttpBearerAuth("{{scheme}}"); + {{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"); {{/isApiKey}} {{#isOAuth}} @@ -225,6 +226,21 @@ public class ApiClient { return contentTypes[0]; } + + /** + * Helper method to configure the bearer token. + * @param bearerToken the bearer token. + */ + public void setBearerToken(String bearerToken) { + for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof HttpBearerAuth) { + ((HttpBearerAuth) apiAuthorization).setBearerToken(bearerToken); + return; + } + } + throw new RuntimeException("No Bearer authentication configured!"); + } + /** * Helper method to configure the first api key found * @param apiKey API key diff --git a/libraries/resttemplate/ApiClient.mustache b/libraries/resttemplate/ApiClient.mustache index 4bc1e243843..7aa5a692845 100644 --- a/libraries/resttemplate/ApiClient.mustache +++ b/libraries/resttemplate/ApiClient.mustache @@ -66,6 +66,7 @@ import java.util.TimeZone; import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.HttpBearerAuth; import {{invokerPackage}}.auth.ApiKeyAuth; {{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; @@ -125,8 +126,9 @@ public class ApiClient { setUserAgent("Java-SDK"); // Setup authentications (key: authentication name, value: authentication). - authentications = new HashMap();{{#authMethods}}{{#isBasic}} - authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}");{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} // Prevent the authentications from being modified. @@ -185,6 +187,20 @@ public class ApiClient { return authentications.get(authName); } + /** + * Helper method to set token for HTTP bearer authentication. + * @param bearerToken the token + */ + public void setBearerToken(String bearerToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBearerAuth) { + ((HttpBearerAuth) auth).setBearerToken(bearerToken); + return; + } + } + throw new RuntimeException("No Bearer authentication configured!"); + } + /** * Helper method to set username for the first HTTP basic authentication. * @param username the username diff --git a/libraries/retrofit/ApiClient.mustache b/libraries/retrofit/ApiClient.mustache index ed7a041dfd8..356ffb95a11 100644 --- a/libraries/retrofit/ApiClient.mustache +++ b/libraries/retrofit/ApiClient.mustache @@ -33,6 +33,7 @@ import com.squareup.okhttp.Interceptor; import com.squareup.okhttp.OkHttpClient; import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.HttpBearerAuth; import {{invokerPackage}}.auth.ApiKeyAuth; {{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; @@ -57,9 +58,11 @@ public class ApiClient { {{#hasAuthMethods}} Interceptor auth; {{#authMethods}}if ("{{name}}".equals(authName)) { - {{#isBasic}} - auth = new HttpBasicAuth(); - {{/isBasic}} + {{#isBasic}}{{#isBasicBasic}} + auth = new HttpBasicAuth(); + {{/isBasicBasic}}{{^isBasicBasic}} + auth = new HttpBearerAuth("{{scheme}}"); + {{/isBasicBasic}}{{/isBasic}} {{#isApiKey}} auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}");{{/isApiKey}} {{#isOAuth}} @@ -159,6 +162,19 @@ public class ApiClient { } } + /** + * Helper method to set token for the first Http Bearer authentication found. + * @param bearerToken Bearer token + */ + public void setBearerToken(String bearerToken) { + for (Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof HttpBearerAuth) { + ((HttpBearerAuth) apiAuthorization).setBearerToken(bearerToken); + return; + } + } + } + /** * Helper method to configure the username/password for basic auth or password oauth * @param username Username diff --git a/libraries/retrofit2/ApiClient.mustache b/libraries/retrofit2/ApiClient.mustache index 727078358c8..e5dfb17180f 100644 --- a/libraries/retrofit2/ApiClient.mustache +++ b/libraries/retrofit2/ApiClient.mustache @@ -26,6 +26,7 @@ import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; import retrofit2.converter.gson.GsonConverterFactory; import retrofit2.converter.scalars.ScalarsConverterFactory; import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.HttpBearerAuth; import {{invokerPackage}}.auth.ApiKeyAuth; {{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; @@ -62,9 +63,11 @@ public class ApiClient { {{#hasAuthMethods}} Interceptor auth; {{#authMethods}}if ("{{name}}".equals(authName)) { - {{#isBasic}} + {{#isBasic}}{{#isBasicBasic}} auth = new HttpBasicAuth(); - {{/isBasic}} + {{/isBasicBasic}}{{^isBasicBasic}} + auth = new HttpBearerAuth("{{scheme}}"); + {{/isBasicBasic}}{{/isBasic}} {{#isApiKey}} auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"); {{/isApiKey}} @@ -209,6 +212,21 @@ public class ApiClient { return this; } + /** + * Helper method to set token for the first Http Bearer authentication found. + * @param bearerToken Bearer token + * @return ApiClient + */ + public ApiClient setBearerToken(String bearerToken) { + for (Interceptor apiAuthorization : apiAuthorizations.values()) { + if (apiAuthorization instanceof HttpBearerAuth) { + ((HttpBearerAuth) apiAuthorization).setBearerToken(bearerToken); + return this; + } + } + return this; + } + /** * Helper method to configure the username/password for basic auth or password oauth * @param username Username diff --git a/libraries/retrofit2/play24/ApiClient.mustache b/libraries/retrofit2/play24/ApiClient.mustache index 8683ccc5f22..023fc3093b7 100644 --- a/libraries/retrofit2/play24/ApiClient.mustache +++ b/libraries/retrofit2/play24/ApiClient.mustache @@ -40,8 +40,9 @@ public class ApiClient { public ApiClient() { // Setup authentications (key: authentication name, value: authentication). - authentications = new HashMap<{{#supportJava6}}String, Authentication{{/supportJava6}}>();{{#authMethods}}{{#isBasic}} - // authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications = new HashMap<{{#supportJava6}}String, Authentication{{/supportJava6}}>();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + // authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} + // authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}");{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} // authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} // Prevent the authentications from being modified. diff --git a/libraries/vertx/ApiClient.mustache b/libraries/vertx/ApiClient.mustache index 9ef6b240d6c..7c6bab7c4c0 100644 --- a/libraries/vertx/ApiClient.mustache +++ b/libraries/vertx/ApiClient.mustache @@ -2,6 +2,7 @@ package {{invokerPackage}}; import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.HttpBearerAuth; import {{invokerPackage}}.auth.ApiKeyAuth; {{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; @@ -78,8 +79,9 @@ public class ApiClient { this.objectMapper.setDateFormat(dateFormat); // Setup authentications (key: authentication name, value: authentication). - this.authentications = new HashMap<>();{{#authMethods}}{{#isBasic}} - authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + this.authentications = new HashMap<>();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}");{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} // Prevent the authentications from being modified. @@ -161,6 +163,20 @@ public class ApiClient { return authentications.get(authName); } + /** + * Helper method to set access token for the first Bearer authentication. + * @param bearerToken Bearer token + */ + public ApiClient setBearerToken(String bearerToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBearerAuth) { + ((HttpBearerAuth) auth).setBearerToken(bearerToken); + return this; + } + } + throw new RuntimeException("No Bearer authentication configured!"); + } + /** * Helper method to set username for the first HTTP basic authentication. * diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index bb7a3261c2e..cdb3ce2cd36 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -59,6 +59,7 @@ import java.util.TimeZone; import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.HttpBearerAuth; import {{invokerPackage}}.auth.ApiKeyAuth; {{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; @@ -122,8 +123,9 @@ public class ApiClient { protected void init() { // Setup authentications (key: authentication name, value: authentication). - authentications = new HashMap();{{#authMethods}}{{#isBasic}} - authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}");{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} // Prevent the authentications from being modified. @@ -182,6 +184,20 @@ public class ApiClient { return authentications.get(authName); } + /** + * Helper method to set access token for the first Bearer authentication. + * @param bearerToken Bearer token + */ + public void setBearerToken(String bearerToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBearerAuth) { + ((HttpBearerAuth) auth).setBearerToken(bearerToken); + return; + } + } + throw new RuntimeException("No Bearer authentication configured!"); + } + /** * Helper method to set username for the first HTTP basic authentication. * @param username the username From 739d62159e471f4af256381dbefb7f1c18c3ecac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Vasek?= Date: Wed, 27 Mar 2019 15:10:02 +0100 Subject: [PATCH 100/370] [JAVA] Use specified data type in enum's fromValue instead of string (#2347) * Use specified data type in enum's fromValue instead of string * updated samples * update samples * remoe String.valueOf --- modelEnum.mustache | 8 ++++---- modelInnerEnum.mustache | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/modelEnum.mustache b/modelEnum.mustache index 3d21e9b2764..e22a8e6ecee 100644 --- a/modelEnum.mustache +++ b/modelEnum.mustache @@ -47,13 +47,13 @@ public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum {{#jackson}} @JsonCreator {{/jackson}} - public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue(String text) { + public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue({{{dataType}}} value) { for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { - if (String.valueOf(b.value).equals(text)) { + if (b.value.equals(value)) { return b; } } - {{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + text + "'");{{/useNullForUnknownEnumValue}} + {{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + value + "'");{{/useNullForUnknownEnumValue}} } {{#gson}} @@ -66,7 +66,7 @@ public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum @Override public {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException { {{{dataType}}} value = jsonReader.{{#isInteger}}nextInt(){{/isInteger}}{{^isInteger}}next{{{dataType}}}(){{/isInteger}}; - return {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue(String.valueOf(value)); + return {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue(value); } } {{/gson}} diff --git a/modelInnerEnum.mustache b/modelInnerEnum.mustache index 71dd9a4df16..87c23108c11 100644 --- a/modelInnerEnum.mustache +++ b/modelInnerEnum.mustache @@ -38,13 +38,13 @@ {{#jackson}} @JsonCreator {{/jackson}} - public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue(String text) { + public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue({{{dataType}}} value) { for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { - if (String.valueOf(b.value).equals(text)) { + if (b.value.equals(value)) { return b; } } - {{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + text + "'");{{/useNullForUnknownEnumValue}} + {{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + value + "'");{{/useNullForUnknownEnumValue}} } {{#gson}} @@ -57,7 +57,7 @@ @Override public {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException { {{{dataType}}} value = jsonReader.{{#isInteger}}nextInt(){{/isInteger}}{{^isInteger}}next{{{dataType}}}(){{/isInteger}}; - return {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue(String.valueOf(value)); + return {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue(value); } } {{/gson}} From 69ef80f25bfce09c0790f4f3f59050d50a0e874e Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 27 Mar 2019 23:02:03 +0800 Subject: [PATCH 101/370] improve indentation, update dependencies (#2521) --- libraries/feign/ApiClient.mustache | 10 +++++++--- libraries/okhttp-gson/pom.mustache | 4 ++-- libraries/retrofit/ApiClient.mustache | 16 ++++++++++------ libraries/retrofit2/pom.mustache | 4 ++-- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/libraries/feign/ApiClient.mustache b/libraries/feign/ApiClient.mustache index b121f4e3cf6..6d43061d347 100644 --- a/libraries/feign/ApiClient.mustache +++ b/libraries/feign/ApiClient.mustache @@ -57,11 +57,15 @@ public class ApiClient { {{#hasAuthMethods}} RequestInterceptor auth; {{#authMethods}}if ("{{name}}".equals(authName)) { - {{#isBasic}}{{#isBasicBasic}} + {{#isBasic}} + {{#isBasicBasic}} auth = new HttpBasicAuth(); - {{/isBasicBasic}}{{^isBasicBasic}} + {{/isBasicBasic}} + {{^isBasicBasic}} auth = new HttpBearerAuth("{{scheme}}"); - {{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + {{/isBasicBasic}} + {{/isBasic}} + {{#isApiKey}} auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"); {{/isApiKey}} {{#isOAuth}} diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index e3efc5851e8..5ef1fc2bf9b 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -289,14 +289,14 @@ ${java.version} 1.8.3 1.5.21 - 3.13.1 + 3.14.0 2.8.5 3.8.1 {{#joda}} 2.9.9 {{/joda}} {{#threetenbp}} - 1.3.5 + 1.3.8 {{/threetenbp}} 1.0.0 4.12 diff --git a/libraries/retrofit/ApiClient.mustache b/libraries/retrofit/ApiClient.mustache index 356ffb95a11..45327813288 100644 --- a/libraries/retrofit/ApiClient.mustache +++ b/libraries/retrofit/ApiClient.mustache @@ -58,13 +58,17 @@ public class ApiClient { {{#hasAuthMethods}} Interceptor auth; {{#authMethods}}if ("{{name}}".equals(authName)) { - {{#isBasic}}{{#isBasicBasic}} - auth = new HttpBasicAuth(); - {{/isBasicBasic}}{{^isBasicBasic}} - auth = new HttpBearerAuth("{{scheme}}"); - {{/isBasicBasic}}{{/isBasic}} + {{#isBasic}} + {{#isBasicBasic}} + auth = new HttpBasicAuth(); + {{/isBasicBasic}} + {{^isBasicBasic}} + auth = new HttpBearerAuth("{{scheme}}"); + {{/isBasicBasic}} + {{/isBasic}} {{#isApiKey}} - auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}");{{/isApiKey}} + auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"); + {{/isApiKey}} {{#isOAuth}} auth = new OAuth(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{#hasMore}}, {{/hasMore}}{{/scopes}}"); {{/isOAuth}} diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index 26ae8a95780..5c208861690 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -351,7 +351,7 @@ {{#supportJava6}}1.6{{/supportJava6}}{{^supportJava6}}{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}{{/supportJava6}} ${java.version} ${java.version} - 1.8.0 + 1.8.3 1.5.21 {{#usePlayWS}} 2.8.11.3 @@ -379,7 +379,7 @@ 2.9.9 {{/joda}} {{#threetenbp}} - 1.3.5 + 1.3.8 {{/threetenbp}} 1.0.1 4.12 From bd40316a182c15c4161f977fda851d57605aaffc Mon Sep 17 00:00:00 2001 From: Thibaud Sowa Date: Tue, 2 Apr 2019 11:43:56 +0200 Subject: [PATCH 102/370] Support OAuth without 'expires_in' data (#2563) [Java][Feign] Support OAuth without 'expires_in' data --- libraries/feign/auth/OAuth.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/feign/auth/OAuth.mustache b/libraries/feign/auth/OAuth.mustache index 0ed92dbcae9..c0344c1113f 100644 --- a/libraries/feign/auth/OAuth.mustache +++ b/libraries/feign/auth/OAuth.mustache @@ -120,7 +120,7 @@ public class OAuth implements RequestInterceptor { public synchronized void setAccessToken(String accessToken, Long expiresIn) { this.accessToken = accessToken; - this.expirationTimeMillis = System.currentTimeMillis() + expiresIn * MILLIS_PER_SECOND; + this.expirationTimeMillis = expiresIn == null ? null : System.currentTimeMillis() + expiresIn * MILLIS_PER_SECOND; } public TokenRequestBuilder getTokenRequestBuilder() { From 9a476db57c12a9b95ab48de3d46938e983cb4ceb Mon Sep 17 00:00:00 2001 From: Victor Orlovsky Date: Fri, 5 Apr 2019 19:26:11 +0300 Subject: [PATCH 103/370] [Java][Rest-assured] Update dependencies for rest-assured client (#2599) * Update dependencies for rest-assured client * Return okio_version in build.gradle.mustache --- libraries/rest-assured/build.gradle.mustache | 8 ++++---- libraries/rest-assured/build.sbt.mustache | 8 ++++---- libraries/rest-assured/pom.mustache | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/libraries/rest-assured/build.gradle.mustache b/libraries/rest-assured/build.gradle.mustache index af9e49e0dfb..03ea659d066 100644 --- a/libraries/rest-assured/build.gradle.mustache +++ b/libraries/rest-assured/build.gradle.mustache @@ -96,15 +96,15 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.21" - rest_assured_version = "3.1.0" + rest_assured_version = "3.3.0" junit_version = "4.12" - gson_version = "2.6.1" - gson_fire_version = "1.8.2" + gson_version = "2.8.5" + gson_fire_version = "1.8.3" {{#joda}} jodatime_version = "2.9.9" {{/joda}} {{#threetenbp}} - threetenbp_version = "1.3.5" + threetenbp_version = "1.3.8" {{/threetenbp}} okio_version = "1.13.0" } diff --git a/libraries/rest-assured/build.sbt.mustache b/libraries/rest-assured/build.sbt.mustache index 7a666ebace6..454ff06c346 100644 --- a/libraries/rest-assured/build.sbt.mustache +++ b/libraries/rest-assured/build.sbt.mustache @@ -10,14 +10,14 @@ lazy val root = (project in file(".")). resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( "io.swagger" % "swagger-annotations" % "1.5.21", - "io.rest-assured" % "scala-support" % "3.1.0", - "com.google.code.gson" % "gson" % "2.6.1", - "io.gsonfire" % "gson-fire" % "1.8.2" % "compile", + "io.rest-assured" % "scala-support" % "3.3.0", + "com.google.code.gson" % "gson" % "2.8.5", + "io.gsonfire" % "gson-fire" % "1.8.3" % "compile", {{#joda}} "joda-time" % "joda-time" % "2.9.9" % "compile", {{/joda}} {{#threetenbp}} - "org.threeten" % "threetenbp" % "1.3.5" % "compile", + "org.threeten" % "threetenbp" % "1.3.8" % "compile", {{/threetenbp}} "com.squareup.okio" % "okio" % "1.13.0" % "compile", "junit" % "junit" % "4.12" % "test", diff --git a/libraries/rest-assured/pom.mustache b/libraries/rest-assured/pom.mustache index 64285da8111..d480939b403 100644 --- a/libraries/rest-assured/pom.mustache +++ b/libraries/rest-assured/pom.mustache @@ -251,15 +251,15 @@ UTF-8 1.5.21 - 3.1.0 - 2.6.1 - 1.8.2 + 3.3.0 + 2.8.5 + 1.8.3 1.0.0 {{#joda}} 2.9.9 {{/joda}} {{#threetenbp}} - 1.3.5 + 1.3.8 {{/threetenbp}} 1.13.0 4.12 From 6c169b5c7c7be0526dd44d8c64bdc7ca39510383 Mon Sep 17 00:00:00 2001 From: Hugo Barrigas Date: Fri, 19 Apr 2019 07:46:28 +0100 Subject: [PATCH 104/370] [JAVA][Webclient]fix select body for url encoded media type. (#2686) * fix select body for url encoded media type. * run bin. --- libraries/webclient/ApiClient.mustache | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index cdb3ce2cd36..7f2d3c35cbc 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -472,8 +472,20 @@ public class ApiClient { * @return Object the selected body */ protected BodyInserter selectBody(Object obj, MultiValueMap formParams, MediaType contentType) { - boolean isForm = MediaType.MULTIPART_FORM_DATA.isCompatibleWith(contentType) || MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(contentType); - return isForm ? BodyInserters.fromMultipartData(formParams) : (obj != null ? BodyInserters.fromObject(obj) : null); + if(MediaType.APPLICATION_FORM_URLENCODED.equals(contentType)) { + MultiValueMap map = new LinkedMultiValueMap(); + + formParams + .toSingleValueMap() + .entrySet() + .forEach(es -> map.add(es.getKey(), (String) es.getValue())); + + return BodyInserters.fromFormData(map); + } else if(MediaType.MULTIPART_FORM_DATA.equals(contentType)) { + return BodyInserters.fromMultipartData(formParams); + } else { + return obj != null ? BodyInserters.fromObject(obj) : null; + } } /** From c9ccb2203961f9eaa0e4a0ba858ac1d4696f6eb3 Mon Sep 17 00:00:00 2001 From: Ferdinand Beyer Date: Tue, 23 Apr 2019 18:56:38 +0200 Subject: [PATCH 105/370] Add missing closing parenthesis (#2720) --- libraries/webclient/ApiClient.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index 7f2d3c35cbc..943acff9c37 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -125,7 +125,7 @@ public class ApiClient { // Setup authentications (key: authentication name, value: authentication). authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} - authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}");{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} // Prevent the authentications from being modified. From eddd0cd1476519d21b75a70a1b59042eff70642b Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 24 Apr 2019 10:46:40 +0800 Subject: [PATCH 106/370] fix missing parenthesis for http bearer auth (#2723) --- libraries/resttemplate/ApiClient.mustache | 2 +- libraries/retrofit2/play24/ApiClient.mustache | 2 +- libraries/vertx/ApiClient.mustache | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/resttemplate/ApiClient.mustache b/libraries/resttemplate/ApiClient.mustache index 7aa5a692845..3f8f6a0f4de 100644 --- a/libraries/resttemplate/ApiClient.mustache +++ b/libraries/resttemplate/ApiClient.mustache @@ -128,7 +128,7 @@ public class ApiClient { // Setup authentications (key: authentication name, value: authentication). authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} - authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}");{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} // Prevent the authentications from being modified. diff --git a/libraries/retrofit2/play24/ApiClient.mustache b/libraries/retrofit2/play24/ApiClient.mustache index 023fc3093b7..e03dc69971b 100644 --- a/libraries/retrofit2/play24/ApiClient.mustache +++ b/libraries/retrofit2/play24/ApiClient.mustache @@ -42,7 +42,7 @@ public class ApiClient { // Setup authentications (key: authentication name, value: authentication). authentications = new HashMap<{{#supportJava6}}String, Authentication{{/supportJava6}}>();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} // authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} - // authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}");{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + // authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} // authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} // Prevent the authentications from being modified. diff --git a/libraries/vertx/ApiClient.mustache b/libraries/vertx/ApiClient.mustache index 7c6bab7c4c0..0b515c04898 100644 --- a/libraries/vertx/ApiClient.mustache +++ b/libraries/vertx/ApiClient.mustache @@ -81,7 +81,7 @@ public class ApiClient { // Setup authentications (key: authentication name, value: authentication). this.authentications = new HashMap<>();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} - authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}");{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} // Prevent the authentications from being modified. From 3dee1d813b7ea15a43f046e7a05a519cb8123f40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9res=20Zolt=C3=A1n?= Date: Thu, 9 May 2019 18:56:39 +0200 Subject: [PATCH 107/370] Fixed vertex ApiClient template (#2841) * updated java/vertex ApiClient template * update java samples --- libraries/vertx/ApiClient.mustache | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/vertx/ApiClient.mustache b/libraries/vertx/ApiClient.mustache index 0b515c04898..170c92666ed 100644 --- a/libraries/vertx/ApiClient.mustache +++ b/libraries/vertx/ApiClient.mustache @@ -567,20 +567,21 @@ public class ApiClient { if (httpResponse.statusCode() == 204 || returnType == null) { result = Future.succeededFuture(null); } else { - T resultContent; + T resultContent = null; if ("byte[]".equals(returnType.getType().toString())) { resultContent = (T) httpResponse.body().getBytes(); + result = Future.succeededFuture(resultContent); } else if (AsyncFile.class.equals(returnType.getType())) { handleFileDownload(httpResponse, handler); return; } else { try { resultContent = Json.mapper.readValue(httpResponse.bodyAsString(), returnType); + result = Future.succeededFuture(resultContent); } catch (Exception e) { - throw new DecodeException("Failed to decode:" + e.getMessage(), e); + result = ApiException.fail(new DecodeException("Failed to decode:" + e.getMessage(), e)); } } - result = Future.succeededFuture(resultContent); } } else { result = ApiException.fail(httpResponse.statusMessage(), httpResponse.statusCode(), httpResponse.headers(), httpResponse.bodyAsString()); From e131e94300a178a5e0581010db623fcb8772f49a Mon Sep 17 00:00:00 2001 From: William Cheng Date: Mon, 13 May 2019 15:59:59 +0800 Subject: [PATCH 108/370] Minor wording change (#2875) * better wording for version of openapi doc * update petstore samples --- licenseInfo.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/licenseInfo.mustache b/licenseInfo.mustache index 335db1c5938..abc2f4578eb 100644 --- a/licenseInfo.mustache +++ b/licenseInfo.mustache @@ -2,7 +2,7 @@ * {{{appName}}} * {{{appDescription}}} * - * {{#version}}OpenAPI spec version: {{{version}}}{{/version}} + * {{#version}}The version of the OpenAPI document: {{{version}}}{{/version}} * {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}} * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). From b6e3a0030a9c8f498f54f419711609511d985489 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Sat, 25 May 2019 18:24:37 +0800 Subject: [PATCH 109/370] Update jackson-databind to address security issues (#2993) * update jackson-databind to address security issue * update java vertx client dev, sample * update dep, samples * update retrofit play2 dep --- build.gradle.mustache | 7 ++++--- libraries/feign/build.gradle.mustache | 6 +++--- libraries/feign/build.sbt.mustache | 8 ++++---- libraries/feign/pom.mustache | 4 ++-- libraries/google-api-client/build.gradle.mustache | 6 +++--- libraries/google-api-client/build.sbt.mustache | 14 +++++++------- libraries/google-api-client/pom.mustache | 6 +++--- libraries/jersey2/build.gradle.mustache | 6 +++--- libraries/jersey2/build.sbt.mustache | 12 ++++++------ libraries/jersey2/pom.mustache | 6 +++--- libraries/resteasy/build.gradle.mustache | 6 +++--- libraries/resteasy/build.sbt.mustache | 8 ++++---- libraries/resteasy/pom.mustache | 6 +++--- libraries/resttemplate/build.gradle.mustache | 6 +++--- libraries/resttemplate/pom.mustache | 6 +++--- libraries/retrofit2/build.gradle.mustache | 8 ++++---- libraries/retrofit2/build.sbt.mustache | 12 ++++++------ libraries/retrofit2/pom.mustache | 8 ++++---- libraries/vertx/build.gradle.mustache | 4 ++-- libraries/vertx/pom.mustache | 6 +++--- libraries/webclient/pom.mustache | 6 +++--- 21 files changed, 76 insertions(+), 75 deletions(-) diff --git a/build.gradle.mustache b/build.gradle.mustache index 04a9d55cfd7..2e00ae91d1f 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -32,6 +32,7 @@ if(hasProperty('target') && target == 'android') { minSdkVersion 14 targetSdkVersion 25 } + compileOptions { {{#supportJava6}} sourceCompatibility JavaVersion.VERSION_1_6 @@ -134,9 +135,9 @@ if(hasProperty('target') && target == 'android') { } ext { - swagger_annotations_version = "1.5.17" - jackson_version = "{{^threetenbp}}2.8.11{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" - jackson_databind_version = "{{^threetenbp}}2.8.11.2{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" + swagger_annotations_version = "1.5.22" + jackson_version = "{{^threetenbp}}2.9.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" + jackson_databind_version = "{{^threetenbp}}2.9.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" jersey_version = "1.19.4" jodatime_version = "2.9.9" junit_version = "4.12" diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index c96666e2aa5..041a5c09203 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -119,9 +119,9 @@ if(hasProperty('target') && target == 'android') { } ext { - swagger_annotations_version = "1.5.21" - jackson_version = "2.8.11" - jackson_databind_version = "2.8.11.3" + swagger_annotations_version = "1.5.22" + jackson_version = "2.9.9" + jackson_databind_version = "2.9.9" {{#threetenbp}} threepane_version = "2.6.4" {{/threetenbp}} diff --git a/libraries/feign/build.sbt.mustache b/libraries/feign/build.sbt.mustache index 2168e3e9f6e..3a6532530d8 100644 --- a/libraries/feign/build.sbt.mustache +++ b/libraries/feign/build.sbt.mustache @@ -9,14 +9,14 @@ lazy val root = (project in file(".")). publishArtifact in (Compile, packageDoc) := false, resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( - "io.swagger" % "swagger-annotations" % "1.5.21" % "compile", + "io.swagger" % "swagger-annotations" % "1.5.22" % "compile", "io.github.openfeign" % "feign-core" % "{{#useFeign10}}10.0.1{{/useFeign10}}{{^useFeign10}}9.4.0{{/useFeign10}}" % "compile", "io.github.openfeign" % "feign-jackson" % "{{#useFeign10}}10.0.1{{/useFeign10}}{{^useFeign10}}9.4.0{{/useFeign10}}" % "compile", "io.github.openfeign" % "feign-slf4j" % "{{#useFeign10}}10.0.1{{/useFeign10}}{{^useFeign10}}9.4.0{{/useFeign10}}" % "compile", "io.github.openfeign.form" % "feign-form" % "2.1.0" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.8.11" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.11" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.9.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.9" % "compile", "com.fasterxml.jackson.datatype" % "jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}" % "2.8.7" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4" % "compile", "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index ebfe5859b1f..e685755460e 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -302,8 +302,8 @@ 1.5.21 {{#useFeign10}}10.0.1{{/useFeign10}}{{^useFeign10}}9.4.0{{/useFeign10}} 2.1.0 - 2.8.11 - 2.8.11.3 + 2.9.9 + 2.9.9 {{#threetenbp}} 2.6.4 {{/threetenbp}} diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache index 62f9f6b6d4e..f8d3ce9d785 100644 --- a/libraries/google-api-client/build.gradle.mustache +++ b/libraries/google-api-client/build.gradle.mustache @@ -119,9 +119,9 @@ if(hasProperty('target') && target == 'android') { } ext { - swagger_annotations_version = "1.5.21" - jackson_version = "2.8.11" - jackson_databind_version = "2.8.11.3" + swagger_annotations_version = "1.5.22" + jackson_version = "2.9.9" + jackson_databind_version = "2.9.9" google_api_client_version = "1.23.0" jersey_common_version = "2.25.1" jodatime_version = "2.9.9" diff --git a/libraries/google-api-client/build.sbt.mustache b/libraries/google-api-client/build.sbt.mustache index 10f26b64932..48f28b25d1b 100644 --- a/libraries/google-api-client/build.sbt.mustache +++ b/libraries/google-api-client/build.sbt.mustache @@ -9,20 +9,20 @@ lazy val root = (project in file(".")). publishArtifact in (Compile, packageDoc) := false, resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( - "io.swagger" % "swagger-annotations" % "1.5.21", + "io.swagger" % "swagger-annotations" % "1.5.22", "com.google.api-client" % "google-api-client" % "1.23.0", "org.glassfish.jersey.core" % "jersey-common" % "2.25.1", - "com.fasterxml.jackson.core" % "jackson-core" % "2.8.11" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.11" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.9.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.9" % "compile", {{#withXml}} - "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.8.9" % "compile", + "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.9.9" % "compile", {{/withXml}} {{#joda}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.8.9" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.9" % "compile", {{/joda}} {{#java8}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.8.9" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.9" % "compile", {{/java8}} {{#threetenbp}} "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4" % "compile", diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index db32695d81b..35f0cafdf98 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -292,11 +292,11 @@ UTF-8 - 1.5.21 + 1.5.22 1.23.0 2.25.1 - 2.8.11 - 2.8.11.3 + 2.9.9 + 2.9.9 {{#joda}} 2.9.9 {{/joda}} diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index dfd4cda7506..6ca2e18a7cd 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -118,9 +118,9 @@ if(hasProperty('target') && target == 'android') { } ext { - swagger_annotations_version = "1.5.21" - jackson_version = "2.8.11" - jackson_databind_version = "2.8.11.3" + swagger_annotations_version = "1.5.22" + jackson_version = "2.9.9" + jackson_databind_version = "2.9.9" {{#supportJava6}} jersey_version = "2.6" commons_io_version=2.5 diff --git a/libraries/jersey2/build.sbt.mustache b/libraries/jersey2/build.sbt.mustache index 64157fb6cb2..d5d69065495 100644 --- a/libraries/jersey2/build.sbt.mustache +++ b/libraries/jersey2/build.sbt.mustache @@ -9,18 +9,18 @@ lazy val root = (project in file(".")). publishArtifact in (Compile, packageDoc) := false, resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( - "io.swagger" % "swagger-annotations" % "1.5.21", + "io.swagger" % "swagger-annotations" % "1.5.22", "org.glassfish.jersey.core" % "jersey-client" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, "org.glassfish.jersey.media" % "jersey-media-multipart" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, "org.glassfish.jersey.media" % "jersey-media-json-jackson" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, - "com.fasterxml.jackson.core" % "jackson-core" % "2.8.11" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.11" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.9.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.9" % "compile", {{#joda}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.8.9" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.9" % "compile", {{/joda}} {{#java8}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.8.9" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.9" % "compile", {{/java8}} {{#threetenbp}} "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4" % "compile", diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 026b777ec9a..3c0af2dac5f 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -323,7 +323,7 @@ UTF-8 - 1.5.21 + 1.5.22 {{^supportJava6}} 2.27 {{/supportJava6}} @@ -332,8 +332,8 @@ 2.5 3.6 {{/supportJava6}} - 2.8.11 - 2.8.11.3 + 2.9.9 + 2.9.9 {{#threetenbp}} 2.6.4 {{/threetenbp}} diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index bb64ceda849..16da888f26a 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -118,9 +118,9 @@ if(hasProperty('target') && target == 'android') { } ext { - swagger_annotations_version = "1.5.21" - jackson_version = "2.8.11" - jackson_databind_version = "2.8.11.3" + swagger_annotations_version = "1.5.22" + jackson_version = "2.9.9" + jackson_databind_version = "2.9.9" threetenbp_version = "2.6.4" resteasy_version = "3.1.3.Final" {{^java8}} diff --git a/libraries/resteasy/build.sbt.mustache b/libraries/resteasy/build.sbt.mustache index 5f713ff9033..81170d4c520 100644 --- a/libraries/resteasy/build.sbt.mustache +++ b/libraries/resteasy/build.sbt.mustache @@ -9,13 +9,13 @@ lazy val root = (project in file(".")). publishArtifact in (Compile, packageDoc) := false, resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( - "io.swagger" % "swagger-annotations" % "1.5.21" % "compile", + "io.swagger" % "swagger-annotations" % "1.5.22" % "compile", "org.jboss.resteasy" % "resteasy-client" % "3.1.3.Final" % "compile", "org.jboss.resteasy" % "resteasy-multipart-provider" % "3.1.3.Final" % "compile", "org.jboss.resteasy" % "resteasy-jackson2-provider" % "3.1.3.Final" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.8.11" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.11" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.9.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.9" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4" % "compile", {{#java8}} "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.8.6" % "compile", diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index ab5332b4cb6..48b52419739 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -281,10 +281,10 @@ UTF-8 - 1.5.21 + 1.5.22 3.1.3.Final - 2.8.11 - 2.8.11.3 + 2.9.9 + 2.9.9 2.6.4 {{^java8}} 2.9.9 diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index d1ea2074850..eae0fa4e4aa 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -119,9 +119,9 @@ if(hasProperty('target') && target == 'android') { } ext { - swagger_annotations_version = "1.5.21" - jackson_version = "2.8.11" - jackson_databind_version = "2.8.11.3" + swagger_annotations_version = "1.5.22" + jackson_version = "2.9.9" + jackson_databind_version = "2.9.9" spring_web_version = "4.3.9.RELEASE" jodatime_version = "2.9.9" junit_version = "4.12" diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache index 600880cb6a0..39a4a7c8d8d 100644 --- a/libraries/resttemplate/pom.mustache +++ b/libraries/resttemplate/pom.mustache @@ -295,10 +295,10 @@ UTF-8 - 1.5.21 + 1.5.22 4.3.9.RELEASE - 2.8.11 - 2.8.11.3 + 2.9.9 + 2.9.9 {{#joda}} 2.9.9 {{/joda}} diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index 125f276b399..39574a5755f 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -127,16 +127,16 @@ ext { play_version = "2.4.11" {{/play24}} {{#play25}} - jackson_version = "2.7.8" + jackson_version = "2.9.9" play_version = "2.5.14" {{/play25}} {{#play26}} - jackson_version = "2.8.11" - jackson_databind_version = "2.8.11.3" + jackson_version = "2.9.9" + jackson_databind_version = "2.9.9" play_version = "2.6.7" {{/play26}} {{/usePlayWS}} - swagger_annotations_version = "1.5.21" + swagger_annotations_version = "1.5.22" junit_version = "4.12" {{#useRxJava}} rx_java_version = "1.3.0" diff --git a/libraries/retrofit2/build.sbt.mustache b/libraries/retrofit2/build.sbt.mustache index 4c7a766cdce..21b00d3b91e 100644 --- a/libraries/retrofit2/build.sbt.mustache +++ b/libraries/retrofit2/build.sbt.mustache @@ -23,16 +23,16 @@ lazy val root = (project in file(".")). {{/play24}} {{#play25}} "com.typesafe.play" % "play-java-ws_2.11" % "2.5.15" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.7.8" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.7.8" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.7.8" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.9.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.9" % "compile", {{/play25}} {{#play26}} "com.typesafe.play" % "play-ahc-ws_2.12" % "2.6.7" % "compile", "javax.validation" % "validation-api" % "1.1.0.Final" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.8.11" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.8.11" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.8.11.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.9.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.9" % "compile", {{/play26}} "com.squareup.retrofit2" % "converter-jackson" % "2.3.0" % "compile", {{/usePlayWS}} diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index 5c208861690..4653b6650a1 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -352,19 +352,19 @@ ${java.version} ${java.version} 1.8.3 - 1.5.21 + 1.5.22 {{#usePlayWS}} - 2.8.11.3 + 2.9.9 {{#play24}} 2.6.6 2.4.11 {{/play24}} {{#play25}} - 2.7.8 + 2.9.9 2.5.15 {{/play25}} {{#play26}} - 2.8.11 + 2.9.9 2.6.7 {{/play26}} {{/usePlayWS}} diff --git a/libraries/vertx/build.gradle.mustache b/libraries/vertx/build.gradle.mustache index d7652437be7..1e97c1e2599 100644 --- a/libraries/vertx/build.gradle.mustache +++ b/libraries/vertx/build.gradle.mustache @@ -28,8 +28,8 @@ task execute(type:JavaExec) { ext { swagger_annotations_version = "1.5.21" - jackson_version = "{{^threetenbp}}2.8.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" - jackson_databind_version = "{{^threetenbp}}2.8.11.3{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" + jackson_version = "{{^threetenbp}}2.9.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" + jackson_databind_version = "{{^threetenbp}}2.9.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" vertx_version = "3.4.2" junit_version = "4.12" } diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache index 5af4dc1ba9b..c3976600d94 100644 --- a/libraries/vertx/pom.mustache +++ b/libraries/vertx/pom.mustache @@ -276,9 +276,9 @@ UTF-8 3.4.2 - 1.5.21 - {{^threetenbp}}2.8.11{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} - {{^threetenbp}}2.8.11.3{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} + 1.5.22 + {{^threetenbp}}2.9.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} + {{^threetenbp}}2.9.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} 4.12 diff --git a/libraries/webclient/pom.mustache b/libraries/webclient/pom.mustache index d44f942930a..8919c3d481a 100644 --- a/libraries/webclient/pom.mustache +++ b/libraries/webclient/pom.mustache @@ -129,10 +129,10 @@ UTF-8 - 1.5.20 + 1.5.22 5.0.7.RELEASE - 2.8.11 - 2.8.11.3 + 2.9.9 + 2.9.9 4.12 3.1.8.RELEASE 0.7.8.RELEASE From 84024dd20c0b31f4a9822b0361e0e609644bcc5d Mon Sep 17 00:00:00 2001 From: William Cheng Date: Mon, 27 May 2019 00:26:24 +0800 Subject: [PATCH 110/370] update jackson joda version, samples (#3005) --- libraries/resteasy/build.sbt.mustache | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/resteasy/build.sbt.mustache b/libraries/resteasy/build.sbt.mustache index 81170d4c520..4f67eb38823 100644 --- a/libraries/resteasy/build.sbt.mustache +++ b/libraries/resteasy/build.sbt.mustache @@ -18,10 +18,10 @@ lazy val root = (project in file(".")). "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.9" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4" % "compile", {{#java8}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.8.6" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.9" % "compile", {{/java8}} {{^java8}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.7.5" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.9" % "compile", "joda-time" % "joda-time" % "2.9.9" % "compile", "com.brsanthu" % "migbase64" % "2.2" % "compile", {{/java8}} From b0a334099044a245626eb1ebb09dc7d180333a51 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Mon, 27 May 2019 15:11:02 +0800 Subject: [PATCH 111/370] update feign to the latest stable version (#2999) --- libraries/feign/auth/OAuth.mustache | 2 +- libraries/feign/build.gradle.mustache | 2 +- libraries/feign/build.sbt.mustache | 8 ++++---- libraries/feign/pom.mustache | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libraries/feign/auth/OAuth.mustache b/libraries/feign/auth/OAuth.mustache index c0344c1113f..25b1f193ba9 100644 --- a/libraries/feign/auth/OAuth.mustache +++ b/libraries/feign/auth/OAuth.mustache @@ -96,7 +96,7 @@ public class OAuth implements RequestInterceptor { accessTokenResponse = oauthClient.accessToken(tokenRequestBuilder.buildBodyMessage()); } catch (Exception e) { {{#useFeign10}} - throw new RetryableException(e.getMessage(), HttpMethod.POST, e, null); + throw new RetryableException(0, e.getMessage(), HttpMethod.POST, e, null); {{/useFeign10}} {{^useFeign10}} throw new RetryableException(e.getMessage(), e,null); diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index 041a5c09203..24e5e816cac 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -125,7 +125,7 @@ ext { {{#threetenbp}} threepane_version = "2.6.4" {{/threetenbp}} - feign_version = "{{#useFeign10}}10.0.1{{/useFeign10}}{{^useFeign10}}9.4.0{{/useFeign10}}" + feign_version = "{{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" feign_form_version = "2.1.0" junit_version = "4.12" oltu_version = "1.0.1" diff --git a/libraries/feign/build.sbt.mustache b/libraries/feign/build.sbt.mustache index 3a6532530d8..946b3195611 100644 --- a/libraries/feign/build.sbt.mustache +++ b/libraries/feign/build.sbt.mustache @@ -10,14 +10,14 @@ lazy val root = (project in file(".")). resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( "io.swagger" % "swagger-annotations" % "1.5.22" % "compile", - "io.github.openfeign" % "feign-core" % "{{#useFeign10}}10.0.1{{/useFeign10}}{{^useFeign10}}9.4.0{{/useFeign10}}" % "compile", - "io.github.openfeign" % "feign-jackson" % "{{#useFeign10}}10.0.1{{/useFeign10}}{{^useFeign10}}9.4.0{{/useFeign10}}" % "compile", - "io.github.openfeign" % "feign-slf4j" % "{{#useFeign10}}10.0.1{{/useFeign10}}{{^useFeign10}}9.4.0{{/useFeign10}}" % "compile", + "io.github.openfeign" % "feign-core" % "{{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", + "io.github.openfeign" % "feign-jackson" % "{{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", + "io.github.openfeign" % "feign-slf4j" % "{{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", "io.github.openfeign.form" % "feign-form" % "2.1.0" % "compile", "com.fasterxml.jackson.core" % "jackson-core" % "2.9.9" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.9" % "compile", "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.9" % "compile", - "com.fasterxml.jackson.datatype" % "jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}" % "2.8.7" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}" % "2.9.9" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4" % "compile", "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", "com.brsanthu" % "migbase64" % "2.2" % "compile", diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index e685755460e..21954ad8ad4 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -300,7 +300,7 @@ ${java.version} ${java.version} 1.5.21 - {{#useFeign10}}10.0.1{{/useFeign10}}{{^useFeign10}}9.4.0{{/useFeign10}} + {{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}} 2.1.0 2.9.9 2.9.9 From 721ccafd09597eb4b14e3df8e05dd597b137349d Mon Sep 17 00:00:00 2001 From: Sai Giridhar P Date: Tue, 28 May 2019 22:25:59 +0530 Subject: [PATCH 112/370] [java-okhttpgson]: Include API's Http response codes and their corresponding description and response headers in the documentation (#2995) * fix(okhttp-gson-java): Adding response headers on api_doc.mustache * feat(okhttp-gson): Adding Http response headers to docs and javadocs * feat(okhttp-gson): Included dots in custom tage * feat(java-okhttpgson): Updating pet project * feat(java-okhttpgson): Updating other pet project --- libraries/okhttp-gson/api.mustache | 81 ++++++++++++++++++++++++++ libraries/okhttp-gson/api_doc.mustache | 9 +++ libraries/okhttp-gson/pom.mustache | 9 +++ 3 files changed, 99 insertions(+) diff --git a/libraries/okhttp-gson/api.mustache b/libraries/okhttp-gson/api.mustache index 3705e654e09..32b1e3fcf04 100644 --- a/libraries/okhttp-gson/api.mustache +++ b/libraries/okhttp-gson/api.mustache @@ -69,6 +69,15 @@ public class {{classname}} { * @param _callback Callback for upload/download progress * @return Call to execute * @throws ApiException If fail to serialize the request body object + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} {{#isDeprecated}} * @deprecated {{/isDeprecated}} @@ -179,6 +188,15 @@ public class {{classname}} { * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}{{/allParams}}{{#returnType}} * @return {{returnType}}{{/returnType}} * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} {{#isDeprecated}} * @deprecated {{/isDeprecated}} @@ -202,6 +220,15 @@ public class {{classname}} { * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}{{/allParams}} * @return ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} {{#isDeprecated}} * @deprecated {{/isDeprecated}} @@ -226,6 +253,15 @@ public class {{classname}} { * @param _callback The callback to be executed when the API call finishes * @return The request call * @throws ApiException If fail to process the API call, e.g. serializing the request body object + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} {{#isDeprecated}} * @deprecated {{/isDeprecated}} @@ -277,6 +313,15 @@ public class {{classname}} { * @param _callback ApiCallback API callback * @return Call to execute * @throws ApiException If fail to serialize the request body object + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} {{#isDeprecated}} * @deprecated {{/isDeprecated}} @@ -292,6 +337,15 @@ public class {{classname}} { * Execute {{operationId}} request{{#returnType}} * @return {{returnType}}{{/returnType}} * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} {{#isDeprecated}} * @deprecated {{/isDeprecated}} @@ -308,6 +362,15 @@ public class {{classname}} { * Execute {{operationId}} request with HTTP info returned * @return ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} {{#isDeprecated}} * @deprecated {{/isDeprecated}} @@ -324,6 +387,15 @@ public class {{classname}} { * @param _callback The callback to be executed when the API call finishes * @return The request call * @throws ApiException If fail to process the API call, e.g. serializing the request body object + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} {{#isDeprecated}} * @deprecated {{/isDeprecated}} @@ -341,6 +413,15 @@ public class {{classname}} { * {{notes}}{{#requiredParams}} * @param {{paramName}} {{description}} (required){{/requiredParams}} * @return API{{operationId}}Request + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} {{#isDeprecated}} * @deprecated {{/isDeprecated}} diff --git a/libraries/okhttp-gson/api_doc.mustache b/libraries/okhttp-gson/api_doc.mustache index 1292eb3aa84..7c798325d39 100644 --- a/libraries/okhttp-gson/api_doc.mustache +++ b/libraries/okhttp-gson/api_doc.mustache @@ -81,5 +81,14 @@ Name | Type | Description | Notes - **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} - **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} +{{#responses.0}} +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +{{#responses}} +**{{code}}** | {{message}} | {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}} | +{{/responses}} +{{/responses.0}} + {{/operation}} {{/operations}} diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index 5ef1fc2bf9b..eac0a4e1ba2 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -149,6 +149,15 @@ jar + + + + http.response.details + a + Http Response Details: + + + From 5dcea72947466740218a3362fe283ddffe4ef1b6 Mon Sep 17 00:00:00 2001 From: Sai Giridhar P Date: Tue, 28 May 2019 22:28:23 +0530 Subject: [PATCH 113/370] [java-okhttp]: Make example snippets code compilable (#3016) * fix(okhttp-gson): Make example executable * fix(okhttp-gson): Make example executable * fix(okhttp-gson): Make example executable * fix(okhttp-gson): Updating pet project * fix(okhttp-gson): Updating parcelable project * fix(okhttp-gson): Using {{{}}} --- libraries/okhttp-gson/README.mustache | 82 ++++++++++++++------------ libraries/okhttp-gson/api_doc.mustache | 79 ++++++++++++++----------- 2 files changed, 87 insertions(+), 74 deletions(-) diff --git a/libraries/okhttp-gson/README.mustache b/libraries/okhttp-gson/README.mustache index 441a7849436..07636f62a4e 100644 --- a/libraries/okhttp-gson/README.mustache +++ b/libraries/okhttp-gson/README.mustache @@ -77,48 +77,52 @@ Please follow the [installation](#installation) instruction and execute the foll ```java {{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}} -import {{{invokerPackage}}}.*; -import {{{invokerPackage}}}.auth.*; -import {{{modelPackage}}}.*; +// Import classes: +import {{{invokerPackage}}}.ApiClient; +import {{{invokerPackage}}}.ApiException; +import {{{invokerPackage}}}.Configuration;{{#hasAuthMethods}} +import {{{invokerPackage}}}.auth.*;{{/hasAuthMethods}} +import {{{invokerPackage}}}.models.*; import {{{package}}}.{{{classname}}}; -import java.io.File; -import java.util.*; - -public class {{{classname}}}Example { - - public static void main(String[] args) { - {{#hasAuthMethods}}ApiClient defaultClient = Configuration.getDefaultApiClient(); - {{#authMethods}}{{#isBasic}} - // Configure HTTP basic authorization: {{{name}}} - HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); - {{{name}}}.setUsername("YOUR USERNAME"); - {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasic}}{{#isApiKey}} - // Configure API key authorization: {{{name}}} - ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); - {{{name}}}.setApiKey("YOUR API KEY"); - // Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null) - //{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} - // Configure OAuth2 access token for authorization: {{{name}}} - OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); - {{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}} - {{/authMethods}} - {{/hasAuthMethods}} - - {{{classname}}} apiInstance = new {{{classname}}}(); - {{#allParams}} - {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} - {{/allParams}} - try { - {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}{{^vendorExtensions.x-group-parameters}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}({{#requiredParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}){{#optionalParams}} - .{{{paramName}}}({{{paramName}}}){{/optionalParams}} - .execute();{{/vendorExtensions.x-group-parameters}}{{#returnType}} - System.out.println(result);{{/returnType}} - } catch (ApiException e) { - System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); - e.printStackTrace(); - } +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("{{{basePath}}}"); + {{#hasAuthMethods}} + {{#authMethods}}{{#isBasic}} + // Configure HTTP basic authorization: {{{name}}} + HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setUsername("YOUR USERNAME"); + {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasic}}{{#isApiKey}} + // Configure API key authorization: {{{name}}} + ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setApiKey("YOUR API KEY"); + // Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null) + //{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} + // Configure OAuth2 access token for authorization: {{{name}}} + OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}} + {{/authMethods}} + {{/hasAuthMethods}} + + {{{classname}}} apiInstance = new {{{classname}}}(defaultClient); + {{#allParams}} + {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} + {{/allParams}} + try { + {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}{{^vendorExtensions.x-group-parameters}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}({{#requiredParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}){{#optionalParams}} + .{{{paramName}}}({{{paramName}}}){{/optionalParams}} + .execute();{{/vendorExtensions.x-group-parameters}}{{#returnType}} + System.out.println(result);{{/returnType}} + } catch (ApiException e) { + System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); } + } } {{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} ``` diff --git a/libraries/okhttp-gson/api_doc.mustache b/libraries/okhttp-gson/api_doc.mustache index 7c798325d39..720b4d3c5ee 100644 --- a/libraries/okhttp-gson/api_doc.mustache +++ b/libraries/okhttp-gson/api_doc.mustache @@ -21,43 +21,52 @@ Method | HTTP request | Description ### Example ```java -// Import classes:{{#hasAuthMethods}} -//import {{{invokerPackage}}}.ApiClient;{{/hasAuthMethods}} -//import {{{invokerPackage}}}.ApiException;{{#hasAuthMethods}} -//import {{{invokerPackage}}}.Configuration; -//import {{{invokerPackage}}}.auth.*;{{/hasAuthMethods}} -//import {{{package}}}.{{{classname}}}; - -{{#hasAuthMethods}} -ApiClient defaultClient = Configuration.getDefaultApiClient(); -{{#authMethods}}{{#isBasic}} -// Configure HTTP basic authorization: {{{name}}} -HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); -{{{name}}}.setUsername("YOUR USERNAME"); -{{{name}}}.setPassword("YOUR PASSWORD");{{/isBasic}}{{#isApiKey}} -// Configure API key authorization: {{{name}}} -ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); -{{{name}}}.setApiKey("YOUR API KEY"); -// Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null) -//{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} -// Configure OAuth2 access token for authorization: {{{name}}} -OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); -{{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}} -{{/authMethods}} -{{/hasAuthMethods}} - -{{{classname}}} apiInstance = new {{{classname}}}(); -{{#allParams}} -{{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} -{{/allParams}} -try { - {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}{{^vendorExtensions.x-group-parameters}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}({{#requiredParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}){{#optionalParams}} +// Import classes: +import {{{invokerPackage}}}.ApiClient; +import {{{invokerPackage}}}.ApiException; +import {{{invokerPackage}}}.Configuration;{{#hasAuthMethods}} +import {{{invokerPackage}}}.auth.*;{{/hasAuthMethods}} +import {{{invokerPackage}}}.models.*; +import {{{package}}}.{{{classname}}}; + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("{{{basePath}}}"); + {{#hasAuthMethods}} + {{#authMethods}}{{#isBasic}} + // Configure HTTP basic authorization: {{{name}}} + HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setUsername("YOUR USERNAME"); + {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasic}}{{#isApiKey}} + // Configure API key authorization: {{{name}}} + ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setApiKey("YOUR API KEY"); + // Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null) + //{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} + // Configure OAuth2 access token for authorization: {{{name}}} + OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}} + {{/authMethods}} + {{/hasAuthMethods}} + + {{{classname}}} apiInstance = new {{{classname}}}(defaultClient); + {{#allParams}} + {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} + {{/allParams}} + try { + {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}{{^vendorExtensions.x-group-parameters}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}({{#requiredParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}){{#optionalParams}} .{{{paramName}}}({{{paramName}}}){{/optionalParams}} .execute();{{/vendorExtensions.x-group-parameters}}{{#returnType}} - System.out.println(result);{{/returnType}} -} catch (ApiException e) { - System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); - e.printStackTrace(); + System.out.println(result);{{/returnType}} + } catch (ApiException e) { + System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } } ``` From 3480be1c828e621412acd6f5b3a84a4a1908d2b3 Mon Sep 17 00:00:00 2001 From: Sai Giridhar P Date: Mon, 3 Jun 2019 13:07:55 +0530 Subject: [PATCH 114/370] fix(java-jersey2): Fixing javadocs warnings (#3040) * edit fix(java-jersey2): Fixing javadocs warnings * fix(java-jersey): Updating pet project --- libraries/jersey2/ApiClient.mustache | 2 ++ libraries/jersey2/api.mustache | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 9b19457b04c..1007a857ca0 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -808,6 +808,8 @@ public class ApiClient { * Update query and header parameters based on authentication settings. * * @param authNames The authentications to apply + * @param queryParams List of query parameters + * @param headerParams Map of header parameters */ protected void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams) { for (String authName : authNames) { diff --git a/libraries/jersey2/api.mustache b/libraries/jersey2/api.mustache index a275689bba5..9c218e35bfa 100644 --- a/libraries/jersey2/api.mustache +++ b/libraries/jersey2/api.mustache @@ -75,9 +75,7 @@ public class {{classname}} { {{#allParams}} * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} - {{#returnType}} * @return ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> - {{/returnType}} * @throws ApiException if fails to make API call {{#isDeprecated}} * @deprecated From ea78b891776c0a3b96a1a1d07f3c9748f615c405 Mon Sep 17 00:00:00 2001 From: Sai Giridhar P Date: Mon, 3 Jun 2019 13:10:22 +0530 Subject: [PATCH 115/370] feat(java-okhttpgson): Making API response headers case insensitive (#3029) * feat(java-okhttpgson): Making API response headers case insensitive * feat(java-okhttpgson): Adding documentation * feat(java-okhttpgson): Removing tabs * feat(java-okhttpgson): Removing tabs --- libraries/okhttp-gson/ApiResponse.mustache | 12 ++- libraries/okhttp-gson/apiException.mustache | 96 +++++++++++++++++++++ 2 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 libraries/okhttp-gson/apiException.mustache diff --git a/libraries/okhttp-gson/ApiResponse.mustache b/libraries/okhttp-gson/ApiResponse.mustache index 3909393697c..1f3f3a31981 100644 --- a/libraries/okhttp-gson/ApiResponse.mustache +++ b/libraries/okhttp-gson/ApiResponse.mustache @@ -4,6 +4,10 @@ package {{invokerPackage}}; import java.util.List; import java.util.Map; +{{#caseInsensitiveResponseHeaders}} +import java.util.Map.Entry; +import java.util.TreeMap; +{{/caseInsensitiveResponseHeaders}} /** * API response returned by API call. @@ -30,7 +34,13 @@ public class ApiResponse { */ public ApiResponse(int statusCode, Map> headers, T data) { this.statusCode = statusCode; - this.headers = headers; + {{#caseInsensitiveResponseHeaders}} + Map> responseHeaders = new TreeMap>(String.CASE_INSENSITIVE_ORDER); + for(Entry> entry : headers.entrySet()){ + responseHeaders.put(entry.getKey().toLowerCase(), entry.getValue()); + } + {{/caseInsensitiveResponseHeaders}} + this.headers = {{#caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}; this.data = data; } diff --git a/libraries/okhttp-gson/apiException.mustache b/libraries/okhttp-gson/apiException.mustache new file mode 100644 index 00000000000..e8952456591 --- /dev/null +++ b/libraries/okhttp-gson/apiException.mustache @@ -0,0 +1,96 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import java.util.Map; +import java.util.List; +{{#caseInsensitiveResponseHeaders}} +import java.util.Map.Entry; +import java.util.TreeMap; +{{/caseInsensitiveResponseHeaders}} + +{{>generatedAnnotation}} +public class ApiException extends{{#useRuntimeException}} RuntimeException {{/useRuntimeException}}{{^useRuntimeException}} Exception {{/useRuntimeException}}{ + private int code = 0; + private Map> responseHeaders = null; + private String responseBody = null; + + public ApiException() {} + + public ApiException(Throwable throwable) { + super(throwable); + } + + public ApiException(String message) { + super(message); + } + + public ApiException(String message, Throwable throwable, int code, Map> responseHeaders, String responseBody) { + super(message, throwable); + this.code = code; + {{#caseInsensitiveResponseHeaders}} + Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER); + for(Entry> entry : responseHeaders.entrySet()){ + headers.put(entry.getKey().toLowerCase(), entry.getValue()); + } + {{/caseInsensitiveResponseHeaders}} + this.responseHeaders = {{#caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}; + this.responseBody = responseBody; + } + + public ApiException(String message, int code, Map> responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(String message, Throwable throwable, int code, Map> responseHeaders) { + this(message, throwable, code, responseHeaders, null); + } + + public ApiException(int code, Map> responseHeaders, String responseBody) { + this((String) null, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(int code, String message) { + super(message); + this.code = code; + } + + public ApiException(int code, String message, Map> responseHeaders, String responseBody) { + this(code, message); + {{#caseInsensitiveResponseHeaders}} + Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER); + for(Entry> entry : responseHeaders.entrySet()){ + headers.put(entry.getKey().toLowerCase(), entry.getValue()); + } + {{/caseInsensitiveResponseHeaders}} + this.responseHeaders = {{#caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}; + this.responseBody = responseBody; + } + + /** + * Get the HTTP status code. + * + * @return HTTP status code + */ + public int getCode() { + return code; + } + + /** + * Get the HTTP response headers. + * + * @return A map of list of string + */ + public Map> getResponseHeaders() { + return responseHeaders; + } + + /** + * Get the HTTP response body. + * + * @return Response body in the form of string + */ + public String getResponseBody() { + return responseBody; + } +} From dfb995eaa109f6e1470b3fb7989af86607e0b17d Mon Sep 17 00:00:00 2001 From: Sai Giridhar P Date: Mon, 3 Jun 2019 13:12:41 +0530 Subject: [PATCH 116/370] [Java][jersey2]: Documentation changes and making example snippet compilable (#3056) * feat(java-jersey2): Adding http response headers and making example compilable * feat(java-jersey2): Updating pet project * feat(java-jersey2): Removing uncessary lines from Readme * feat(java-jersey2): Updating pet projects * feat(java-jersey2): Updating pet projects --- README.mustache | 13 ++--- api_doc.mustache | 88 ++++++++++++++++++++-------------- libraries/jersey2/api.mustache | 18 +++++++ libraries/jersey2/pom.mustache | 9 ++++ 4 files changed, 87 insertions(+), 41 deletions(-) diff --git a/README.mustache b/README.mustache index 1a487fc280a..ff0026651fe 100644 --- a/README.mustache +++ b/README.mustache @@ -84,14 +84,12 @@ import {{{invokerPackage}}}.auth.*; import {{{modelPackage}}}.*; import {{{package}}}.{{{classname}}}; -import java.io.File; -import java.util.*; - public class {{{classname}}}Example { public static void main(String[] args) { - {{#hasAuthMethods}}ApiClient defaultClient = Configuration.getDefaultApiClient(); - {{#authMethods}}{{#isBasic}} + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("{{{basePath}}}"); + {{#hasAuthMethods}}{{#authMethods}}{{#isBasic}} // Configure HTTP basic authorization: {{{name}}} HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); {{{name}}}.setUsername("YOUR USERNAME"); @@ -107,7 +105,7 @@ public class {{{classname}}}Example { {{/authMethods}} {{/hasAuthMethods}} - {{{classname}}} apiInstance = new {{{classname}}}(); + {{{classname}}} apiInstance = new {{{classname}}}(defaultClient); {{#allParams}} {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} {{/allParams}} @@ -116,6 +114,9 @@ public class {{{classname}}}Example { System.out.println(result);{{/returnType}} } catch (ApiException e) { System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); e.printStackTrace(); } } diff --git a/api_doc.mustache b/api_doc.mustache index bffe140b315..3a9d2886266 100644 --- a/api_doc.mustache +++ b/api_doc.mustache @@ -23,41 +23,50 @@ Method | HTTP request | Description ### Example ```java -// Import classes:{{#hasAuthMethods}} -//import {{{invokerPackage}}}.ApiClient;{{/hasAuthMethods}} -//import {{{invokerPackage}}}.ApiException;{{#hasAuthMethods}} -//import {{{invokerPackage}}}.Configuration; -//import {{{invokerPackage}}}.auth.*;{{/hasAuthMethods}} -//import {{{package}}}.{{{classname}}}; - -{{#hasAuthMethods}} -ApiClient defaultClient = Configuration.getDefaultApiClient(); -{{#authMethods}}{{#isBasic}} -// Configure HTTP basic authorization: {{{name}}} -HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); -{{{name}}}.setUsername("YOUR USERNAME"); -{{{name}}}.setPassword("YOUR PASSWORD");{{/isBasic}}{{#isApiKey}} -// Configure API key authorization: {{{name}}} -ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); -{{{name}}}.setApiKey("YOUR API KEY"); -// Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null) -//{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} -// Configure OAuth2 access token for authorization: {{{name}}} -OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); -{{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}} -{{/authMethods}} -{{/hasAuthMethods}} - -{{{classname}}} apiInstance = new {{{classname}}}(); -{{#allParams}} -{{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} -{{/allParams}} -try { - {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} - System.out.println(result);{{/returnType}} -} catch (ApiException e) { - System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); - e.printStackTrace(); +// Import classes: +import {{{invokerPackage}}}.ApiClient; +import {{{invokerPackage}}}.ApiException; +import {{{invokerPackage}}}.Configuration;{{#hasAuthMethods}} +import {{{invokerPackage}}}.auth.*;{{/hasAuthMethods}} +import {{{invokerPackage}}}.models.*; +import {{{package}}}.{{{classname}}}; + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("{{{basePath}}}"); + {{#hasAuthMethods}} + {{#authMethods}}{{#isBasic}} + // Configure HTTP basic authorization: {{{name}}} + HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setUsername("YOUR USERNAME"); + {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasic}}{{#isApiKey}} + // Configure API key authorization: {{{name}}} + ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setApiKey("YOUR API KEY"); + // Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null) + //{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} + // Configure OAuth2 access token for authorization: {{{name}}} + OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}} + {{/authMethods}} + {{/hasAuthMethods}} + + {{{classname}}} apiInstance = new {{{classname}}}(defaultClient); + {{#allParams}} + {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} + {{/allParams}} + try { + {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + System.out.println(result);{{/returnType}} + } catch (ApiException e) { + System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } } ``` @@ -82,5 +91,14 @@ Name | Type | Description | Notes - **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} - **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} +{{#responses.0}} +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +{{#responses}} +| **{{code}}** | {{message}} | {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}} | +{{/responses}} +{{/responses.0}} + {{/operation}} {{/operations}} diff --git a/libraries/jersey2/api.mustache b/libraries/jersey2/api.mustache index 9c218e35bfa..19c079e3229 100644 --- a/libraries/jersey2/api.mustache +++ b/libraries/jersey2/api.mustache @@ -50,6 +50,15 @@ public class {{classname}} { * @return {{returnType}} {{/returnType}} * @throws ApiException if fails to make API call + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} {{#isDeprecated}} * @deprecated {{/isDeprecated}} @@ -77,6 +86,15 @@ public class {{classname}} { {{/allParams}} * @return ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> * @throws ApiException if fails to make API call + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} {{#isDeprecated}} * @deprecated {{/isDeprecated}} diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 3c0af2dac5f..0d60744b9e0 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -170,6 +170,15 @@ jar + + + + http.response.details + a + Http Response Details: + + + From 0ccbfa6a95f184dbca6b82e109ed20bb34a5a9af Mon Sep 17 00:00:00 2001 From: Sai Giridhar P Date: Tue, 4 Jun 2019 19:33:01 +0530 Subject: [PATCH 117/370] feat(java-jersey2): Making response headers case-insensitive (#3072) * feat(java-jersey2): Making headers case-insensitive * feat(java-jersey2): Updating documentation --- libraries/jersey2/ApiResponse.mustache | 12 +++- libraries/jersey2/apiException.mustache | 96 +++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 libraries/jersey2/apiException.mustache diff --git a/libraries/jersey2/ApiResponse.mustache b/libraries/jersey2/ApiResponse.mustache index 2f01685a0af..a67b11f054c 100644 --- a/libraries/jersey2/ApiResponse.mustache +++ b/libraries/jersey2/ApiResponse.mustache @@ -4,6 +4,10 @@ package {{invokerPackage}}; import java.util.List; import java.util.Map; +{{#caseInsensitiveResponseHeaders}} +import java.util.Map.Entry; +import java.util.TreeMap; +{{/caseInsensitiveResponseHeaders}} /** * API response returned by API call. @@ -30,7 +34,13 @@ public class ApiResponse { */ public ApiResponse(int statusCode, Map> headers, T data) { this.statusCode = statusCode; - this.headers = headers; + {{#caseInsensitiveResponseHeaders}} + Map> responseHeaders = new TreeMap>(String.CASE_INSENSITIVE_ORDER); + for(Entry> entry : headers.entrySet()){ + responseHeaders.put(entry.getKey().toLowerCase(), entry.getValue()); + } + {{/caseInsensitiveResponseHeaders}} + this.headers = {{#caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}; this.data = data; } diff --git a/libraries/jersey2/apiException.mustache b/libraries/jersey2/apiException.mustache new file mode 100644 index 00000000000..e8952456591 --- /dev/null +++ b/libraries/jersey2/apiException.mustache @@ -0,0 +1,96 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import java.util.Map; +import java.util.List; +{{#caseInsensitiveResponseHeaders}} +import java.util.Map.Entry; +import java.util.TreeMap; +{{/caseInsensitiveResponseHeaders}} + +{{>generatedAnnotation}} +public class ApiException extends{{#useRuntimeException}} RuntimeException {{/useRuntimeException}}{{^useRuntimeException}} Exception {{/useRuntimeException}}{ + private int code = 0; + private Map> responseHeaders = null; + private String responseBody = null; + + public ApiException() {} + + public ApiException(Throwable throwable) { + super(throwable); + } + + public ApiException(String message) { + super(message); + } + + public ApiException(String message, Throwable throwable, int code, Map> responseHeaders, String responseBody) { + super(message, throwable); + this.code = code; + {{#caseInsensitiveResponseHeaders}} + Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER); + for(Entry> entry : responseHeaders.entrySet()){ + headers.put(entry.getKey().toLowerCase(), entry.getValue()); + } + {{/caseInsensitiveResponseHeaders}} + this.responseHeaders = {{#caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}; + this.responseBody = responseBody; + } + + public ApiException(String message, int code, Map> responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(String message, Throwable throwable, int code, Map> responseHeaders) { + this(message, throwable, code, responseHeaders, null); + } + + public ApiException(int code, Map> responseHeaders, String responseBody) { + this((String) null, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(int code, String message) { + super(message); + this.code = code; + } + + public ApiException(int code, String message, Map> responseHeaders, String responseBody) { + this(code, message); + {{#caseInsensitiveResponseHeaders}} + Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER); + for(Entry> entry : responseHeaders.entrySet()){ + headers.put(entry.getKey().toLowerCase(), entry.getValue()); + } + {{/caseInsensitiveResponseHeaders}} + this.responseHeaders = {{#caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}; + this.responseBody = responseBody; + } + + /** + * Get the HTTP status code. + * + * @return HTTP status code + */ + public int getCode() { + return code; + } + + /** + * Get the HTTP response headers. + * + * @return A map of list of string + */ + public Map> getResponseHeaders() { + return responseHeaders; + } + + /** + * Get the HTTP response body. + * + * @return Response body in the form of string + */ + public String getResponseBody() { + return responseBody; + } +} From b9a72b64dcf31a732f9828a940179fd737c485d0 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Thu, 6 Jun 2019 13:32:58 +0800 Subject: [PATCH 118/370] [Java][okhttp-gson] Update dependencies (#3103) * update java client depedency to the latest version * update java samples --- libraries/okhttp-gson/build.gradle.mustache | 8 ++++---- libraries/okhttp-gson/build.sbt.mustache | 8 ++++---- libraries/okhttp-gson/pom.mustache | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libraries/okhttp-gson/build.gradle.mustache b/libraries/okhttp-gson/build.gradle.mustache index 613c81a48be..cb0e972ae37 100644 --- a/libraries/okhttp-gson/build.gradle.mustache +++ b/libraries/okhttp-gson/build.gradle.mustache @@ -126,15 +126,15 @@ if(hasProperty('target') && target == 'android') { } dependencies { - compile 'io.swagger:swagger-annotations:1.5.21' - compile 'com.squareup.okhttp3:okhttp:3.13.1' - compile 'com.squareup.okhttp3:logging-interceptor:3.13.1' + compile 'io.swagger:swagger-annotations:1.5.22' + compile 'com.squareup.okhttp3:okhttp:3.14.2' + compile 'com.squareup.okhttp3:logging-interceptor:3.14.2' compile 'com.google.code.gson:gson:2.8.5' compile 'io.gsonfire:gson-fire:1.8.3' {{#hasOAuthMethods}} compile group: 'org.apache.oltu.oauth2', name: 'org.apache.oltu.oauth2.client', version: '1.0.1' {{/hasOAuthMethods}} - compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.8.1' + compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.9' {{#joda}} compile 'joda-time:joda-time:2.9.9' {{/joda}} diff --git a/libraries/okhttp-gson/build.sbt.mustache b/libraries/okhttp-gson/build.sbt.mustache index f83f149e920..80a53397e3a 100644 --- a/libraries/okhttp-gson/build.sbt.mustache +++ b/libraries/okhttp-gson/build.sbt.mustache @@ -9,11 +9,11 @@ lazy val root = (project in file(".")). publishArtifact in (Compile, packageDoc) := false, resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( - "io.swagger" % "swagger-annotations" % "1.5.21", - "com.squareup.okhttp3" % "okhttp" % "3.13.1", - "com.squareup.okhttp3" % "logging-interceptor" % "3.13.1", + "io.swagger" % "swagger-annotations" % "1.5.22", + "com.squareup.okhttp3" % "okhttp" % "3.14.2", + "com.squareup.okhttp3" % "logging-interceptor" % "3.14.2", "com.google.code.gson" % "gson" % "2.8.5", - "org.apache.commons" % "commons-lang3" % "3.8.1", + "org.apache.commons" % "commons-lang3" % "3.9", {{#hasOAuthMethods}} "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1", {{/hasOAuthMethods}} diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index eac0a4e1ba2..84b97f52c77 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -298,9 +298,9 @@ ${java.version} 1.8.3 1.5.21 - 3.14.0 + 3.14.2 2.8.5 - 3.8.1 + 3.9 {{#joda}} 2.9.9 {{/joda}} From c5dcebe2400c4ca8a5ff638c8fd1d2928d9f7811 Mon Sep 17 00:00:00 2001 From: Sai Giridhar P Date: Mon, 24 Jun 2019 09:03:57 +0530 Subject: [PATCH 119/370] [java][jesery2]: "InjectionManagerFactory not found" issue (#3153) * feat(java-jersey2): Fixing InjectionManagerFactory issue * feat(java-jersey2): Update pet project --- libraries/jersey2/pom.mustache | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 0d60744b9e0..d8b553a434a 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -235,6 +235,13 @@ jersey-client ${jersey-version}
+ {{^supportJava6}} + + org.glassfish.jersey.inject + jersey-hk2 + ${jersey-version} + + {{/supportJava6}} org.glassfish.jersey.media jersey-media-multipart From ae1ed6f47ec6ce421dc6f40cf7fae414869421c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Fri, 28 Jun 2019 11:55:51 +0200 Subject: [PATCH 120/370] [java-client][okhttp-gson] support bearer authentication (#3236) --- libraries/okhttp-gson/ApiClient.mustache | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index 3c4559359c3..a5617334a8e 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -88,8 +88,9 @@ public class ApiClient { public ApiClient() { init(); - // Setup authentications (key: authentication name, value: authentication).{{#authMethods}}{{#isBasic}} - authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + // Setup authentications (key: authentication name, value: authentication).{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} // Prevent the authentications from being modified. From fb74463d355fb3cc996b5b1bbeb23bcdd28fa491 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 5 Jul 2019 23:32:10 +0800 Subject: [PATCH 121/370] update travis, support java9+ (#3279) --- libraries/okhttp-gson/build.sbt.mustache | 1 + libraries/okhttp-gson/pom.mustache | 8 +++++++- travis.mustache | 19 ++++++++++++------- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/libraries/okhttp-gson/build.sbt.mustache b/libraries/okhttp-gson/build.sbt.mustache index 80a53397e3a..e1c68a17514 100644 --- a/libraries/okhttp-gson/build.sbt.mustache +++ b/libraries/okhttp-gson/build.sbt.mustache @@ -24,6 +24,7 @@ lazy val root = (project in file(".")). "org.threeten" % "threetenbp" % "1.3.5" % "compile", {{/threetenbp}} "io.gsonfire" % "gson-fire" % "1.8.3" % "compile", + "javax.annotation" % "jsr250-api" % "1.0" % "compile", "junit" % "junit" % "4.12" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index 84b97f52c77..6ac73ccff69 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -284,6 +284,11 @@ provided {{/parcelableModel}} + + javax.annotation + jsr250-api + ${javax-annotation-version} + junit @@ -297,7 +302,7 @@ ${java.version} ${java.version} 1.8.3 - 1.5.21 + 1.5.22 3.14.2 2.8.5 3.9 @@ -308,6 +313,7 @@ 1.3.8 {{/threetenbp}} 1.0.0 + 1.0 4.12 UTF-8 diff --git a/travis.mustache b/travis.mustache index 80a7f2fc66c..e3bdf2af1be 100644 --- a/travis.mustache +++ b/travis.mustache @@ -1,17 +1,22 @@ # -# Generated by: https://openapi-generator.tech +# Generated by OpenAPI Generator: https://openapi-generator.tech +# +# Ref: https://docs.travis-ci.com/user/languages/java/ # language: java jdk: - - oraclejdk8 - - oraclejdk7 + - openjdk12 + - openjdk11 + - openjdk10 + - openjdk9 + - openjdk8 before_install: # ensure gradlew has proper permission - chmod a+x ./gradlew script: # test using maven - - mvn test - # uncomment below to test using gradle - # - gradle test - # uncomment below to test using sbt + #- mvn test + # test using gradle + - gradle test + # test using sbt # - sbt test From cb22732c6170e536cef3598fb7551dc931e98620 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Mon, 8 Jul 2019 15:25:47 +0200 Subject: [PATCH 122/370] [java] fix javadoc configuration (#3302) * [java] fix javadoc configuration * [java-pkmst-microservice] fix generated javadoc --- libraries/jersey2/build.gradle.mustache | 4 ++++ libraries/jersey2/pom.mustache | 18 +++++++++--------- libraries/okhttp-gson/build.gradle.mustache | 4 ++++ libraries/okhttp-gson/pom.mustache | 18 +++++++++--------- 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index 6ca2e18a7cd..08462012dd6 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -161,3 +161,7 @@ dependencies { {{/java8}} testCompile "junit:junit:$junit_version" } + +javadoc { + options.tags = [ "http.response.details:a:Http Response Details" ] +} diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index d8b553a434a..a6b6d039f80 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -170,17 +170,17 @@ jar - - - - http.response.details - a - Http Response Details: - - - + + + + http.response.details + a + Http Response Details: + + + org.apache.maven.plugins diff --git a/libraries/okhttp-gson/build.gradle.mustache b/libraries/okhttp-gson/build.gradle.mustache index cb0e972ae37..f255d0123c8 100644 --- a/libraries/okhttp-gson/build.gradle.mustache +++ b/libraries/okhttp-gson/build.gradle.mustache @@ -143,3 +143,7 @@ dependencies { {{/threetenbp}} testCompile 'junit:junit:4.12' } + +javadoc { + options.tags = [ "http.response.details:a:Http Response Details" ] +} diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index 6ac73ccff69..7aa9c2c8a84 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -149,17 +149,17 @@ jar - - - - http.response.details - a - Http Response Details: - - - + + + + http.response.details + a + Http Response Details: + + + org.apache.maven.plugins From 2e92f9dcf0af701e7cc85a5e4d4a826841f4fb66 Mon Sep 17 00:00:00 2001 From: Victor Orlovsky Date: Mon, 8 Jul 2019 17:20:35 +0300 Subject: [PATCH 123/370] [Java][Rest-assured] Bump rest-assured version (#3282) * Update rest-assured version to 4.0.0 * Added rest-assured version 4.0.0 to documentation * Remove CatAllOfTest and DogAllOfTest --- libraries/rest-assured/build.gradle.mustache | 2 +- libraries/rest-assured/build.sbt.mustache | 2 +- libraries/rest-assured/pom.mustache | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/rest-assured/build.gradle.mustache b/libraries/rest-assured/build.gradle.mustache index 03ea659d066..285f42e475f 100644 --- a/libraries/rest-assured/build.gradle.mustache +++ b/libraries/rest-assured/build.gradle.mustache @@ -96,7 +96,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.21" - rest_assured_version = "3.3.0" + rest_assured_version = "4.0.0" junit_version = "4.12" gson_version = "2.8.5" gson_fire_version = "1.8.3" diff --git a/libraries/rest-assured/build.sbt.mustache b/libraries/rest-assured/build.sbt.mustache index 454ff06c346..d8d817271cb 100644 --- a/libraries/rest-assured/build.sbt.mustache +++ b/libraries/rest-assured/build.sbt.mustache @@ -10,7 +10,7 @@ lazy val root = (project in file(".")). resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( "io.swagger" % "swagger-annotations" % "1.5.21", - "io.rest-assured" % "scala-support" % "3.3.0", + "io.rest-assured" % "scala-support" % "4.0.0", "com.google.code.gson" % "gson" % "2.8.5", "io.gsonfire" % "gson-fire" % "1.8.3" % "compile", {{#joda}} diff --git a/libraries/rest-assured/pom.mustache b/libraries/rest-assured/pom.mustache index d480939b403..5aa3ab7c617 100644 --- a/libraries/rest-assured/pom.mustache +++ b/libraries/rest-assured/pom.mustache @@ -251,7 +251,7 @@ UTF-8 1.5.21 - 3.3.0 + 4.0.0 2.8.5 1.8.3 1.0.0 From 6a85e5421d04710aea2664a20aa46dc3e34fb176 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Fri, 12 Jul 2019 06:55:23 +0200 Subject: [PATCH 124/370] [java-client][okhttp-gson] add missing import for bearer authentication (#3343) --- libraries/okhttp-gson/ApiClient.mustache | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index a5617334a8e..cd173326c10 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -52,6 +52,7 @@ import java.util.regex.Pattern; import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.HttpBearerAuth; import {{invokerPackage}}.auth.ApiKeyAuth; {{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; From 3c3ecadb4ccb9e64f4a4e32e0beda80168c10813 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Thu, 18 Jul 2019 07:46:44 +0200 Subject: [PATCH 125/370] [java rest-assured] prevent reqSpec reuse between requests (#3375) * [java rest-assured] prevent reqSpec reuse between requests * Update sample --- libraries/rest-assured/ApiClient.mustache | 6 +-- libraries/rest-assured/api.mustache | 45 ++++++++++++++--------- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/libraries/rest-assured/ApiClient.mustache b/libraries/rest-assured/ApiClient.mustache index 42bdf68613b..19ab0fa98c3 100644 --- a/libraries/rest-assured/ApiClient.mustache +++ b/libraries/rest-assured/ApiClient.mustache @@ -34,13 +34,13 @@ public class ApiClient { {{#apiInfo}} {{#apis}} public {{classname}} {{classVarName}}() { - return {{classname}}.{{classVarName}}(config.baseReqSpec.get()); + return {{classname}}.{{classVarName}}(config.reqSpecSupplier); } {{/apis}} {{/apiInfo}} public static class Config { - private Supplier baseReqSpec = () -> new RequestSpecBuilder() + private Supplier reqSpecSupplier = () -> new RequestSpecBuilder() {{#basePath}}.setBaseUri(BASE_URI){{/basePath}} .setConfig(config().objectMapperConfig(objectMapperConfig().defaultObjectMapper(gson()))); @@ -50,7 +50,7 @@ public class ApiClient { * @return configuration */ public Config reqSpecSupplier(Supplier supplier) { - this.baseReqSpec = supplier; + this.reqSpecSupplier = supplier; return this; } diff --git a/libraries/rest-assured/api.mustache b/libraries/rest-assured/api.mustache index 75c3a373ae3..75ea07db60a 100644 --- a/libraries/rest-assured/api.mustache +++ b/libraries/rest-assured/api.mustache @@ -31,14 +31,23 @@ import static io.restassured.http.Method.*; @Api(value = "{{{baseName}}}") public class {{classname}} { - private RequestSpecBuilder reqSpec; + private Supplier reqSpecSupplier; + private Consumer reqSpecCustomizer; - private {{classname}}(RequestSpecBuilder reqSpec) { - this.reqSpec = reqSpec; + private {{classname}}(Supplier reqSpecSupplier) { + this.reqSpecSupplier = reqSpecSupplier; } - public static {{classname}} {{classVarName}}(RequestSpecBuilder reqSpec) { - return new {{classname}}(reqSpec); + public static {{classname}} {{classVarName}}(Supplier reqSpecSupplier) { + return new {{classname}}(reqSpecSupplier); + } + + private RequestSpecBuilder createReqSpec() { + RequestSpecBuilder reqSpec = reqSpecSupplier.get(); + if(reqSpecCustomizer != null) { + reqSpecCustomizer.accept(reqSpec); + } + return reqSpec; } {{#operations}} @@ -54,18 +63,18 @@ public class {{classname}} { @Deprecated {{/isDeprecated}} public {{operationIdCamelCase}}Oper {{operationId}}() { - return new {{operationIdCamelCase}}Oper(reqSpec); + return new {{operationIdCamelCase}}Oper(createReqSpec()); } {{/operation}} {{/operations}} /** - * Customise request specification - * @param consumer consumer + * Customize request specification + * @param reqSpecCustomizer consumer to modify the RequestSpecBuilder * @return api */ - public {{classname}} reqSpec(Consumer consumer) { - consumer.accept(reqSpec); + public {{classname}} reqSpec(Consumer reqSpecCustomizer) { + this.reqSpecCustomizer = reqSpecCustomizer; return this; } @@ -216,22 +225,22 @@ public class {{classname}} { {{/formParams}} /** - * Customise request specification - * @param consumer consumer + * Customize request specification + * @param reqSpecCustomizer consumer to modify the RequestSpecBuilder * @return operation */ - public {{operationIdCamelCase}}Oper reqSpec(Consumer consumer) { - consumer.accept(reqSpec); + public {{operationIdCamelCase}}Oper reqSpec(Consumer reqSpecCustomizer) { + reqSpecCustomizer.accept(reqSpec); return this; } /** - * Customise response specification - * @param consumer consumer + * Customize response specification + * @param respSpecCustomizer consumer to modify the ResponseSpecBuilder * @return operation */ - public {{operationIdCamelCase}}Oper respSpec(Consumer consumer) { - consumer.accept(respSpec); + public {{operationIdCamelCase}}Oper respSpec(Consumer respSpecCustomizer) { + respSpecCustomizer.accept(respSpec); return this; } } From e9e78994763ee853bd7f7cfeed4a94b9eda777d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Thu, 25 Jul 2019 04:32:50 +0200 Subject: [PATCH 126/370] [java] Support for number enum (#3328) * [java] Support for number enum * [core] add isLong, isNumber, isNumeric, isFloat, isDouble to CodegenModel * [java-gson] fix Enum TypeAdapter in BigDecimal case. --- modelEnum.mustache | 4 ++-- modelInnerEnum.mustache | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modelEnum.mustache b/modelEnum.mustache index e22a8e6ecee..f9136b1a201 100644 --- a/modelEnum.mustache +++ b/modelEnum.mustache @@ -65,8 +65,8 @@ public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum @Override public {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException { - {{{dataType}}} value = jsonReader.{{#isInteger}}nextInt(){{/isInteger}}{{^isInteger}}next{{{dataType}}}(){{/isInteger}}; - return {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue(value); + {{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{^isNumber}}{{^isInteger}}next{{{dataType}}}(){{/isInteger}}{{/isNumber}}; + return {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}}); } } {{/gson}} diff --git a/modelInnerEnum.mustache b/modelInnerEnum.mustache index 87c23108c11..ea0656c2ddf 100644 --- a/modelInnerEnum.mustache +++ b/modelInnerEnum.mustache @@ -56,8 +56,8 @@ @Override public {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException { - {{{dataType}}} value = jsonReader.{{#isInteger}}nextInt(){{/isInteger}}{{^isInteger}}next{{{dataType}}}(){{/isInteger}}; - return {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue(value); + {{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{^isNumber}}{{^isInteger}}next{{{dataType}}}(){{/isInteger}}{{/isNumber}}; + return {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}}); } } {{/gson}} From b5268b124dc63d75a38c56fac83a237ea7670ba5 Mon Sep 17 00:00:00 2001 From: kassim Date: Thu, 25 Jul 2019 04:35:18 +0200 Subject: [PATCH 127/370] [Java] add nullable annotation to pojo template for non-required fields (#3409) * add nullable annotation to pojo template * add jsr305 dependency * jsr305 dependency on all java build.gradle files * jsr305 dependency on all java pom.xml files * update samples * more pom updates * more sample/template updates --- build.gradle.mustache | 1 + libraries/feign/build.gradle.mustache | 1 + libraries/feign/pom.mustache | 7 +++++++ libraries/google-api-client/build.gradle.mustache | 1 + libraries/google-api-client/pom.mustache | 6 ++++++ libraries/jersey2/build.gradle.mustache | 1 + libraries/jersey2/pom.mustache | 7 +++++++ libraries/okhttp-gson/build.gradle.mustache | 1 + libraries/okhttp-gson/pom.mustache | 6 ++++++ libraries/rest-assured/build.gradle.mustache | 1 + libraries/rest-assured/pom.mustache | 6 ++++++ libraries/resteasy/build.gradle.mustache | 1 + libraries/resteasy/pom.mustache | 6 ++++++ libraries/resttemplate/build.gradle.mustache | 1 + libraries/resttemplate/pom.mustache | 7 +++++++ libraries/retrofit/build.gradle.mustache | 1 + libraries/retrofit/pom.mustache | 6 ++++++ libraries/retrofit2/build.gradle.mustache | 1 + libraries/retrofit2/pom.mustache | 6 ++++++ libraries/vertx/build.gradle.mustache | 1 + libraries/vertx/pom.mustache | 7 +++++++ libraries/webclient/pom.mustache | 7 +++++++ pojo.mustache | 1 + pom.mustache | 8 ++++++++ 24 files changed, 91 insertions(+) diff --git a/build.gradle.mustache b/build.gradle.mustache index 2e00ae91d1f..c65fb3cea28 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -145,6 +145,7 @@ ext { dependencies { compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "com.google.code.findbugs:jsr305:3.0.2" compile "com.sun.jersey:jersey-client:$jersey_version" compile "com.sun.jersey.contribs:jersey-multipart:$jersey_version" compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index 24e5e816cac..982faaa4628 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -133,6 +133,7 @@ ext { dependencies { compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "com.google.code.findbugs:jsr305:3.0.2" compile "io.github.openfeign:feign-core:$feign_version" compile "io.github.openfeign:feign-jackson:$feign_version" compile "io.github.openfeign:feign-slf4j:$feign_version" diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index 21954ad8ad4..d2634ca5df4 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -199,6 +199,13 @@ ${swagger-annotations-version} + + + com.google.code.findbugs + jsr305 + 3.0.2 + + io.github.openfeign diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache index f8d3ce9d785..84ae616aad6 100644 --- a/libraries/google-api-client/build.gradle.mustache +++ b/libraries/google-api-client/build.gradle.mustache @@ -133,6 +133,7 @@ ext { dependencies { compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "com.google.code.findbugs:jsr305:3.0.2" compile "com.google.api-client:google-api-client:${google_api_client_version}" compile "org.glassfish.jersey.core:jersey-common:${jersey_common_version}" compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index 35f0cafdf98..0269a88c3bc 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -219,6 +219,12 @@ swagger-annotations ${swagger-annotations-version} + + + com.google.code.findbugs + jsr305 + 3.0.2 + com.google.api-client diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index 08462012dd6..3f192edafd8 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -137,6 +137,7 @@ ext { dependencies { compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "com.google.code.findbugs:jsr305:3.0.2" compile "org.glassfish.jersey.core:jersey-client:$jersey_version" compile "org.glassfish.jersey.media:jersey-media-multipart:$jersey_version" compile "org.glassfish.jersey.media:jersey-media-json-jackson:$jersey_version" diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index a6b6d039f80..27a94b56311 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -229,6 +229,13 @@ ${swagger-annotations-version} + + + com.google.code.findbugs + jsr305 + 3.0.2 + + org.glassfish.jersey.core diff --git a/libraries/okhttp-gson/build.gradle.mustache b/libraries/okhttp-gson/build.gradle.mustache index f255d0123c8..d6ae8e31461 100644 --- a/libraries/okhttp-gson/build.gradle.mustache +++ b/libraries/okhttp-gson/build.gradle.mustache @@ -127,6 +127,7 @@ if(hasProperty('target') && target == 'android') { dependencies { compile 'io.swagger:swagger-annotations:1.5.22' + compile "com.google.code.findbugs:jsr305:3.0.2" compile 'com.squareup.okhttp3:okhttp:3.14.2' compile 'com.squareup.okhttp3:logging-interceptor:3.14.2' compile 'com.google.code.gson:gson:2.8.5' diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index 7aa9c2c8a84..759b9fe8249 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -207,6 +207,12 @@ swagger-annotations ${swagger-core-version} + + + com.google.code.findbugs + jsr305 + 3.0.2 + com.squareup.okhttp3 okhttp diff --git a/libraries/rest-assured/build.gradle.mustache b/libraries/rest-assured/build.gradle.mustache index 285f42e475f..b2d8683d3a4 100644 --- a/libraries/rest-assured/build.gradle.mustache +++ b/libraries/rest-assured/build.gradle.mustache @@ -111,6 +111,7 @@ ext { dependencies { compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "com.google.code.findbugs:jsr305:3.0.2" compile "io.rest-assured:scala-support:$rest_assured_version" compile "io.gsonfire:gson-fire:$gson_fire_version" {{#joda}} diff --git a/libraries/rest-assured/pom.mustache b/libraries/rest-assured/pom.mustache index 5aa3ab7c617..f8a8b5a1c88 100644 --- a/libraries/rest-assured/pom.mustache +++ b/libraries/rest-assured/pom.mustache @@ -206,6 +206,12 @@ swagger-annotations ${swagger-annotations-version} + + + com.google.code.findbugs + jsr305 + 3.0.2 + io.rest-assured rest-assured diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index 16da888f26a..4232b110be4 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -135,6 +135,7 @@ ext { dependencies { compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "com.google.code.findbugs:jsr305:3.0.2" compile "org.jboss.resteasy:resteasy-client:$resteasy_version" compile "org.jboss.resteasy:resteasy-multipart-provider:$resteasy_version" compile "org.jboss.resteasy:resteasy-jackson2-provider:$resteasy_version" diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index 48b52419739..7d6927871f1 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -179,6 +179,12 @@ swagger-annotations ${swagger-annotations-version} + + + com.google.code.findbugs + jsr305 + 3.0.2 + org.jboss.resteasy diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index eae0fa4e4aa..a3a9716286a 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -132,6 +132,7 @@ ext { dependencies { compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "com.google.code.findbugs:jsr305:3.0.2" compile "org.springframework:spring-web:$spring_web_version" compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache index 39a4a7c8d8d..77d021644d6 100644 --- a/libraries/resttemplate/pom.mustache +++ b/libraries/resttemplate/pom.mustache @@ -219,6 +219,13 @@ swagger-annotations ${swagger-annotations-version} + + + + com.google.code.findbugs + jsr305 + 3.0.2 + diff --git a/libraries/retrofit/build.gradle.mustache b/libraries/retrofit/build.gradle.mustache index dc0acee3841..3927003a314 100644 --- a/libraries/retrofit/build.gradle.mustache +++ b/libraries/retrofit/build.gradle.mustache @@ -120,6 +120,7 @@ ext { dependencies { compile "com.squareup.okhttp:okhttp:$okhttp_version" + compile "com.google.code.findbugs:jsr305:3.0.2" compile "com.squareup.retrofit:retrofit:$retrofit_version" compile "io.swagger:swagger-annotations:$swagger_annotations_version" compile "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version" diff --git a/libraries/retrofit/pom.mustache b/libraries/retrofit/pom.mustache index c2a5eeced6f..5e91585eedc 100644 --- a/libraries/retrofit/pom.mustache +++ b/libraries/retrofit/pom.mustache @@ -219,6 +219,12 @@ swagger-annotations ${swagger-annotations-version} + + + com.google.code.findbugs + jsr305 + 3.0.2 + com.squareup.retrofit retrofit diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index 39574a5755f..41ba4811340 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -166,6 +166,7 @@ dependencies { compile "io.reactivex.rxjava2:rxjava:$rx_java_version" {{/useRxJava2}} compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "com.google.code.findbugs:jsr305:3.0.2" compile ("org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version"){ exclude group:'org.apache.oltu.oauth2' , module: 'org.apache.oltu.oauth2.common' } diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index 4653b6650a1..aef50309c1c 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -198,6 +198,12 @@ swagger-annotations ${swagger-annotations-version} + + + com.google.code.findbugs + jsr305 + 3.0.2 + com.squareup.retrofit2 converter-gson diff --git a/libraries/vertx/build.gradle.mustache b/libraries/vertx/build.gradle.mustache index 1e97c1e2599..cf71f237698 100644 --- a/libraries/vertx/build.gradle.mustache +++ b/libraries/vertx/build.gradle.mustache @@ -36,6 +36,7 @@ ext { dependencies { compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "com.google.code.findbugs:jsr305:3.0.2" compile "io.vertx:vertx-web-client:$vertx_version" compile "io.vertx:vertx-rx-java:$vertx_version" compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache index c3976600d94..db6ef66924b 100644 --- a/libraries/vertx/pom.mustache +++ b/libraries/vertx/pom.mustache @@ -208,6 +208,13 @@ ${swagger-annotations-version} + + + com.google.code.findbugs + jsr305 + 3.0.2 + + io.vertx diff --git a/libraries/webclient/pom.mustache b/libraries/webclient/pom.mustache index 8919c3d481a..44098edb0f3 100644 --- a/libraries/webclient/pom.mustache +++ b/libraries/webclient/pom.mustache @@ -72,6 +72,13 @@ swagger-annotations ${swagger-annotations-version} + + + + com.google.code.findbugs + jsr305 + 3.0.2 + io.projectreactor diff --git a/pojo.mustache b/pojo.mustache index e021bf24b2d..276de9b66ee 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -129,6 +129,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela {{/maximum}} * @return {{name}} **/ +{{^required}} @javax.annotation.Nullable {{/required}} {{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} @ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") {{#vendorExtensions.extraAnnotation}} {{{vendorExtensions.extraAnnotation}}} diff --git a/pom.mustache b/pom.mustache index ed6e39c78ea..7dde4b12d9e 100644 --- a/pom.mustache +++ b/pom.mustache @@ -220,6 +220,14 @@ ${swagger-annotations-version} + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + com.sun.jersey From 26f6e821fb322d117767762e0afaa8b455725f68 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 26 Jul 2019 09:49:44 +0800 Subject: [PATCH 128/370] [Java] Replace "useNullForUnknownEnumValue" option with the nullable attribute (#3455) * add nullable support to enum * update test spec with nullable enum * update samples * update samples --- modelEnum.mustache | 2 +- modelInnerEnum.mustache | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modelEnum.mustache b/modelEnum.mustache index f9136b1a201..9428bc70f99 100644 --- a/modelEnum.mustache +++ b/modelEnum.mustache @@ -53,7 +53,7 @@ public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum return b; } } - {{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + value + "'");{{/useNullForUnknownEnumValue}} + {{#isNullable}}return null;{{/isNullable}}{{^isNullable}}throw new IllegalArgumentException("Unexpected value '" + value + "'");{{/isNullable}} } {{#gson}} diff --git a/modelInnerEnum.mustache b/modelInnerEnum.mustache index ea0656c2ddf..614e260c97f 100644 --- a/modelInnerEnum.mustache +++ b/modelInnerEnum.mustache @@ -44,7 +44,7 @@ return b; } } - {{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + value + "'");{{/useNullForUnknownEnumValue}} + {{#isNullable}}return null;{{/isNullable}}{{^isNullable}}throw new IllegalArgumentException("Unexpected value '" + value + "'");{{/isNullable}} } {{#gson}} From 4b0a62556241552365ce81b5ffc208835048c0f5 Mon Sep 17 00:00:00 2001 From: Benjamin Douglas Date: Thu, 25 Jul 2019 18:59:21 -0700 Subject: [PATCH 129/370] Java 11 native HTTP client library (#3434) * Initial commit of Java 11 native HTTP client port * Rebase to master and add JSR305 for @Nullable * Update samples with @Nullable annotations --- libraries/native/ApiClient.mustache | 306 ++++++++++++++++++ libraries/native/README.mustache | 161 +++++++++ libraries/native/api.mustache | 157 +++++++++ libraries/native/apiException.mustache | 79 +++++ libraries/native/build.gradle.mustache | 66 ++++ libraries/native/gradle-wrapper.jar | Bin 0 -> 55616 bytes .../native/gradle-wrapper.properties.mustache | 5 + libraries/native/gradle.properties.mustache | 0 libraries/native/gradlew.bat.mustache | 100 ++++++ libraries/native/gradlew.mustache | 188 +++++++++++ libraries/native/pom.mustache | 215 ++++++++++++ libraries/native/travis.mustache | 16 + 12 files changed, 1293 insertions(+) create mode 100644 libraries/native/ApiClient.mustache create mode 100644 libraries/native/README.mustache create mode 100644 libraries/native/api.mustache create mode 100644 libraries/native/apiException.mustache create mode 100644 libraries/native/build.gradle.mustache create mode 100644 libraries/native/gradle-wrapper.jar create mode 100644 libraries/native/gradle-wrapper.properties.mustache create mode 100644 libraries/native/gradle.properties.mustache create mode 100644 libraries/native/gradlew.bat.mustache create mode 100755 libraries/native/gradlew.mustache create mode 100644 libraries/native/pom.mustache create mode 100644 libraries/native/travis.mustache diff --git a/libraries/native/ApiClient.mustache b/libraries/native/ApiClient.mustache new file mode 100644 index 00000000000..eee8f2923d9 --- /dev/null +++ b/libraries/native/ApiClient.mustache @@ -0,0 +1,306 @@ +{{>licenseInfo}} +package {{invokerPackage}}; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; + +import java.net.URI; +import java.net.URLEncoder; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.nio.charset.Charset; +import java.time.Duration; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.StringJoiner; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +/** + * Configuration and utility class for API clients. + * + *

This class can be constructed and modified, then used to instantiate the + * various API classes. The API classes use the settings in this class to + * configure themselves, but otherwise do not store a link to this class.

+ * + *

This class is mutable and not synchronized, so it is not thread-safe. + * The API classes generated from this are immutable and thread-safe.

+ * + *

The setter methods of this class return the current object to facilitate + * a fluent style of configuration.

+ */ +{{>generatedAnnotation}} +public class ApiClient { + + private static final Charset UTF_8 = Charset.forName("UTF-8"); + + private HttpClient.Builder builder; + private ObjectMapper mapper; + private String scheme; + private String host; + private int port; + private String basePath; + private Consumer interceptor; + private Duration readTimeout; + + private static String valueToString(Object value) { + if (value == null) { + return ""; + } + return value.toString(); + } + + /** + * URL encode a string in the UTF-8 encoding. + * + * @param s String to encode. + * @return URL-encoded representation of the input string. + */ + public static String urlEncode(String s) { + return URLEncoder.encode(s, UTF_8); + } + + /** + * Convert a URL query name/value parameter to a list of encoded {@link Pair} + * objects. + * + *

The value can be null, in which case an empty list is returned.

+ * + * @param name The query name parameter. + * @param value The query value, which may not be a collection but may be + * null. + * @return A singleton list of the {@link Pair} objects representing the input + * parameters, which is encoded for use in a URL. If the value is null, an + * empty list is returned. + */ + public static List parameterToPairs(String name, Object value) { + if (name == null || name.isEmpty() || value == null) { + return Collections.emptyList(); + } + return Collections.singletonList(new Pair(urlEncode(name), urlEncode(value.toString()))); + } + + /** + * Convert a URL query name/collection parameter to a list of encoded + * {@link Pair} objects. + * + * @param collectionFormat The swagger collectionFormat string (csv, tsv, etc). + * @param name The query name parameter. + * @param values A collection of values for the given query name, which may be + * null. + * @return A list of {@link Pair} objects representing the input parameters, + * which is encoded for use in a URL. If the values collection is null, an + * empty list is returned. + */ + public static List parameterToPairs( + String collectionFormat, String name, Collection values) { + if (name == null || name.isEmpty() || values == null || values.isEmpty()) { + return Collections.emptyList(); + } + + // get the collection format (default: csv) + String format = collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat; + + // create the params based on the collection format + if ("multi".equals(format)) { + return values.stream() + .map(value -> new Pair(urlEncode(name), urlEncode(valueToString(value)))) + .collect(Collectors.toList()); + } + + String delimiter; + switch(format) { + case "csv": + delimiter = urlEncode(","); + break; + case "ssv": + delimiter = urlEncode(" "); + break; + case "tsv": + delimiter = urlEncode("\t"); + break; + case "pipes": + delimiter = urlEncode("|"); + break; + default: + throw new IllegalArgumentException("Illegal collection format: " + collectionFormat); + } + + StringJoiner joiner = new StringJoiner(delimiter); + for (Object value : values) { + joiner.add(urlEncode(valueToString(value))); + } + + return Collections.singletonList(new Pair(urlEncode(name), joiner.toString())); + } + + /** + * Ctor. + */ + public ApiClient() { + builder = HttpClient.newBuilder(); + mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.registerModule(new JavaTimeModule()); + URI baseURI = URI.create("{{{basePath}}}"); + scheme = baseURI.getScheme(); + host = baseURI.getHost(); + port = baseURI.getPort(); + basePath = baseURI.getRawPath(); + interceptor = null; + readTimeout = null; + } + + /** + * Set a custom {@link HttpClient.Builder} object to use when creating the + * {@link HttpClient} that is used by the API client. + * + * @param builder Custom client builder. + * @return This object. + */ + public ApiClient setHttpClientBuilder(HttpClient.Builder builder) { + this.builder = builder; + return this; + } + + /** + * Get an {@link HttpClient} based on the current {@link HttpClient.Builder}. + * + *

The returned object is immutable and thread-safe.

+ * + * @return The HTTP client. + */ + public HttpClient getHttpClient() { + return builder.build(); + } + + /** + * Set a custom {@link ObjectMapper} to serialize and deserialize the request + * and response bodies. + * + * @param mapper Custom object mapper. + * @return This object. + */ + public ApiClient setObjectMapper(ObjectMapper mapper) { + this.mapper = mapper; + return this; + } + + /** + * Get a copy of the current {@link ObjectMapper}. + * + * @return A copy of the current object mapper. + */ + public ObjectMapper getObjectMapper() { + return mapper.copy(); + } + + /** + * Set a custom host name for the target service. + * + * @param host The host name of the target service. + * @return This object. + */ + public ApiClient setHost(String host) { + this.host = host; + return this; + } + + /** + * Set a custom port number for the target service. + * + * @param port The port of the target service. Set this to -1 to reset the + * value to the default for the scheme. + * @return This object. + */ + public ApiClient setPort(int port) { + this.port = port; + return this; + } + + /** + * Set a custom base path for the target service, for example '/v2'. + * + * @param basePath The base path against which the rest of the path is + * resolved. + * @return This object. + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Get the base URI to resolve the endpoint paths against. + * + * @return The complete base URI that the rest of the API parameters are + * resolved against. + */ + public String getBaseUri() { + return scheme + "://" + host + (port == -1 ? "" : ":" + port) + basePath; + } + + /** + * Set a custom request interceptor. + * + *

A request interceptor is a mechanism for altering each request before it + * is sent. After the request has been fully configured but not yet built, the + * request builder is passed into this function for further modification, + * after which it is sent out.

+ * + *

This is useful for altering the requests in a custom manner, such as + * adding headers. It could also be used for logging and monitoring.

+ * + * @param interceptor A function invoked before creating each request. A value + * of null resets the interceptor to a no-op. + * @return This object. + */ + public ApiClient setRequestInterceptor(Consumer interceptor) { + this.interceptor = interceptor; + return this; + } + + /** + * Get the custom interceptor. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer getRequestInterceptor() { + return interceptor; + } + + /** + * Set the read timeout for the http client. + * + *

This is the value used by default for each request, though it can be + * overridden on a per-request basis with a request interceptor.

+ * + * @param readTimeout The read timeout used by default by the http client. + * Setting this value to null resets the timeout to an + * effectively infinite value. + * @return This object. + */ + public ApiClient setReadTimeout(Duration readTimeout) { + this.readTimeout = readTimeout; + return this; + } + + /** + * Get the read timeout that was set. + * + * @return The read timeout, or null if no timeout was set. Null represents + * an infinite wait time. + */ + public Duration getReadTimeout() { + return readTimeout; + } +} diff --git a/libraries/native/README.mustache b/libraries/native/README.mustache new file mode 100644 index 00000000000..44356cca82c --- /dev/null +++ b/libraries/native/README.mustache @@ -0,0 +1,161 @@ +# {{artifactId}} + +{{appName}} + +- API version: {{appVersion}} +{{^hideGenerationTimestamp}} + +- Build date: {{generatedDate}} +{{/hideGenerationTimestamp}} + +{{#appDescription}}{{{appDescription}}}{{/appDescription}} + +{{#infoUrl}} + For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) +{{/infoUrl}} + +*Automatically generated by the [OpenAPI Generator](https://openapi-generator.tech)* + +## Requirements + +Building the API client library requires: + +1. Java 11+ +2. Maven/Gradle + +## Installation + +To install the API client library to your local Maven repository, simply execute: + +```shell +mvn clean install +``` + +To deploy it to a remote Maven repository instead, configure the settings of the repository and execute: + +```shell +mvn clean deploy +``` + +Refer to the [OSSRH Guide](http://central.sonatype.org/pages/ossrh-guide.html) for more information. + +### Maven users + +Add this dependency to your project's POM: + +```xml + + {{{groupId}}} + {{{artifactId}}} + {{{artifactVersion}}} + compile + +``` + +### Gradle users + +Add this dependency to your project's build file: + +```groovy +compile "{{{groupId}}}:{{{artifactId}}}:{{{artifactVersion}}}" +``` + +### Others + +At first generate the JAR by executing: + +```shell +mvn clean package +``` + +Then manually install the following JARs: + +- `target/{{{artifactId}}}-{{{artifactVersion}}}.jar` +- `target/lib/*.jar` + +## Getting Started + +Please follow the [installation](#installation) instruction and execute the following Java code: + +```java +{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}} +import {{{invokerPackage}}}.*; +import {{{modelPackage}}}.*; +import {{{package}}}.{{{classname}}}; + +public class {{{classname}}}Example { + + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + // Configure clients using the `defaultClient` object, such as + // overriding the host and port, timeout, etc. + {{{classname}}} apiInstance = new {{{classname}}}(defaultClient); + {{#allParams}} + {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} + {{/allParams}} + try { + {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + System.out.println(result);{{/returnType}} + } catch (ApiException e) { + System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } +} +{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} +``` + +## Documentation for API Endpoints + +All URIs are relative to *{{basePath}}* + +Class | Method | HTTP request | Description +------------ | ------------- | ------------- | ------------- +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} + +## Documentation for Models + +{{#models}}{{#model}} - [{{classname}}]({{modelDocPath}}{{classname}}.md) +{{/model}}{{/models}} + +## Documentation for Authorization + +{{^authMethods}}All endpoints do not require authorization. +{{/authMethods}}Authentication schemes defined for the API: +{{#authMethods}}### {{name}} + +{{#isApiKey}} + +- **Type**: API key +- **API key parameter name**: {{keyParamName}} +- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}} +{{/isApiKey}} +{{#isBasic}} + +- **Type**: HTTP basic authentication +{{/isBasic}} +{{#isOAuth}} + +- **Type**: OAuth +- **Flow**: {{flow}} +- **Authorization URL**: {{authorizationUrl}} +- **Scopes**: {{^scopes}}N/A{{/scopes}} +{{#scopes}} - {{scope}}: {{description}} +{{/scopes}} +{{/isOAuth}} + +{{/authMethods}} + +## Recommendation + +It's recommended to create an instance of `ApiClient` per thread in a multithreaded environment to avoid any potential issues. +However, the instances of the api clients created from the `ApiClient` are thread-safe and can be re-used. + +## Author + +{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} +{{/hasMore}}{{/apis}}{{/apiInfo}} diff --git a/libraries/native/api.mustache b/libraries/native/api.mustache new file mode 100644 index 00000000000..f045c81743e --- /dev/null +++ b/libraries/native/api.mustache @@ -0,0 +1,157 @@ +{{>licenseInfo}} +package {{package}}; + +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.Pair; + +{{#imports}} +import {{import}}; +{{/imports}} + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.util.function.Consumer; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.StringJoiner; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}} { + private final HttpClient memberVarHttpClient; + private final ObjectMapper memberVarObjectMapper; + private final String memberVarBaseUri; + private final Consumer memberVarInterceptor; + private final Duration memberVarReadTimeout; + + public {{classname}}() { + this(new ApiClient()); + } + + public {{classname}}(ApiClient apiClient) { + memberVarHttpClient = apiClient.getHttpClient(); + memberVarObjectMapper = apiClient.getObjectMapper(); + memberVarBaseUri = apiClient.getBaseUri(); + memberVarInterceptor = apiClient.getRequestInterceptor(); + memberVarReadTimeout = apiClient.getReadTimeout(); + } + + {{#operation}} + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}}{{/required}} + {{/allParams}} + {{#returnType}} + * @return {{returnType}} + {{/returnType}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + {{#allParams}} + {{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + } + {{/required}} + {{/allParams}} + + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + + {{! Switch delimiters for baseName so we can write constants like "{query}" }} + String localVarPath = "{{{path}}}"{{#pathParams}} + .replace({{=<% %>=}}"{<%baseName%>}"<%={{ }}=%>, ApiClient.urlEncode({{{paramName}}}.toString())){{/pathParams}}; + + {{#hasQueryParams}} + {{javaUtilPrefix}}List localVarQueryParams = new {{javaUtilPrefix}}ArrayList<>(); + {{#queryParams}} + {{#collectionFormat}} + localVarQueryParams.addAll(ApiClient.parameterToPairs("{{{collectionFormat}}}", "{{baseName}}", {{paramName}})); + {{/collectionFormat}} + {{^collectionFormat}} + localVarQueryParams.addAll(ApiClient.parameterToPairs("{{baseName}}", {{paramName}})); + {{/collectionFormat}} + {{/queryParams}} + + if (!localVarQueryParams.isEmpty()) { + {{javaUtilPrefix}}StringJoiner queryJoiner = new StringJoiner("&"); + localVarQueryParams.forEach(p -> queryJoiner.add(p.getName() + '=' + p.getValue())); + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath + '?' + queryJoiner.toString())); + } else { + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + } + {{/hasQueryParams}} + {{^hasQueryParams}} + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + {{/hasQueryParams}} + + {{#headerParams}} + if ({{paramName}} != null) { + localVarRequestBuilder.header("{{baseName}}", {{paramName}}.toString()); + } + {{/headerParams}} + {{#bodyParam}} + localVarRequestBuilder.header("Content-Type", "application/json"); + {{/bodyParam}} + localVarRequestBuilder.header("Accept", "application/json"); + + try { + {{#bodyParam}} + byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes({{paramName}}); + localVarRequestBuilder.method("{{httpMethod}}", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody)); + {{/bodyParam}} + {{^bodyParam}} + localVarRequestBuilder.method("{{httpMethod}}", HttpRequest.BodyPublishers.noBody()); + {{/bodyParam}} + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); + } + + HttpResponse localVarResponse = memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (localVarResponse.statusCode()/ 100 != 2) { + throw new ApiException(localVarResponse.statusCode(), + "{{operationId}} call received non-success response", + localVarResponse.headers(), + localVarResponse.body() == null ? null : new String(localVarResponse.body().readAllBytes())); + } + + {{#returnType}} + return memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference<{{{returnType}}}>() {}); + {{/returnType}} + } catch (IOException | InterruptedException e) { + throw new ApiException(e); + } + } + {{/operation}} +} +{{/operations}} diff --git a/libraries/native/apiException.mustache b/libraries/native/apiException.mustache new file mode 100644 index 00000000000..3d0eee4bf9c --- /dev/null +++ b/libraries/native/apiException.mustache @@ -0,0 +1,79 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import java.net.http.HttpHeaders; + +{{>generatedAnnotation}} +public class ApiException extends{{#useRuntimeException}} RuntimeException {{/useRuntimeException}}{{^useRuntimeException}} Exception {{/useRuntimeException}}{ + private int code = 0; + private HttpHeaders responseHeaders = null; + private String responseBody = null; + + public ApiException() {} + + public ApiException(Throwable throwable) { + super(throwable); + } + + public ApiException(String message) { + super(message); + } + + public ApiException(String message, Throwable throwable, int code, HttpHeaders responseHeaders, String responseBody) { + super(message, throwable); + this.code = code; + this.responseHeaders = responseHeaders; + this.responseBody = responseBody; + } + + public ApiException(String message, int code, HttpHeaders responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(String message, Throwable throwable, int code, HttpHeaders responseHeaders) { + this(message, throwable, code, responseHeaders, null); + } + + public ApiException(int code, HttpHeaders responseHeaders, String responseBody) { + this((String) null, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(int code, String message) { + super(message); + this.code = code; + } + + public ApiException(int code, String message, HttpHeaders responseHeaders, String responseBody) { + this(code, message); + this.responseHeaders = responseHeaders; + this.responseBody = responseBody; + } + + /** + * Get the HTTP status code. + * + * @return HTTP status code + */ + public int getCode() { + return code; + } + + /** + * Get the HTTP response headers. + * + * @return Headers as an HttpHeaders object + */ + public HttpHeaders getResponseHeaders() { + return responseHeaders; + } + + /** + * Get the HTTP response body. + * + * @return Response body in the form of string + */ + public String getResponseBody() { + return responseBody; + } +} diff --git a/libraries/native/build.gradle.mustache b/libraries/native/build.gradle.mustache new file mode 100644 index 00000000000..f81df201eb2 --- /dev/null +++ b/libraries/native/build.gradle.mustache @@ -0,0 +1,66 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + mavenCentral() + jcenter() + } +} + +repositories { + mavenCentral() + jcenter() +} + +apply plugin: 'java' +apply plugin: 'maven' + +sourceCompatibility = JavaVersion.VERSION_11 +targetCompatibility = JavaVersion.VERSION_11 + +install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } +} + +task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath +} + +task sourcesJar(type: Jar, dependsOn: classes) { + classifier = 'sources' + from sourceSets.main.allSource +} + +task javadocJar(type: Jar, dependsOn: javadoc) { + classifier = 'javadoc' + from javadoc.destinationDir +} + +artifacts { + archives sourcesJar + archives javadocJar +} + + +ext { + swagger_annotations_version = "1.5.22" + jackson_version = "2.9.9" + junit_version = "4.12" +} + +dependencies { + compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "com.google.code.findbugs:jsr305:3.0.2" + compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + testCompile "junit:junit:$junit_version" +} diff --git a/libraries/native/gradle-wrapper.jar b/libraries/native/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..5c2d1cf016b3885f6930543d57b744ea8c220a1a GIT binary patch literal 55616 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 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/libraries/native/gradlew.mustache b/libraries/native/gradlew.mustache new file mode 100755 index 00000000000..8e25e6c19d5 --- /dev/null +++ b/libraries/native/gradlew.mustache @@ -0,0 +1,188 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# 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 +# +# https://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. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/libraries/native/pom.mustache b/libraries/native/pom.mustache new file mode 100644 index 00000000000..ad7c4234c1c --- /dev/null +++ b/libraries/native/pom.mustache @@ -0,0 +1,215 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{artifactUrl}} + {{artifactDescription}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + +{{#parentOverridden}} + + {{{parentGroupId}}} + {{{parentArtifactId}}} + {{{parentVersion}}} + +{{/parentOverridden}} + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 3 + + + 11 + + + + + + + + maven-surefire-plugin + 3.0.0-M3 + + + conf/log4j.properties + + -Xms512m -Xmx1500m + methods + 10 + + + + maven-dependency-plugin + 3.1.1 + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.2 + + + + test-jar + + + + + + + + maven-compiler-plugin + 3.8.1 + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.0 + + + attach-javadocs + + jar + + + + + + maven-source-plugin + 3.1.0 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + maven-gpg-plugin + 1.6 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-annotations-version} + + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-version} + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + + + junit + junit + ${junit-version} + test + + + + UTF-8 + 1.5.22 + 11 + 11 + 2.9.9 + 4.12 + + diff --git a/libraries/native/travis.mustache b/libraries/native/travis.mustache new file mode 100644 index 00000000000..d489da682e9 --- /dev/null +++ b/libraries/native/travis.mustache @@ -0,0 +1,16 @@ +# +# Generated by: https://openapi-generator.tech +# +language: java +jdk: + - oraclejdk11 +before_install: + # ensure gradlew has proper permission + - chmod a+x ./gradlew +script: + # test using maven + - mvn test + # uncomment below to test using gradle + # - gradle test + # uncomment below to test using sbt + # - sbt test From 28d34c966d9ff915e0d78faffa94bf5dbb19cb77 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 26 Jul 2019 10:00:27 +0800 Subject: [PATCH 130/370] [Java] add nullable support to the clients (#3453) * add nullable support, update samples * update samples --- pojo.mustache | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pojo.mustache b/pojo.mustache index 276de9b66ee..afd1ebf4098 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -129,7 +129,14 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela {{/maximum}} * @return {{name}} **/ -{{^required}} @javax.annotation.Nullable {{/required}} +{{#required}} +{{#isNullable}} + @javax.annotation.Nullable +{{/isNullable}} +{{/required}} +{{^required}} + @javax.annotation.Nullable +{{/required}} {{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} @ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") {{#vendorExtensions.extraAnnotation}} {{{vendorExtensions.extraAnnotation}}} From 3e64966b0500639ba14f91aca655225004b1cfa2 Mon Sep 17 00:00:00 2001 From: tjnet Date: Mon, 29 Jul 2019 11:34:57 +0900 Subject: [PATCH 131/370] remove unecessary null check as it cannot be reached due to the Null Pointer Exception (#3480) (#3481) --- libraries/resttemplate/ApiClient.mustache | 3 --- 1 file changed, 3 deletions(-) diff --git a/libraries/resttemplate/ApiClient.mustache b/libraries/resttemplate/ApiClient.mustache index 3f8f6a0f4de..4deaacb19ee 100644 --- a/libraries/resttemplate/ApiClient.mustache +++ b/libraries/resttemplate/ApiClient.mustache @@ -619,9 +619,6 @@ public class ApiClient { if (responseEntity.getStatusCode() == HttpStatus.NO_CONTENT) { return null; } else if (responseEntity.getStatusCode().is2xxSuccessful()) { - if (returnType == null) { - return null; - } return responseEntity.getBody(); } else { // The error handler built into the RestTemplate should handle 400 and 500 series errors. From 3e524d87cf1bc9b5ee68612b86173d544077ac2a Mon Sep 17 00:00:00 2001 From: Marc Schlegel Date: Thu, 1 Aug 2019 06:39:47 +0200 Subject: [PATCH 132/370] [java-client][okhttp-gson] fixes for interceptors in ApiClient.java (#3502) ApiClient for Okhttp3 must not copy the interceptors when setting the HttpClient. Enforce invariant that the HttpClient must never be null. --- libraries/okhttp-gson/ApiClient.mustache | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index cd173326c10..682bf945069 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -187,24 +187,14 @@ public class ApiClient { } /** - * Set HTTP client + * Set HTTP client, which must never be null. * * @param newHttpClient An instance of OkHttpClient * @return Api Client + * @throws NullPointerException when newHttpClient is null */ public ApiClient setHttpClient(OkHttpClient newHttpClient) { - if(!httpClient.equals(newHttpClient)) { - OkHttpClient.Builder builder = newHttpClient.newBuilder(); - Iterator networkInterceptorIterator = httpClient.networkInterceptors().iterator(); - while(networkInterceptorIterator.hasNext()) { - builder.addNetworkInterceptor(networkInterceptorIterator.next()); - } - Iterator interceptorIterator = httpClient.interceptors().iterator(); - while(interceptorIterator.hasNext()) { - builder.addInterceptor(interceptorIterator.next()); - } - this.httpClient = builder.build(); - } + this.httpClient = Objects.requireNonNull(newHttpClient, "HttpClient must not be null!"); return this; } From a9d71ca9f7bdf57ca4b3a1875072ef845097be14 Mon Sep 17 00:00:00 2001 From: unintended Date: Tue, 6 Aug 2019 13:56:43 +0300 Subject: [PATCH 133/370] Expand path templates via resttemplate's uriTemplateHandler (#3500) * Expand path templates via resttemplate's uriTemplateHandler * fix tests and compilation on lower jdk version * fix typo * re-generate samples --- libraries/resttemplate/ApiClient.mustache | 10 ++++++++++ libraries/resttemplate/api.mustache | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/libraries/resttemplate/ApiClient.mustache b/libraries/resttemplate/ApiClient.mustache index 4deaacb19ee..52e5f96e994 100644 --- a/libraries/resttemplate/ApiClient.mustache +++ b/libraries/resttemplate/ApiClient.mustache @@ -555,6 +555,16 @@ public class ApiClient { return isForm ? formParams : obj; } + /** + * Expand path template with variables + * @param pathTemplate path template with placeholders + * @param variables variables to replace + * @return path with placeholders replaced by variables + */ + public String expandPath(String pathTemplate, Map variables) { + return restTemplate.getUriTemplateHandler().expand(pathTemplate, variables).toString(); + } + /** * Invoke API by sending HTTP request with the given options. * diff --git a/libraries/resttemplate/api.mustache b/libraries/resttemplate/api.mustache index 040d776efe9..79cdcd51ac1 100644 --- a/libraries/resttemplate/api.mustache +++ b/libraries/resttemplate/api.mustache @@ -6,6 +6,7 @@ import {{invokerPackage}}.ApiClient; {{/imports}} {{^fullJavaUtil}}import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -72,7 +73,7 @@ public class {{classname}} { // create path and map variables final Map uriVariables = new HashMap();{{#pathParams}} uriVariables.put("{{baseName}}", {{#collectionFormat}}apiClient.collectionPathParameterToString(ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase()), {{{paramName}}}){{/collectionFormat}}{{^collectionFormat}}{{{paramName}}}{{/collectionFormat}});{{/pathParams}}{{/hasPathParams}} - String path = UriComponentsBuilder.fromPath("{{{path}}}"){{#hasPathParams}}.buildAndExpand(uriVariables){{/hasPathParams}}{{^hasPathParams}}.build(){{/hasPathParams}}.toUriString(); + String path = apiClient.expandPath("{{{path}}}", {{#hasPathParams}}uriVariables{{/hasPathParams}}{{^hasPathParams}}Collections.emptyMap(){{/hasPathParams}}); final MultiValueMap queryParams = new LinkedMultiValueMap(); final HttpHeaders headerParams = new HttpHeaders(); From c3e2ad790712639adf31239986d46c1bc5c6777c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Fri, 9 Aug 2019 05:01:23 +0200 Subject: [PATCH 134/370] [java][client][jax-rs] Add a constant for Jackson @JsonProperty (#3560) --- pojo.mustache | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pojo.mustache b/pojo.mustache index afd1ebf4098..240190fa11b 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -20,7 +20,8 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela {{/isContainer}} {{/isEnum}} {{#jackson}} - @JsonProperty("{{baseName}}") + public static final String JSON_PROPERTY_{{nameInSnakeCase}} = "{{baseName}}"; + @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) {{#withXml}} {{^isContainer}} @JacksonXmlProperty({{#isXmlAttribute}}isAttribute = true, {{/isXmlAttribute}}{{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}localName = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") From c056bc86bce5cf018ae1ee64d487a358e17f8207 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Thu, 15 Aug 2019 11:09:12 +0800 Subject: [PATCH 135/370] Add test cases to cover different collection formats (#3640) * add test cases to cover different collection format * add space params to retrofit 1.x * add space params to retrofit 2.x * rename url to localVarUrl * fix exception in haskell servant --- libraries/google-api-client/api.mustache | 12 ++++++------ libraries/retrofit/CollectionFormats.mustache | 4 ++++ libraries/retrofit2/CollectionFormats.mustache | 4 ++++ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/libraries/google-api-client/api.mustache b/libraries/google-api-client/api.mustache index 6a9c10c02ea..4083269ab18 100644 --- a/libraries/google-api-client/api.mustache +++ b/libraries/google-api-client/api.mustache @@ -104,8 +104,8 @@ public class {{classname}} { } }{{/queryParams}}{{/hasQueryParams}} - String url = uriBuilder{{#hasPathParams}}.buildFromMap(uriVariables).toString();{{/hasPathParams}}{{^hasPathParams}}.build().toString();{{/hasPathParams}} - GenericUrl genericUrl = new GenericUrl(url); + String localVarUrl = uriBuilder{{#hasPathParams}}.buildFromMap(uriVariables).toString();{{/hasPathParams}}{{^hasPathParams}}.build().toString();{{/hasPathParams}} + GenericUrl genericUrl = new GenericUrl(localVarUrl); HttpContent content = {{#isBodyAllowed}}apiClient.new JacksonJsonHttpContent({{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}){{/isBodyAllowed}}{{^isBodyAllowed}}null{{/isBodyAllowed}}; return apiClient.getHttpRequestFactory().buildRequest(HttpMethods.{{httpMethod}}, genericUrl, content).execute(); @@ -135,8 +135,8 @@ public class {{classname}} { } }{{/queryParams}}{{/hasQueryParams}} - String url = uriBuilder{{#hasPathParams}}.buildFromMap(uriVariables).toString();{{/hasPathParams}}{{^hasPathParams}}.build().toString();{{/hasPathParams}} - GenericUrl genericUrl = new GenericUrl(url); + String localVarUrl = uriBuilder{{#hasPathParams}}.buildFromMap(uriVariables).toString();{{/hasPathParams}}{{^hasPathParams}}.build().toString();{{/hasPathParams}} + GenericUrl genericUrl = new GenericUrl(localVarUrl); HttpContent content = {{#bodyParam}}{{paramName}} == null ? apiClient.new JacksonJsonHttpContent(null) : @@ -176,8 +176,8 @@ public class {{classname}} { } } - String url = uriBuilder{{#hasPathParams}}.buildFromMap(uriVariables).toString();{{/hasPathParams}}{{^hasPathParams}}.build().toString();{{/hasPathParams}} - GenericUrl genericUrl = new GenericUrl(url); + String localVarUrl = uriBuilder{{#hasPathParams}}.buildFromMap(uriVariables).toString();{{/hasPathParams}}{{^hasPathParams}}.build().toString();{{/hasPathParams}} + GenericUrl genericUrl = new GenericUrl(localVarUrl); HttpContent content = {{#isBodyAllowed}}apiClient.new JacksonJsonHttpContent({{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}){{/isBodyAllowed}}{{^isBodyAllowed}}null{{/isBodyAllowed}}; return apiClient.getHttpRequestFactory().buildRequest(HttpMethods.{{httpMethod}}, genericUrl, content).execute(); diff --git a/libraries/retrofit/CollectionFormats.mustache b/libraries/retrofit/CollectionFormats.mustache index a549ea59d1c..33331adb026 100644 --- a/libraries/retrofit/CollectionFormats.mustache +++ b/libraries/retrofit/CollectionFormats.mustache @@ -35,6 +35,10 @@ public class CollectionFormats { } + public static class SPACEParams extends SSVParams { + + } + public static class SSVParams extends CSVParams { public SSVParams() { diff --git a/libraries/retrofit2/CollectionFormats.mustache b/libraries/retrofit2/CollectionFormats.mustache index 8c91c335dfc..dbfa4ae767b 100644 --- a/libraries/retrofit2/CollectionFormats.mustache +++ b/libraries/retrofit2/CollectionFormats.mustache @@ -35,6 +35,10 @@ public class CollectionFormats { } + public static class SPACEParams extends SSVParams { + + } + public static class SSVParams extends CSVParams { public SSVParams() { From f1e5e8f17c1ede388be5aa0d214700488836a968 Mon Sep 17 00:00:00 2001 From: Benjamin Douglas Date: Wed, 14 Aug 2019 21:47:23 -0700 Subject: [PATCH 136/370] Use javax.annotation.processing.Generated for Java 11 native client (#3637) Before Java 9, the `Generated` annotation was part of JEE and in the `javax.annotation` package. Starting with Java 9, it is now part of the standard SDK, under the new `javax.annotation.processing` package. This change creates a custom Generated annotation template for the native clientlib, since it is guaranteed to be run in Java 11+. --- libraries/native/generatedAnnotation.mustache | 1 + 1 file changed, 1 insertion(+) create mode 100644 libraries/native/generatedAnnotation.mustache diff --git a/libraries/native/generatedAnnotation.mustache b/libraries/native/generatedAnnotation.mustache new file mode 100644 index 00000000000..dc1f2cd40e9 --- /dev/null +++ b/libraries/native/generatedAnnotation.mustache @@ -0,0 +1 @@ +{{^hideGenerationTimestamp}}@javax.annotation.processing.Generated(value = "{{generatorClass}}", date = "{{generatedDate}}"){{/hideGenerationTimestamp}} \ No newline at end of file From 8d78cd5d3450df7ca1ddd468e632d471cd16d3f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Thu, 15 Aug 2019 16:01:19 +0200 Subject: [PATCH 137/370] [java-client] set collection to null when not required (#3615) * [java][model] set collection to null when not required * Fix tests * Fix trailing whitespace * generate samples * Restore 'de.thetaphi' plugin in pom.xml --- pojo.mustache | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pojo.mustache b/pojo.mustache index 240190fa11b..f0c3a646258 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -59,7 +59,12 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}"; @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}}) {{/gson}} + {{#isContainer}} + private {{{datatypeWithEnum}}} {{name}}{{#required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/required}}{{^required}} = null{{/required}}; + {{/isContainer}} + {{^isContainer}} private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; + {{/isContainer}} {{/vars}} {{#parcelableModel}} From 5ed58084c9ecdfaf1dff757ce49dcc648545fe77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Fri, 16 Aug 2019 05:42:41 +0200 Subject: [PATCH 138/370] [java-client][jersey2][resteasy] add support for TRACE method (#3653) --- libraries/jersey2/ApiClient.mustache | 2 ++ libraries/resteasy/ApiClient.mustache | 2 ++ 2 files changed, 4 insertions(+) diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 1007a857ca0..24c8b86d30a 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -721,6 +721,8 @@ public class ApiClient { response = invocationBuilder.method("PATCH", entity); } else if ("HEAD".equals(method)) { response = invocationBuilder.head(); + } else if ("TRACE".equals(method)) { + response = invocationBuilder.trace(); } else { throw new ApiException(500, "unknown method type " + method); } diff --git a/libraries/resteasy/ApiClient.mustache b/libraries/resteasy/ApiClient.mustache index 457abc0e1d8..fa12ff9be3b 100644 --- a/libraries/resteasy/ApiClient.mustache +++ b/libraries/resteasy/ApiClient.mustache @@ -666,6 +666,8 @@ public class ApiClient { response = invocationBuilder.header("X-HTTP-Method-Override", "PATCH").post(entity); } else if ("HEAD".equals(method)) { response = invocationBuilder.head(); + } else if ("TRACE".equals(method)) { + response = invocationBuilder.trace(); } else { throw new ApiException(500, "unknown method type " + method); } From 55a39bac4e0c649a13ea446922712f86c3f4373e Mon Sep 17 00:00:00 2001 From: Slavek Kabrda Date: Fri, 16 Aug 2019 10:26:06 +0200 Subject: [PATCH 139/370] [Java][client] make it possible to send explicit nulls for nullable fields (#3474) * [Java][client] make it possible to send explicit nulls for nullable fields * Regenerate samples --- jackson_annotations.mustache | 19 ++++ libraries/feign/ApiClient.mustache | 3 + libraries/feign/pom.mustache | 6 ++ .../google-api-client/ApiClient.mustache | 3 + libraries/google-api-client/pom.mustache | 6 ++ libraries/jersey2/JSON.mustache | 3 + libraries/jersey2/pom.mustache | 6 ++ libraries/native/ApiClient.mustache | 3 + libraries/native/pom.mustache | 6 ++ libraries/resteasy/JSON.mustache | 3 + libraries/resteasy/pom.mustache | 6 ++ libraries/resttemplate/ApiClient.mustache | 3 + libraries/resttemplate/pom.mustache | 6 ++ libraries/retrofit2/play24/ApiClient.mustache | 8 +- libraries/retrofit2/play25/ApiClient.mustache | 8 +- libraries/retrofit2/play26/ApiClient.mustache | 3 + libraries/retrofit2/pom.mustache | 16 ++++ libraries/vertx/ApiClient.mustache | 3 + libraries/vertx/pom.mustache | 6 ++ libraries/webclient/ApiClient.mustache | 3 + libraries/webclient/pom.mustache | 6 ++ pojo.mustache | 88 +++++++++++++++---- 22 files changed, 196 insertions(+), 18 deletions(-) create mode 100644 jackson_annotations.mustache diff --git a/jackson_annotations.mustache b/jackson_annotations.mustache new file mode 100644 index 00000000000..ac01b293cc1 --- /dev/null +++ b/jackson_annotations.mustache @@ -0,0 +1,19 @@ +{{! + If this is map and items are nullable, make sure that nulls are included. + To determine what JsonInclude.Include method to use, consider the following: + * If the field is required, always include it, even if it is null. + * Else use custom behaviour, IOW use whatever is defined on the object mapper + }} + @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) + @JsonInclude({{#isMapContainer}}{{#items.isNullable}}content = JsonInclude.Include.ALWAYS, {{/items.isNullable}}{{/isMapContainer}}value = JsonInclude.Include.{{#required}}ALWAYS{{/required}}{{^required}}USE_DEFAULTS{{/required}}) + {{#withXml}} + {{^isContainer}} + @JacksonXmlProperty({{#isXmlAttribute}}isAttribute = true, {{/isXmlAttribute}}{{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}localName = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isContainer}} + {{#isContainer}} + {{#isXmlWrapped}} + // items.xmlName={{items.xmlName}} + @JacksonXmlElementWrapper(useWrapping = {{isXmlWrapped}}, {{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}localName = "{{#items.xmlName}}{{items.xmlName}}{{/items.xmlName}}{{^items.xmlName}}{{items.baseName}}{{/items.xmlName}}") + {{/isXmlWrapped}} + {{/isContainer}} + {{/withXml}} \ No newline at end of file diff --git a/libraries/feign/ApiClient.mustache b/libraries/feign/ApiClient.mustache index 6d43061d347..9df586c08cb 100644 --- a/libraries/feign/ApiClient.mustache +++ b/libraries/feign/ApiClient.mustache @@ -12,6 +12,7 @@ import org.threeten.bp.*; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; +import org.openapitools.jackson.nullable.JsonNullableModule; {{#joda}} import com.fasterxml.jackson.datatype.joda.JodaModule; {{/joda}} @@ -177,6 +178,8 @@ public class ApiClient { module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); objectMapper.registerModule(module); {{/threetenbp}} + JsonNullableModule jnm = new JsonNullableModule(); + objectMapper.registerModule(jnm); return objectMapper; } diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index d2634ca5df4..1e9edaec8c0 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -244,6 +244,11 @@ jackson-databind ${jackson-databind-version} + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + {{#withXml}} @@ -310,6 +315,7 @@ {{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}} 2.1.0 2.9.9 + 0.2.0 2.9.9 {{#threetenbp}} 2.6.4 diff --git a/libraries/google-api-client/ApiClient.mustache b/libraries/google-api-client/ApiClient.mustache index fa6e7a601fe..9df560415d0 100644 --- a/libraries/google-api-client/ApiClient.mustache +++ b/libraries/google-api-client/ApiClient.mustache @@ -4,6 +4,7 @@ import {{apiPackage}}.*; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; +import org.openapitools.jackson.nullable.JsonNullableModule; {{#joda}} import com.fasterxml.jackson.datatype.joda.JodaModule; {{/joda}} @@ -53,6 +54,8 @@ public class ApiClient { module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); objectMapper.registerModule(module); {{/threetenbp}} + JsonNullableModule jnm = new JsonNullableModule(); + objectMapper.registerModule(jnm); return objectMapper; } diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index 0269a88c3bc..be8c28602dd 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -253,6 +253,11 @@ jackson-databind ${jackson-version} + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + {{#withXml}} @@ -303,6 +308,7 @@ 2.25.1 2.9.9 2.9.9 + 0.2.0 {{#joda}} 2.9.9 {{/joda}} diff --git a/libraries/jersey2/JSON.mustache b/libraries/jersey2/JSON.mustache index 911391a6baf..56ea77278f7 100644 --- a/libraries/jersey2/JSON.mustache +++ b/libraries/jersey2/JSON.mustache @@ -5,6 +5,7 @@ import org.threeten.bp.*; {{/threetenbp}} import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; +import org.openapitools.jackson.nullable.JsonNullableModule; {{#java8}} import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; {{/java8}} @@ -45,6 +46,8 @@ public class JSON implements ContextResolver { module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); mapper.registerModule(module); {{/threetenbp}} + JsonNullableModule jnm = new JsonNullableModule(); + mapper.registerModule(jnm); } /** diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 27a94b56311..d72e0b1fe81 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -276,6 +276,11 @@ jackson-databind ${jackson-databind-version} + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + {{#withXml}} @@ -357,6 +362,7 @@ {{/supportJava6}} 2.9.9 2.9.9 + 0.2.0 {{#threetenbp}} 2.6.4 {{/threetenbp}} diff --git a/libraries/native/ApiClient.mustache b/libraries/native/ApiClient.mustache index eee8f2923d9..ce313c70ef5 100644 --- a/libraries/native/ApiClient.mustache +++ b/libraries/native/ApiClient.mustache @@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.openapitools.jackson.nullable.JsonNullableModule; import java.net.URI; import java.net.URLEncoder; @@ -151,6 +152,8 @@ public class ApiClient { mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); mapper.registerModule(new JavaTimeModule()); + JsonNullableModule jnm = new JsonNullableModule(); + mapper.registerModule(jnm); URI baseURI = URI.create("{{{basePath}}}"); scheme = baseURI.getScheme(); host = baseURI.getHost(); diff --git a/libraries/native/pom.mustache b/libraries/native/pom.mustache index ad7c4234c1c..e3fe7f74118 100644 --- a/libraries/native/pom.mustache +++ b/libraries/native/pom.mustache @@ -188,6 +188,11 @@ jackson-datatype-jsr310 ${jackson-version} + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + @@ -210,6 +215,7 @@ 11 11 2.9.9 + 0.2.0 4.12 diff --git a/libraries/resteasy/JSON.mustache b/libraries/resteasy/JSON.mustache index 6f5829fa509..22888421d82 100644 --- a/libraries/resteasy/JSON.mustache +++ b/libraries/resteasy/JSON.mustache @@ -2,6 +2,7 @@ package {{invokerPackage}}; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; +import org.openapitools.jackson.nullable.JsonNullableModule; {{#java8}} import com.fasterxml.jackson.datatype.jsr310.*; {{/java8}} @@ -26,6 +27,8 @@ public class JSON implements ContextResolver { mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); mapper.setDateFormat(new RFC3339DateFormat()); + JsonNullableModule jnm = new JsonNullableModule(); + mapper.registerModule(jnm); {{#java8}} mapper.registerModule(new JavaTimeModule()); {{/java8}} diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index 7d6927871f1..d190566bac5 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -212,6 +212,11 @@ jackson-databind ${jackson-databind-version} + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + {{#withXml}} @@ -291,6 +296,7 @@ 3.1.3.Final 2.9.9 2.9.9 + 0.2.0 2.6.4 {{^java8}} 2.9.9 diff --git a/libraries/resttemplate/ApiClient.mustache b/libraries/resttemplate/ApiClient.mustache index 52e5f96e994..43078344343 100644 --- a/libraries/resttemplate/ApiClient.mustache +++ b/libraries/resttemplate/ApiClient.mustache @@ -39,6 +39,7 @@ import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter; import com.fasterxml.jackson.databind.ObjectMapper; +import org.openapitools.jackson.nullable.JsonNullableModule; {{/threetenbp}} import java.io.BufferedReader; @@ -661,6 +662,7 @@ public class ApiClient { messageConverters.add(new MappingJackson2HttpMessageConverter()); XmlMapper xmlMapper = new XmlMapper(); xmlMapper.configure(ToXmlGenerator.Feature.WRITE_XML_DECLARATION, true); + xmlMapper.registerModule(new JsonNullableModule()); messageConverters.add(new MappingJackson2XmlHttpMessageConverter(xmlMapper)); RestTemplate restTemplate = new RestTemplate(messageConverters); @@ -674,6 +676,7 @@ public class ApiClient { module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); mapper.registerModule(module); + mapper.registerModule(new JsonNullableModule()); } } {{/threetenbp}} diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache index 77d021644d6..c48a68e347a 100644 --- a/libraries/resttemplate/pom.mustache +++ b/libraries/resttemplate/pom.mustache @@ -255,6 +255,11 @@ jackson-jaxrs-json-provider ${jackson-version} + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + {{#withXml}} @@ -306,6 +311,7 @@ 4.3.9.RELEASE 2.9.9 2.9.9 + 0.2.0 {{#joda}} 2.9.9 {{/joda}} diff --git a/libraries/retrofit2/play24/ApiClient.mustache b/libraries/retrofit2/play24/ApiClient.mustache index e03dc69971b..2395426ab2c 100644 --- a/libraries/retrofit2/play24/ApiClient.mustache +++ b/libraries/retrofit2/play24/ApiClient.mustache @@ -8,6 +8,8 @@ import java.util.*; import retrofit2.Retrofit; import retrofit2.converter.scalars.ScalarsConverterFactory; import retrofit2.converter.jackson.JacksonConverterFactory; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.openapitools.jackson.nullable.JsonNullableModule; import play.libs.Json; import play.libs.ws.WSClient; @@ -68,10 +70,14 @@ public class ApiClient { auth.applyToParams(extraQueryParams, extraHeaders); } + ObjectMapper mapper = Json.mapper(); + JsonNullableModule jnm = new JsonNullableModule(); + mapper.registerModule(jnm); + return new Retrofit.Builder() .baseUrl(basePath) .addConverterFactory(ScalarsConverterFactory.create()) - .addConverterFactory(JacksonConverterFactory.create(Json.mapper())) + .addConverterFactory(JacksonConverterFactory.create(mapper)) .callFactory(new Play24CallFactory(wsClient, extraHeaders, extraQueryParams)) .addCallAdapterFactory(new Play24CallAdapterFactory()) .build() diff --git a/libraries/retrofit2/play25/ApiClient.mustache b/libraries/retrofit2/play25/ApiClient.mustache index 7d3dbd1e28c..221d52c4e9b 100644 --- a/libraries/retrofit2/play25/ApiClient.mustache +++ b/libraries/retrofit2/play25/ApiClient.mustache @@ -8,6 +8,8 @@ import java.util.*; import retrofit2.Retrofit; import retrofit2.converter.scalars.ScalarsConverterFactory; import retrofit2.converter.jackson.JacksonConverterFactory; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.openapitools.jackson.nullable.JsonNullableModule; import play.libs.Json; import play.libs.ws.WSClient; @@ -67,10 +69,14 @@ public class ApiClient { auth.applyToParams(extraQueryParams, extraHeaders); } + ObjectMapper mapper = Json.mapper(); + JsonNullableModule jnm = new JsonNullableModule(); + mapper.registerModule(jnm); + return new Retrofit.Builder() .baseUrl(basePath) .addConverterFactory(ScalarsConverterFactory.create()) - .addConverterFactory(JacksonConverterFactory.create(Json.mapper())) + .addConverterFactory(JacksonConverterFactory.create(mapper)) .callFactory(new Play25CallFactory(wsClient, extraHeaders, extraQueryParams)) .addCallAdapterFactory(new Play25CallAdapterFactory()) .build() diff --git a/libraries/retrofit2/play26/ApiClient.mustache b/libraries/retrofit2/play26/ApiClient.mustache index d59912773c8..166fb088019 100644 --- a/libraries/retrofit2/play26/ApiClient.mustache +++ b/libraries/retrofit2/play26/ApiClient.mustache @@ -13,6 +13,7 @@ import retrofit2.Converter; import retrofit2.Retrofit; import retrofit2.converter.scalars.ScalarsConverterFactory; import retrofit2.converter.jackson.JacksonConverterFactory; +import org.openapitools.jackson.nullable.JsonNullableModule; import play.libs.Json; import play.libs.ws.WSClient; @@ -89,6 +90,8 @@ public class ApiClient { } if (defaultMapper == null) { defaultMapper = Json.mapper(); + JsonNullableModule jnm = new JsonNullableModule(); + defaultMapper.registerModule(jnm); } return new Retrofit.Builder() diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index aef50309c1c..b35ffe66264 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -314,6 +314,11 @@ play-java-ws_2.11 ${play-version} + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + {{/play24}} {{#play25}} @@ -321,6 +326,11 @@ play-java-ws_2.11 ${play-version} + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + {{/play25}} {{#play26}} @@ -333,6 +343,11 @@ validation-api 1.1.0.Final + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + {{/play26}} {{/usePlayWS}} {{#parcelableModel}} @@ -373,6 +388,7 @@ 2.9.9 2.6.7 {{/play26}} + 0.2.0 {{/usePlayWS}} 2.5.0 {{#useRxJava}} diff --git a/libraries/vertx/ApiClient.mustache b/libraries/vertx/ApiClient.mustache index 170c92666ed..90f4cbcb33b 100644 --- a/libraries/vertx/ApiClient.mustache +++ b/libraries/vertx/ApiClient.mustache @@ -14,6 +14,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.openapitools.jackson.nullable.JsonNullableModule; import io.vertx.core.*; import io.vertx.core.buffer.Buffer; import io.vertx.core.file.AsyncFile; @@ -77,6 +78,8 @@ public class ApiClient { this.objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); this.objectMapper.registerModule(new JavaTimeModule()); this.objectMapper.setDateFormat(dateFormat); + JsonNullableModule jnm = new JsonNullableModule(); + this.objectMapper.registerModule(jnm); // Setup authentications (key: authentication name, value: authentication). this.authentications = new HashMap<>();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache index db6ef66924b..a2fd9f30ebe 100644 --- a/libraries/vertx/pom.mustache +++ b/libraries/vertx/pom.mustache @@ -243,6 +243,11 @@ jackson-databind ${jackson-databind} + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + {{#joda}} com.fasterxml.jackson.datatype @@ -286,6 +291,7 @@ 1.5.22 {{^threetenbp}}2.9.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} {{^threetenbp}}2.9.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} + 0.2.0 4.12 diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index 943acff9c37..2e08f6da5f2 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -3,6 +3,7 @@ package {{invokerPackage}}; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.openapitools.jackson.nullable.JsonNullableModule; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.core.ParameterizedTypeReference; @@ -96,6 +97,8 @@ public class ApiClient { mapper.setDateFormat(dateFormat); mapper.registerModule(new JavaTimeModule()); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + JsonNullableModule jnm = new JsonNullableModule(); + mapper.registerModule(jnm); this.webClient = buildWebClient(mapper); this.init(); diff --git a/libraries/webclient/pom.mustache b/libraries/webclient/pom.mustache index 44098edb0f3..4fbf5d9cf1d 100644 --- a/libraries/webclient/pom.mustache +++ b/libraries/webclient/pom.mustache @@ -105,6 +105,11 @@ jackson-databind ${jackson-databind-version} + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + {{#java8}} @@ -140,6 +145,7 @@ 5.0.7.RELEASE 2.9.9 2.9.9 + 0.2.0 4.12 3.1.8.RELEASE 0.7.8.RELEASE diff --git a/pojo.mustache b/pojo.mustache index f0c3a646258..6ba1d72e2bc 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -19,21 +19,6 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela {{/mostInnerItems}} {{/isContainer}} {{/isEnum}} - {{#jackson}} - public static final String JSON_PROPERTY_{{nameInSnakeCase}} = "{{baseName}}"; - @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) - {{#withXml}} - {{^isContainer}} - @JacksonXmlProperty({{#isXmlAttribute}}isAttribute = true, {{/isXmlAttribute}}{{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}localName = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") - {{/isContainer}} - {{#isContainer}} - {{#isXmlWrapped}} - // items.xmlName={{items.xmlName}} - @JacksonXmlElementWrapper(useWrapping = {{isXmlWrapped}}, {{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}localName = "{{#items.xmlName}}{{items.xmlName}}{{/items.xmlName}}{{^items.xmlName}}{{items.baseName}}{{/items.xmlName}}") - {{/isXmlWrapped}} - {{/isContainer}} - {{/withXml}} - {{/jackson}} {{#withXml}} {{#isXmlAttribute}} @XmlAttribute(name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") @@ -59,12 +44,25 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}"; @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}}) {{/gson}} + {{#jackson}} + public static final String JSON_PROPERTY_{{nameInSnakeCase}} = "{{baseName}}"; + {{/jackson}} + {{#vendorExtensions.isJacksonOptionalNullable}} + {{#isContainer}} + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined(); + {{/isContainer}} + {{^isContainer}} + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + {{/isContainer}} + {{/vendorExtensions.isJacksonOptionalNullable}} + {{^vendorExtensions.isJacksonOptionalNullable}} {{#isContainer}} private {{{datatypeWithEnum}}} {{name}}{{#required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/required}}{{^required}} = null{{/required}}; {{/isContainer}} {{^isContainer}} private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; {{/isContainer}} + {{/vendorExtensions.isJacksonOptionalNullable}} {{/vars}} {{#parcelableModel}} @@ -89,14 +87,28 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela {{/gson}} {{/parcelableModel}} {{#vars}} + {{^isReadOnly}} public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { - this.{{name}} = {{name}}; + {{#vendorExtensions.isJacksonOptionalNullable}}this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});{{/vendorExtensions.isJacksonOptionalNullable}} + {{^vendorExtensions.isJacksonOptionalNullable}}this.{{name}} = {{name}};{{/vendorExtensions.isJacksonOptionalNullable}} return this; } {{#isListContainer}} public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { + {{#vendorExtensions.isJacksonOptionalNullable}} + if (this.{{name}} == null || !this.{{name}}.isPresent()) { + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); + } + try { + this.{{name}}.get().add({{name}}Item); + } catch (java.util.NoSuchElementException e) { + // this can never happen, as we make sure above that the value is present + } + return this; + {{/vendorExtensions.isJacksonOptionalNullable}} + {{^vendorExtensions.isJacksonOptionalNullable}} {{^required}} if (this.{{name}} == null) { this.{{name}} = {{{defaultValue}}}; @@ -104,11 +116,24 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela {{/required}} this.{{name}}.add({{name}}Item); return this; + {{/vendorExtensions.isJacksonOptionalNullable}} } {{/isListContainer}} {{#isMapContainer}} public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { + {{#vendorExtensions.isJacksonOptionalNullable}} + if (this.{{name}} == null || !this.{{name}}.isPresent()) { + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); + } + try { + this.{{name}}.get().put(key, {{name}}Item); + } catch (java.util.NoSuchElementException e) { + // this can never happen, as we make sure above that the value is present + } + return this; + {{/vendorExtensions.isJacksonOptionalNullable}} + {{^vendorExtensions.isJacksonOptionalNullable}} {{^required}} if (this.{{name}} == null) { this.{{name}} = {{{defaultValue}}}; @@ -116,6 +141,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela {{/required}} this.{{name}}.put(key, {{name}}Item); return this; + {{/vendorExtensions.isJacksonOptionalNullable}} } {{/isMapContainer}} @@ -147,13 +173,43 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela {{#vendorExtensions.extraAnnotation}} {{{vendorExtensions.extraAnnotation}}} {{/vendorExtensions.extraAnnotation}} +{{^vendorExtensions.isJacksonOptionalNullable}}{{#jackson}}{{> jackson_annotations}}{{/jackson}}{{/vendorExtensions.isJacksonOptionalNullable}} public {{{datatypeWithEnum}}} {{getter}}() { + {{#vendorExtensions.isJacksonOptionalNullable}} + {{#isReadOnly}}{{! A readonly attribute doesn't have setter => jackson will set null directly if explicitly returned by API, so make sure we have an empty JsonNullable}} + if ({{name}} == null) { + {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + } + {{/isReadOnly}} + return {{name}}.orElse(null); + {{/vendorExtensions.isJacksonOptionalNullable}} + {{^vendorExtensions.isJacksonOptionalNullable}} + return {{name}}; + {{/vendorExtensions.isJacksonOptionalNullable}} + } + + {{#vendorExtensions.isJacksonOptionalNullable}} +{{> jackson_annotations}} + public JsonNullable<{{{datatypeWithEnum}}}> {{getter}}_JsonNullable() { return {{name}}; } + {{/vendorExtensions.isJacksonOptionalNullable}} + {{^isReadOnly}} + {{#vendorExtensions.isJacksonOptionalNullable}} + @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) + public void {{setter}}_JsonNullable(JsonNullable<{{{datatypeWithEnum}}}> {{name}}) { + this.{{name}} = {{name}}; + } + {{/vendorExtensions.isJacksonOptionalNullable}} public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.isJacksonOptionalNullable}} + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); + {{/vendorExtensions.isJacksonOptionalNullable}} + {{^vendorExtensions.isJacksonOptionalNullable}} this.{{name}} = {{name}}; + {{/vendorExtensions.isJacksonOptionalNullable}} } {{/isReadOnly}} From e688fa957e74a03ef732026ab7eca69befd6234d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Mon, 19 Aug 2019 16:51:18 +0200 Subject: [PATCH 140/370] [java-client][jersey2][resteasy] add support for OPTIONS method (#3677) * [java-client][jersey2][resteasy] add support for OPTIONS method * Update samples --- libraries/jersey2/ApiClient.mustache | 2 ++ libraries/resteasy/ApiClient.mustache | 2 ++ 2 files changed, 4 insertions(+) diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 24c8b86d30a..ab6a4a1353c 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -721,6 +721,8 @@ public class ApiClient { response = invocationBuilder.method("PATCH", entity); } else if ("HEAD".equals(method)) { response = invocationBuilder.head(); + } else if ("OPTIONS".equals(method)) { + response = invocationBuilder.options(); } else if ("TRACE".equals(method)) { response = invocationBuilder.trace(); } else { diff --git a/libraries/resteasy/ApiClient.mustache b/libraries/resteasy/ApiClient.mustache index fa12ff9be3b..c094e55c728 100644 --- a/libraries/resteasy/ApiClient.mustache +++ b/libraries/resteasy/ApiClient.mustache @@ -666,6 +666,8 @@ public class ApiClient { response = invocationBuilder.header("X-HTTP-Method-Override", "PATCH").post(entity); } else if ("HEAD".equals(method)) { response = invocationBuilder.head(); + } else if ("OPTIONS".equals(method)) { + response = invocationBuilder.options(); } else if ("TRACE".equals(method)) { response = invocationBuilder.trace(); } else { From 2edc284fe7e5e98740379f7ee89bf3dd05cc61cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Wed, 21 Aug 2019 15:38:27 +0200 Subject: [PATCH 141/370] [java-client][resteasy] support bearer authentication (#3706) --- libraries/resteasy/ApiClient.mustache | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/resteasy/ApiClient.mustache b/libraries/resteasy/ApiClient.mustache index c094e55c728..dbf79473a23 100644 --- a/libraries/resteasy/ApiClient.mustache +++ b/libraries/resteasy/ApiClient.mustache @@ -41,6 +41,7 @@ import org.jboss.resteasy.spi.ResteasyProviderFactory; import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.HttpBearerAuth; import {{invokerPackage}}.auth.ApiKeyAuth; {{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; @@ -78,8 +79,9 @@ public class ApiClient { setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); // Setup authentications (key: authentication name, value: authentication). - authentications = new HashMap();{{#authMethods}}{{#isBasic}} - authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} + authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} // Prevent the authentications from being modified. From c0b2277189f8f0c45c4b339fdfb9b3f350965986 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Thu, 22 Aug 2019 09:50:47 +0200 Subject: [PATCH 142/370] [java-client][resteasy][jersey2][google-api-client][okhttp-json] several fixes to make sent requests more accurate (#3703) --- libraries/google-api-client/api.mustache | 5 +++-- libraries/jersey2/ApiClient.mustache | 9 +++++++-- libraries/jersey2/api.mustache | 2 +- libraries/okhttp-gson/api.mustache | 2 +- libraries/resteasy/ApiClient.mustache | 4 ++-- libraries/resteasy/api.mustache | 2 +- 6 files changed, 15 insertions(+), 9 deletions(-) diff --git a/libraries/google-api-client/api.mustache b/libraries/google-api-client/api.mustache index 4083269ab18..7c5669aa2a2 100644 --- a/libraries/google-api-client/api.mustache +++ b/libraries/google-api-client/api.mustache @@ -6,6 +6,7 @@ import {{invokerPackage}}.ApiClient; {{/imports}} import com.fasterxml.jackson.core.type.TypeReference; +import com.google.api.client.http.EmptyContent; import com.google.api.client.http.GenericUrl; import com.google.api.client.http.HttpContent; import com.google.api.client.http.InputStreamContent; @@ -107,7 +108,7 @@ public class {{classname}} { String localVarUrl = uriBuilder{{#hasPathParams}}.buildFromMap(uriVariables).toString();{{/hasPathParams}}{{^hasPathParams}}.build().toString();{{/hasPathParams}} GenericUrl genericUrl = new GenericUrl(localVarUrl); - HttpContent content = {{#isBodyAllowed}}apiClient.new JacksonJsonHttpContent({{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}){{/isBodyAllowed}}{{^isBodyAllowed}}null{{/isBodyAllowed}}; + HttpContent content = {{#isBodyAllowed}}{{#bodyParam}}apiClient.new JacksonJsonHttpContent({{paramName}}){{/bodyParam}}{{^bodyParam}}new EmptyContent(){{/bodyParam}}{{/isBodyAllowed}}{{^isBodyAllowed}}null{{/isBodyAllowed}}; return apiClient.getHttpRequestFactory().buildRequest(HttpMethods.{{httpMethod}}, genericUrl, content).execute(); }{{#bodyParam}} @@ -179,7 +180,7 @@ public class {{classname}} { String localVarUrl = uriBuilder{{#hasPathParams}}.buildFromMap(uriVariables).toString();{{/hasPathParams}}{{^hasPathParams}}.build().toString();{{/hasPathParams}} GenericUrl genericUrl = new GenericUrl(localVarUrl); - HttpContent content = {{#isBodyAllowed}}apiClient.new JacksonJsonHttpContent({{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}){{/isBodyAllowed}}{{^isBodyAllowed}}null{{/isBodyAllowed}}; + HttpContent content = {{#isBodyAllowed}}{{#bodyParam}}apiClient.new JacksonJsonHttpContent({{paramName}}){{/bodyParam}}{{^bodyParam}}new EmptyContent(){{/bodyParam}}{{/isBodyAllowed}}{{^isBodyAllowed}}null{{/isBodyAllowed}}; return apiClient.getHttpRequestFactory().buildRequest(HttpMethods.{{httpMethod}}, genericUrl, content).execute(); } diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index ab6a4a1353c..4d2c3e21b61 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -704,7 +704,7 @@ public class ApiClient { } } - Entity entity = serialize(body, formParams, contentType); + Entity entity = (body == null) ? Entity.json("") : serialize(body, formParams, contentType); Response response = null; @@ -716,7 +716,7 @@ public class ApiClient { } else if ("PUT".equals(method)) { response = invocationBuilder.put(entity); } else if ("DELETE".equals(method)) { - response = invocationBuilder.delete(); + response = invocationBuilder.method("DELETE", entity); } else if ("PATCH".equals(method)) { response = invocationBuilder.method("PATCH", entity); } else if ("HEAD".equals(method)) { @@ -776,6 +776,8 @@ public class ApiClient { clientConfig.register(json); clientConfig.register(JacksonFeature.class); clientConfig.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true); + // turn off compliance validation to be able to send payloads with DELETE calls + clientConfig.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true); if (debugging) { {{^supportJava6}} clientConfig.register(new LoggingFeature(java.util.logging.Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME), java.util.logging.Level.INFO, LoggingFeature.Verbosity.PAYLOAD_ANY, 1024*50 /* Log payloads up to 50K */)); @@ -786,6 +788,9 @@ public class ApiClient { {{#supportJava6}} clientConfig.register(new LoggingFilter(java.util.logging.Logger.getLogger(LoggingFilter.class.getName()), true)); {{/supportJava6}} + } else { + // suppress warnings for payloads with DELETE calls: + java.util.logging.Logger.getLogger("org.glassfish.jersey.client").setLevel(java.util.logging.Level.SEVERE); } performAdditionalClientConfiguration(clientConfig); return ClientBuilder.newClient(clientConfig); diff --git a/libraries/jersey2/api.mustache b/libraries/jersey2/api.mustache index 19c079e3229..89131a0f943 100644 --- a/libraries/jersey2/api.mustache +++ b/libraries/jersey2/api.mustache @@ -107,7 +107,7 @@ public class {{classname}} { @Deprecated {{/isDeprecated}} public ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { - Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}new Object(){{/bodyParam}}; + Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { diff --git a/libraries/okhttp-gson/api.mustache b/libraries/okhttp-gson/api.mustache index 32b1e3fcf04..26015967b40 100644 --- a/libraries/okhttp-gson/api.mustache +++ b/libraries/okhttp-gson/api.mustache @@ -90,7 +90,7 @@ public class {{classname}} { @Deprecated {{/isDeprecated}} public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} okhttp3.Call {{operationId}}Call({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ApiCallback _callback) throws ApiException { - Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}new Object(){{/bodyParam}}; + Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; // create path and map variables String localVarPath = "{{{path}}}"{{#pathParams}} diff --git a/libraries/resteasy/ApiClient.mustache b/libraries/resteasy/ApiClient.mustache index dbf79473a23..ca672da4998 100644 --- a/libraries/resteasy/ApiClient.mustache +++ b/libraries/resteasy/ApiClient.mustache @@ -663,9 +663,9 @@ public class ApiClient { } else if ("PUT".equals(method)) { response = invocationBuilder.put(entity); } else if ("DELETE".equals(method)) { - response = invocationBuilder.delete(); + response = invocationBuilder.method("DELETE", entity); } else if ("PATCH".equals(method)) { - response = invocationBuilder.header("X-HTTP-Method-Override", "PATCH").post(entity); + response = invocationBuilder.method("PATCH", entity); } else if ("HEAD".equals(method)) { response = invocationBuilder.head(); } else if ("OPTIONS".equals(method)) { diff --git a/libraries/resteasy/api.mustache b/libraries/resteasy/api.mustache index f6806af6b5f..e13ddbc9e16 100644 --- a/libraries/resteasy/api.mustache +++ b/libraries/resteasy/api.mustache @@ -57,7 +57,7 @@ public class {{classname}} { @Deprecated {{/isDeprecated}} public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { - Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}new Object(){{/bodyParam}}; + Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { From 98fb34dcf0db862a523cc08703be4138f7b70668 Mon Sep 17 00:00:00 2001 From: thecrazzymouse Date: Fri, 23 Aug 2019 13:52:48 +0200 Subject: [PATCH 143/370] [BUG] Https protocol schema is not handled correctly in java 11 native code #3729 (#3730) * added getter for schema --- libraries/native/ApiClient.mustache | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libraries/native/ApiClient.mustache b/libraries/native/ApiClient.mustache index ce313c70ef5..6bcad4a2f3f 100644 --- a/libraries/native/ApiClient.mustache +++ b/libraries/native/ApiClient.mustache @@ -252,6 +252,17 @@ public class ApiClient { return scheme + "://" + host + (port == -1 ? "" : ":" + port) + basePath; } + /** + * Set a custom scheme for the target service, for example 'https'. + * + * @param scheme The scheme of the target service + * @return This object. + */ + public ApiClient setScheme(String scheme){ + this.scheme = scheme; + return this; + } + /** * Set a custom request interceptor. * From 76bbea225984e0d7c74736d7c00428533d19756a Mon Sep 17 00:00:00 2001 From: FlorianBruckner Date: Sun, 25 Aug 2019 12:02:36 +0200 Subject: [PATCH 144/370] Two tiny fixes for Java Vertx client (#3683) * two tiny fixes: 1.) ApiClient already defines and configures an objectMapper to not fail on unknown properties, but it is not used when parsing the response. The fix uses the pre-configured object mapper instead of the vertx default one 2.) When an operation has no response (or just ones without content), the accept array passed to ApiClient is emtpy. This makes the null check in ApiClient useless, as it still tries to set a null Accept header, which is refused with an NPE. Amend the check with .length > 0 to catch this case. * update generated client as required by contributor guidelines --- libraries/vertx/ApiClient.mustache | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/vertx/ApiClient.mustache b/libraries/vertx/ApiClient.mustache index 90f4cbcb33b..571a3e4e63f 100644 --- a/libraries/vertx/ApiClient.mustache +++ b/libraries/vertx/ApiClient.mustache @@ -444,7 +444,7 @@ public class ApiClient { updateParamsForAuth(authNames, queryParams, headerParams); - if (accepts != null) { + if (accepts != null && accepts.length > 0) { headerParams.add(HttpHeaders.ACCEPT, selectHeaderAccept(accepts)); } @@ -579,7 +579,7 @@ public class ApiClient { return; } else { try { - resultContent = Json.mapper.readValue(httpResponse.bodyAsString(), returnType); + resultContent = this.objectMapper.readValue(httpResponse.bodyAsString(), returnType); result = Future.succeededFuture(resultContent); } catch (Exception e) { result = ApiException.fail(new DecodeException("Failed to decode:" + e.getMessage(), e)); From 0408658dab852573d109427cb221bf0b458c13fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Thu, 29 Aug 2019 10:40:34 +0200 Subject: [PATCH 145/370] [java-client][java-jaxrs-server][jackson] Add @JsonPropertyOrder to models (#3778) --- model.mustache | 1 + pojo.mustache | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/model.mustache b/model.mustache index 08429bb58de..2194bbfdb39 100644 --- a/model.mustache +++ b/model.mustache @@ -20,6 +20,7 @@ import {{import}}; import java.io.Serializable; {{/serializableModel}} {{#jackson}} +import com.fasterxml.jackson.annotation.JsonPropertyOrder; {{#withXml}} import com.fasterxml.jackson.dataformat.xml.annotation.*; {{/withXml}} diff --git a/pojo.mustache b/pojo.mustache index 6ba1d72e2bc..309a42baced 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -2,6 +2,13 @@ * {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}} */{{#description}} @ApiModel(description = "{{{description}}}"){{/description}} +{{#jackson}} +@JsonPropertyOrder({ +{{#vars}} + {{classname}}.JSON_PROPERTY_{{nameInSnakeCase}}{{^-last}},{{/-last}} +{{/vars}} +}) +{{/jackson}} {{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcelableModel}}implements Parcelable {{#serializableModel}}, Serializable {{/serializableModel}}{{/parcelableModel}}{{^parcelableModel}}{{#serializableModel}}implements Serializable {{/serializableModel}}{{/parcelableModel}}{ {{#serializableModel}} From 28e6821f94a40ed19d3e4a967b4283bd05a6233f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Thu, 29 Aug 2019 17:34:37 +0200 Subject: [PATCH 146/370] [java-client][rest-assured] add jackson support in addition to gson (#3795) --- libraries/rest-assured/ApiClient.mustache | 5 +- .../rest-assured/JacksonObjectMapper.mustache | 64 ++++++++++++++++ libraries/rest-assured/api.mustache | 13 +++- libraries/rest-assured/api_test.mustache | 5 +- libraries/rest-assured/build.gradle.mustache | 18 ++++- libraries/rest-assured/build.sbt.mustache | 7 ++ libraries/rest-assured/pom.mustache | 73 +++++++++++++++++-- 7 files changed, 172 insertions(+), 13 deletions(-) create mode 100644 libraries/rest-assured/JacksonObjectMapper.mustache diff --git a/libraries/rest-assured/ApiClient.mustache b/libraries/rest-assured/ApiClient.mustache index 19ab0fa98c3..1a691ea9482 100644 --- a/libraries/rest-assured/ApiClient.mustache +++ b/libraries/rest-assured/ApiClient.mustache @@ -13,7 +13,8 @@ import java.util.function.Supplier; import static io.restassured.config.ObjectMapperConfig.objectMapperConfig; import static io.restassured.config.RestAssuredConfig.config; -import static {{invokerPackage}}.GsonObjectMapper.gson; +import static {{invokerPackage}}.{{#gson}}GsonObjectMapper.gson{{/gson}}{{#jackson}}JacksonObjectMapper.jackson{{/jackson}}; + {{/fullJavaUtil}} public class ApiClient { @@ -42,7 +43,7 @@ public class ApiClient { public static class Config { private Supplier reqSpecSupplier = () -> new RequestSpecBuilder() {{#basePath}}.setBaseUri(BASE_URI){{/basePath}} - .setConfig(config().objectMapperConfig(objectMapperConfig().defaultObjectMapper(gson()))); + .setConfig(config().objectMapperConfig(objectMapperConfig().defaultObjectMapper({{#gson}}gson(){{/gson}}{{#jackson}}jackson(){{/jackson}}))); /** * Use common specification for all operations diff --git a/libraries/rest-assured/JacksonObjectMapper.mustache b/libraries/rest-assured/JacksonObjectMapper.mustache new file mode 100644 index 00000000000..9d87ce9ef46 --- /dev/null +++ b/libraries/rest-assured/JacksonObjectMapper.mustache @@ -0,0 +1,64 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +{{#threetenbp}} +import org.threeten.bp.*; +{{/threetenbp}} +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.*; +import org.openapitools.jackson.nullable.JsonNullableModule; +{{#java8}} +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{/java8}} +{{#joda}} +import com.fasterxml.jackson.datatype.joda.JodaModule; +{{/joda}} +{{#threetenbp}} +import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; +{{/threetenbp}} + +import io.restassured.internal.mapping.Jackson2Mapper; +import io.restassured.path.json.mapper.factory.Jackson2ObjectMapperFactory; + + +public class JacksonObjectMapper extends Jackson2Mapper { + + private JacksonObjectMapper() { + super(createFactory()); + } + + private static Jackson2ObjectMapperFactory createFactory() { + return (cls, charset) -> { + ObjectMapper mapper = new ObjectMapper(); + mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.setDateFormat(new RFC3339DateFormat()); + {{#java8}} + mapper.registerModule(new JavaTimeModule()); + {{/java8}} + {{#joda}} + mapper.registerModule(new JodaModule()); + {{/joda}} + {{#threetenbp}} + ThreeTenModule module = new ThreeTenModule(); + module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); + module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); + module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); + mapper.registerModule(module); + {{/threetenbp}} + JsonNullableModule jnm = new JsonNullableModule(); + mapper.registerModule(jnm); + return mapper; + }; + } + + public static JacksonObjectMapper jackson() { + return new JacksonObjectMapper(); + } +} \ No newline at end of file diff --git a/libraries/rest-assured/api.mustache b/libraries/rest-assured/api.mustache index 75ea07db60a..db803e8f2e1 100644 --- a/libraries/rest-assured/api.mustache +++ b/libraries/rest-assured/api.mustache @@ -2,7 +2,9 @@ package {{package}}; +{{#gson}} import com.google.gson.reflect.TypeToken; +{{/gson}} {{#imports}}import {{import}}; {{/imports}} @@ -15,6 +17,9 @@ import java.util.Map; import io.restassured.RestAssured; import io.restassured.builder.RequestSpecBuilder; import io.restassured.builder.ResponseSpecBuilder; +{{#jackson}} +import io.restassured.common.mapper.TypeRef; +{{/jackson}} import io.restassured.http.Method; import io.restassured.response.Response; import io.swagger.annotations.*; @@ -24,8 +29,9 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; {{/fullJavaUtil}} +{{#gson}} import {{invokerPackage}}.JSON; - +{{/gson}} import static io.restassured.http.Method.*; @Api(value = "{{{baseName}}}") @@ -139,8 +145,9 @@ public class {{classname}} { * @return {{returnType}} */ public {{{returnType}}} executeAs(Function handler) { - Type type = new TypeToken<{{{returnType}}}>(){}.getType(); - return execute(handler).as(type); + {{#gson}}Type type = new TypeToken<{{{returnType}}}>(){}.getType(); + {{/gson}}{{#jackson}}TypeRef<{{{returnType}}}> type = new TypeRef<{{{returnType}}}>(){}; + {{/jackson}}return execute(handler).as(type); } {{/returnType}} {{#bodyParams}} diff --git a/libraries/rest-assured/api_test.mustache b/libraries/rest-assured/api_test.mustache index 5c17db415e3..74a1c9f7e8c 100644 --- a/libraries/rest-assured/api_test.mustache +++ b/libraries/rest-assured/api_test.mustache @@ -20,7 +20,7 @@ import java.util.Map; {{/fullJavaUtil}} import static io.restassured.config.ObjectMapperConfig.objectMapperConfig; import static io.restassured.config.RestAssuredConfig.config; -import static {{invokerPackage}}.GsonObjectMapper.gson; +import static {{invokerPackage}}.{{#gson}}GsonObjectMapper.gson{{/gson}}{{#jackson}}JacksonObjectMapper.jackson{{/jackson}}; /** * API tests for {{classname}} @@ -33,7 +33,8 @@ public class {{classname}}Test { @Before public void createApi() { api = ApiClient.api(ApiClient.Config.apiConfig().reqSpecSupplier( - () -> new RequestSpecBuilder().setConfig(config().objectMapperConfig(objectMapperConfig().defaultObjectMapper(gson()))) + () -> new RequestSpecBuilder() + .setConfig(config().objectMapperConfig(objectMapperConfig().defaultObjectMapper({{#gson}}gson(){{/gson}}{{#jackson}}jackson(){{/jackson}}))) .addFilter(new ErrorLoggingFilter()) .setBaseUri("{{{basePath}}}"))).{{classVarName}}(); } diff --git a/libraries/rest-assured/build.gradle.mustache b/libraries/rest-assured/build.gradle.mustache index b2d8683d3a4..d67815a76aa 100644 --- a/libraries/rest-assured/build.gradle.mustache +++ b/libraries/rest-assured/build.gradle.mustache @@ -98,8 +98,15 @@ ext { swagger_annotations_version = "1.5.21" rest_assured_version = "4.0.0" junit_version = "4.12" +{{#jackson}} + jackson_version = "{{^threetenbp}}2.9.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" + jackson_databind_version = "{{^threetenbp}}2.9.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" + jackson-databind-nullable-version = 0.2.0 +{{/jackson}} +{{#gson}} gson_version = "2.8.5" gson_fire_version = "1.8.3" +{{/gson}} {{#joda}} jodatime_version = "2.9.9" {{/joda}} @@ -113,10 +120,19 @@ dependencies { compile "io.swagger:swagger-annotations:$swagger_annotations_version" compile "com.google.code.findbugs:jsr305:3.0.2" compile "io.rest-assured:scala-support:$rest_assured_version" +{{#jackson}} + compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + compile "org.openapitools:jackson-databind-nullable:$jackson-databind-nullable-version" +{{/jackson}} +{{#gson}} compile "io.gsonfire:gson-fire:$gson_fire_version" + compile 'com.google.code.gson:gson:$gson_version' +{{/gson}} {{#joda}} compile "joda-time:joda-time:$jodatime_version" - compile 'com.google.code.gson:gson:$gson_version' {{/joda}} {{#threetenbp}} compile "org.threeten:threetenbp:$threetenbp_version" diff --git a/libraries/rest-assured/build.sbt.mustache b/libraries/rest-assured/build.sbt.mustache index d8d817271cb..5f62ab21481 100644 --- a/libraries/rest-assured/build.sbt.mustache +++ b/libraries/rest-assured/build.sbt.mustache @@ -11,8 +11,15 @@ lazy val root = (project in file(".")). libraryDependencies ++= Seq( "io.swagger" % "swagger-annotations" % "1.5.21", "io.rest-assured" % "scala-support" % "4.0.0", +{{#jackson}} + "com.fasterxml.jackson.core" % "jackson-core" % "2.9.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.9" % "compile", +{{/jackson}} +{{#gson}} "com.google.code.gson" % "gson" % "2.8.5", "io.gsonfire" % "gson-fire" % "1.8.3" % "compile", +{{/gson}} {{#joda}} "joda-time" % "joda-time" % "2.9.9" % "compile", {{/joda}} diff --git a/libraries/rest-assured/pom.mustache b/libraries/rest-assured/pom.mustache index f8a8b5a1c88..383403811b8 100644 --- a/libraries/rest-assured/pom.mustache +++ b/libraries/rest-assured/pom.mustache @@ -217,11 +217,13 @@ rest-assured ${rest-assured.version} + {{#gson}} com.google.code.gson gson ${gson-version} + {{/gson}} {{#joda}} joda-time @@ -236,16 +238,69 @@ ${threetenbp-version} {{/threetenbp}} + {{#gson}} io.gsonfire gson-fire ${gson-fire-version} - - com.squareup.okio - okio - ${okio-version} - + {{/gson}} + {{#jackson}} + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-databind-version} + + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + + {{#withXml}} + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson-version} + + {{/withXml}} + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + {{/joda}} + {{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{/java8}} + {{#threetenbp}} + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${jackson-threetenbp-version} + + {{/threetenbp}} + {{/jackson}} + + com.squareup.okio + okio + ${okio-version} + junit @@ -267,6 +322,14 @@ {{#threetenbp}} 1.3.8 {{/threetenbp}} + {{#jackson}} + 2.9.9 + 2.9.9 + 0.2.0 + {{#threetenbp}} + 2.6.4 + {{/threetenbp}} + {{/jackson}} 1.13.0 4.12 From 334fc5675963b066552e654354234d7864a15ea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Fri, 30 Aug 2019 07:51:50 +0200 Subject: [PATCH 147/370] [java] add jackson-databind-nullable dependency to the gradle.build file (#3793) * Add jackson-databind-nullable * Update samples --- build.gradle.mustache | 2 ++ libraries/feign/build.gradle.mustache | 2 ++ libraries/google-api-client/build.gradle.mustache | 2 ++ libraries/jersey2/build.gradle.mustache | 2 ++ libraries/resteasy/build.gradle.mustache | 2 ++ libraries/resttemplate/build.gradle.mustache | 2 ++ libraries/retrofit2/build.gradle.mustache | 2 ++ 7 files changed, 14 insertions(+) diff --git a/build.gradle.mustache b/build.gradle.mustache index c65fb3cea28..9e1142970ee 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -138,6 +138,7 @@ ext { swagger_annotations_version = "1.5.22" jackson_version = "{{^threetenbp}}2.9.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" jackson_databind_version = "{{^threetenbp}}2.9.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" + jackson-databind-nullable-version = "0.2.0" jersey_version = "1.19.4" jodatime_version = "2.9.9" junit_version = "4.12" @@ -152,6 +153,7 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + compile "org.openapitools:jackson-databind-nullable:$jackson-databind-nullable-version" {{#joda}} compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index 982faaa4628..febdd5d11bf 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -122,6 +122,7 @@ ext { swagger_annotations_version = "1.5.22" jackson_version = "2.9.9" jackson_databind_version = "2.9.9" + jackson-databind-nullable-version = "0.2.0" {{#threetenbp}} threepane_version = "2.6.4" {{/threetenbp}} @@ -141,6 +142,7 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + compile "org.openapitools:jackson-databind-nullable:$jackson-databind-nullable-version" {{#joda}} compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache index 84ae616aad6..f01cd1fc70f 100644 --- a/libraries/google-api-client/build.gradle.mustache +++ b/libraries/google-api-client/build.gradle.mustache @@ -122,6 +122,7 @@ ext { swagger_annotations_version = "1.5.22" jackson_version = "2.9.9" jackson_databind_version = "2.9.9" + jackson-databind-nullable-version = "0.2.0" google_api_client_version = "1.23.0" jersey_common_version = "2.25.1" jodatime_version = "2.9.9" @@ -140,6 +141,7 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + compile "org.openapitools:jackson-databind-nullable:$jackson-databind-nullable-version" {{#java8}} compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index 3f192edafd8..fdda0dc7ede 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -121,6 +121,7 @@ ext { swagger_annotations_version = "1.5.22" jackson_version = "2.9.9" jackson_databind_version = "2.9.9" + jackson-databind-nullable-version = "0.2.0" {{#supportJava6}} jersey_version = "2.6" commons_io_version=2.5 @@ -144,6 +145,7 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + compile "org.openapitools:jackson-databind-nullable:$jackson-databind-nullable-version" {{#joda}} compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index 4232b110be4..47b5e19323a 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -121,6 +121,7 @@ ext { swagger_annotations_version = "1.5.22" jackson_version = "2.9.9" jackson_databind_version = "2.9.9" + jackson-databind-nullable-version = "0.2.0" threetenbp_version = "2.6.4" resteasy_version = "3.1.3.Final" {{^java8}} @@ -143,6 +144,7 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$threetenbp_version" + compile "org.openapitools:jackson-databind-nullable:$jackson-databind-nullable-version" {{#java8}} compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index a3a9716286a..e3cd4fa751e 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -122,6 +122,7 @@ ext { swagger_annotations_version = "1.5.22" jackson_version = "2.9.9" jackson_databind_version = "2.9.9" + jackson-databind-nullable-version = "0.2.0" spring_web_version = "4.3.9.RELEASE" jodatime_version = "2.9.9" junit_version = "4.12" @@ -138,6 +139,7 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + compile "org.openapitools:jackson-databind-nullable:$jackson-databind-nullable-version" {{#java8}} compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index 41ba4811340..0d4d1ad995e 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -133,6 +133,7 @@ ext { {{#play26}} jackson_version = "2.9.9" jackson_databind_version = "2.9.9" + jackson-databind-nullable-version = "0.2.0" play_version = "2.6.7" {{/play26}} {{/usePlayWS}} @@ -189,6 +190,7 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + compile "org.openapitools:jackson-databind-nullable:$jackson-databind-nullable-version" compile "com.fasterxml.jackson.datatype:jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}:$jackson_version" {{/usePlayWS}} From c98bf2bd9ba4d6a4e5d7bd073dfcd7ade73fa3e6 Mon Sep 17 00:00:00 2001 From: Quim Muntal Date: Tue, 3 Sep 2019 15:35:49 +0200 Subject: [PATCH 148/370] Support custom git repository (#3757) * add gitHost param to GeneratorSettings and related * parameterize gitHost in READMEs * parameterize gitHost in go.mod * parameterize gitHost in git_push * update petstore samples * run ./bin/utils/export_docs_generators.sh * run meta-codehen.sh * Revert "run meta-codehen.sh" This reverts commit d6d579f6159186531257cdfdd73b9caf9e9ffeba. * Revert "run ./bin/utils/export_docs_generators.sh" This reverts commit 1b81538198d4319fd1b4e97447303e3cc0e8dc99. * Revert "update petstore samples" This reverts commit f513add88396707f6991ae2e4920359583ec88f1. * run ensure-up-to-date --- git_push.sh.mustache | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/git_push.sh.mustache b/git_push.sh.mustache index 8a32e53995d..8b3f689c912 100755 --- a/git_push.sh.mustache +++ b/git_push.sh.mustache @@ -1,11 +1,17 @@ #!/bin/sh # ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ # -# Usage example: /bin/sh ./git_push.sh wing328 openapi-pestore-perl "minor update" +# Usage example: /bin/sh ./git_push.sh wing328 openapi-pestore-perl "minor update" "gitlab.com" git_user_id=$1 git_repo_id=$2 release_note=$3 +git_host=$4 + +if [ "$git_host" = "" ]; then + git_host="{{{gitHost}}}" + echo "[INFO] No command line input provided. Set \$git_host to $git_host" +fi if [ "$git_user_id" = "" ]; then git_user_id="{{{gitUserId}}}" @@ -28,7 +34,7 @@ git init # Adds the files in the local repository and stages them for commit. git add . -# Commits the tracked changes and prepares them to be pushed to a remote repository. +# Commits the tracked changes and prepares them to be pushed to a remote repository. git commit -m "$release_note" # Sets the new remote @@ -37,9 +43,9 @@ if [ "$git_remote" = "" ]; then # git remote not defined if [ "$GIT_TOKEN" = "" ]; then echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment." - git remote add origin https://github.com/${git_user_id}/${git_repo_id}.git + git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git else - git remote add origin https://${git_user_id}:${GIT_TOKEN}@github.com/${git_user_id}/${git_repo_id}.git + git remote add origin https://${git_user_id}:${GIT_TOKEN}@${git_host}/${git_user_id}/${git_repo_id}.git fi fi @@ -47,6 +53,6 @@ fi git pull origin master # Pushes (Forces) the changes in the local repository up to the remote repository -echo "Git pushing to https://github.com/${git_user_id}/${git_repo_id}.git" +echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git" git push origin master 2>&1 | grep -v 'To https' From 3302975b7c99fbdc5b36eee96d308d06d9011e73 Mon Sep 17 00:00:00 2001 From: Benjamin Simpson Date: Sat, 7 Sep 2019 06:36:19 +0200 Subject: [PATCH 149/370] [Java][okhttp-gson] fix failure to deserialize floats (#3846) * fixed bug where nullApi.java would be generated. Instead, generated DefaultApi.java to match the default path /{pathParam} * fix to bug #3157 * update samples --- modelInnerEnum.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modelInnerEnum.mustache b/modelInnerEnum.mustache index 614e260c97f..101870341f5 100644 --- a/modelInnerEnum.mustache +++ b/modelInnerEnum.mustache @@ -56,7 +56,7 @@ @Override public {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException { - {{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{^isNumber}}{{^isInteger}}next{{{dataType}}}(){{/isInteger}}{{/isNumber}}; + {{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = {{#isFloat}}(float){{/isFloat}} jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{^isNumber}}{{^isInteger}}{{#isFloat}}nextDouble{{/isFloat}}{{^isFloat}}next{{{dataType}}}{{/isFloat}}(){{/isInteger}}{{/isNumber}}; return {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}}); } } From cf13a9c223a06ff55640e6f8db574673cfcd630d Mon Sep 17 00:00:00 2001 From: Benjamin Simpson Date: Fri, 13 Sep 2019 09:52:28 +0200 Subject: [PATCH 150/370] updated google-api-client version from 1.23.0 to 1.30.2. Bugfix #3625 (#3882) --- libraries/google-api-client/pom.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index be8c28602dd..76ddf4325e2 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -304,7 +304,7 @@ UTF-8 1.5.22 - 1.23.0 + 1.30.2 2.25.1 2.9.9 2.9.9 From c5decfcf7870da2380eee16f598bf00b90b463d9 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Tue, 24 Sep 2019 13:56:59 +0800 Subject: [PATCH 151/370] Fix jackson-databind security issue (#3945) * fix jackson security issue * update groovy petstore sample --- build.gradle.mustache | 4 ++-- libraries/feign/build.gradle.mustache | 4 ++-- libraries/feign/build.sbt.mustache | 6 +++--- libraries/feign/pom.mustache | 4 ++-- libraries/google-api-client/build.gradle.mustache | 4 ++-- libraries/google-api-client/build.sbt.mustache | 6 +++--- libraries/google-api-client/pom.mustache | 4 ++-- libraries/jersey2/build.gradle.mustache | 4 ++-- libraries/jersey2/build.sbt.mustache | 6 +++--- libraries/jersey2/pom.mustache | 4 ++-- libraries/resteasy/build.gradle.mustache | 4 ++-- libraries/resteasy/build.sbt.mustache | 6 +++--- libraries/resteasy/pom.mustache | 4 ++-- libraries/resttemplate/build.gradle.mustache | 4 ++-- libraries/retrofit2/build.gradle.mustache | 6 +++--- libraries/retrofit2/build.sbt.mustache | 12 ++++++------ libraries/retrofit2/pom.mustache | 6 +++--- libraries/vertx/build.gradle.mustache | 4 ++-- libraries/vertx/pom.mustache | 4 ++-- libraries/webclient/pom.mustache | 4 ++-- 20 files changed, 50 insertions(+), 50 deletions(-) diff --git a/build.gradle.mustache b/build.gradle.mustache index 9e1142970ee..99d255c54db 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -136,8 +136,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "{{^threetenbp}}2.9.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" - jackson_databind_version = "{{^threetenbp}}2.9.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" + jackson_version = "{{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" + jackson_databind_version = "{{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" jackson-databind-nullable-version = "0.2.0" jersey_version = "1.19.4" jodatime_version = "2.9.9" diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index febdd5d11bf..a92022e83ae 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -120,8 +120,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.9.9" - jackson_databind_version = "2.9.9" + jackson_version = "2.9.10" + jackson_databind_version = "2.9.10" jackson-databind-nullable-version = "0.2.0" {{#threetenbp}} threepane_version = "2.6.4" diff --git a/libraries/feign/build.sbt.mustache b/libraries/feign/build.sbt.mustache index 946b3195611..04091222022 100644 --- a/libraries/feign/build.sbt.mustache +++ b/libraries/feign/build.sbt.mustache @@ -14,9 +14,9 @@ lazy val root = (project in file(".")). "io.github.openfeign" % "feign-jackson" % "{{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", "io.github.openfeign" % "feign-slf4j" % "{{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", "io.github.openfeign.form" % "feign-form" % "2.1.0" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.9.9" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.9" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.9.10" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.10" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10" % "compile", "com.fasterxml.jackson.datatype" % "jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}" % "2.9.9" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4" % "compile", "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index 1e9edaec8c0..ef60c22df43 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -314,9 +314,9 @@ 1.5.21 {{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}} 2.1.0 - 2.9.9 + 2.9.10 0.2.0 - 2.9.9 + 2.9.10 {{#threetenbp}} 2.6.4 {{/threetenbp}} diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache index f01cd1fc70f..4471072ec2f 100644 --- a/libraries/google-api-client/build.gradle.mustache +++ b/libraries/google-api-client/build.gradle.mustache @@ -120,8 +120,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.9.9" - jackson_databind_version = "2.9.9" + jackson_version = "2.9.10" + jackson_databind_version = "2.9.10" jackson-databind-nullable-version = "0.2.0" google_api_client_version = "1.23.0" jersey_common_version = "2.25.1" diff --git a/libraries/google-api-client/build.sbt.mustache b/libraries/google-api-client/build.sbt.mustache index 48f28b25d1b..3dea3928279 100644 --- a/libraries/google-api-client/build.sbt.mustache +++ b/libraries/google-api-client/build.sbt.mustache @@ -12,9 +12,9 @@ lazy val root = (project in file(".")). "io.swagger" % "swagger-annotations" % "1.5.22", "com.google.api-client" % "google-api-client" % "1.23.0", "org.glassfish.jersey.core" % "jersey-common" % "2.25.1", - "com.fasterxml.jackson.core" % "jackson-core" % "2.9.9" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.9" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.9.10" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.10" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10" % "compile", {{#withXml}} "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.9.9" % "compile", {{/withXml}} diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index 76ddf4325e2..8bafe1ea9a4 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -306,8 +306,8 @@ 1.5.22 1.30.2 2.25.1 - 2.9.9 - 2.9.9 + 2.9.10 + 2.9.10 0.2.0 {{#joda}} 2.9.9 diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index fdda0dc7ede..588239f5c88 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -119,8 +119,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.9.9" - jackson_databind_version = "2.9.9" + jackson_version = "2.9.10" + jackson_databind_version = "2.9.10" jackson-databind-nullable-version = "0.2.0" {{#supportJava6}} jersey_version = "2.6" diff --git a/libraries/jersey2/build.sbt.mustache b/libraries/jersey2/build.sbt.mustache index d5d69065495..ef2e32af36e 100644 --- a/libraries/jersey2/build.sbt.mustache +++ b/libraries/jersey2/build.sbt.mustache @@ -13,9 +13,9 @@ lazy val root = (project in file(".")). "org.glassfish.jersey.core" % "jersey-client" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, "org.glassfish.jersey.media" % "jersey-media-multipart" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, "org.glassfish.jersey.media" % "jersey-media-json-jackson" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, - "com.fasterxml.jackson.core" % "jackson-core" % "2.9.9" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.9" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.9.10" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.10" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10" % "compile", {{#joda}} "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.9" % "compile", {{/joda}} diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index d72e0b1fe81..621228c2a7a 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -360,8 +360,8 @@ 2.5 3.6 {{/supportJava6}} - 2.9.9 - 2.9.9 + 2.9.10 + 2.9.10 0.2.0 {{#threetenbp}} 2.6.4 diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index 47b5e19323a..1c133a74353 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -119,8 +119,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.9.9" - jackson_databind_version = "2.9.9" + jackson_version = "2.9.10" + jackson_databind_version = "2.9.10" jackson-databind-nullable-version = "0.2.0" threetenbp_version = "2.6.4" resteasy_version = "3.1.3.Final" diff --git a/libraries/resteasy/build.sbt.mustache b/libraries/resteasy/build.sbt.mustache index 4f67eb38823..0af339a0da6 100644 --- a/libraries/resteasy/build.sbt.mustache +++ b/libraries/resteasy/build.sbt.mustache @@ -13,9 +13,9 @@ lazy val root = (project in file(".")). "org.jboss.resteasy" % "resteasy-client" % "3.1.3.Final" % "compile", "org.jboss.resteasy" % "resteasy-multipart-provider" % "3.1.3.Final" % "compile", "org.jboss.resteasy" % "resteasy-jackson2-provider" % "3.1.3.Final" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.9.9" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.9" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.9.10" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.10" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4" % "compile", {{#java8}} "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.9" % "compile", diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index d190566bac5..4318c37628a 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -294,8 +294,8 @@ UTF-8 1.5.22 3.1.3.Final - 2.9.9 - 2.9.9 + 2.9.10 + 2.9.10 0.2.0 2.6.4 {{^java8}} diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index e3cd4fa751e..1815ab926e1 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -120,8 +120,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.9.9" - jackson_databind_version = "2.9.9" + jackson_version = "2.9.10" + jackson_databind_version = "2.9.10" jackson-databind-nullable-version = "0.2.0" spring_web_version = "4.3.9.RELEASE" jodatime_version = "2.9.9" diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index 0d4d1ad995e..cf02f243950 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -127,12 +127,12 @@ ext { play_version = "2.4.11" {{/play24}} {{#play25}} - jackson_version = "2.9.9" + jackson_version = "2.9.10" play_version = "2.5.14" {{/play25}} {{#play26}} - jackson_version = "2.9.9" - jackson_databind_version = "2.9.9" + jackson_version = "2.9.10" + jackson_databind_version = "2.9.10" jackson-databind-nullable-version = "0.2.0" play_version = "2.6.7" {{/play26}} diff --git a/libraries/retrofit2/build.sbt.mustache b/libraries/retrofit2/build.sbt.mustache index 21b00d3b91e..78f7e5786af 100644 --- a/libraries/retrofit2/build.sbt.mustache +++ b/libraries/retrofit2/build.sbt.mustache @@ -23,16 +23,16 @@ lazy val root = (project in file(".")). {{/play24}} {{#play25}} "com.typesafe.play" % "play-java-ws_2.11" % "2.5.15" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.9.9" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.9" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.9.10" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.10" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10" % "compile", {{/play25}} {{#play26}} "com.typesafe.play" % "play-ahc-ws_2.12" % "2.6.7" % "compile", "javax.validation" % "validation-api" % "1.1.0.Final" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.9.9" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.9" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.9.10" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.10" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10" % "compile", {{/play26}} "com.squareup.retrofit2" % "converter-jackson" % "2.3.0" % "compile", {{/usePlayWS}} diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index b35ffe66264..8bca88942d3 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -375,17 +375,17 @@ 1.8.3 1.5.22 {{#usePlayWS}} - 2.9.9 + 2.9.10 {{#play24}} 2.6.6 2.4.11 {{/play24}} {{#play25}} - 2.9.9 + 2.9.10 2.5.15 {{/play25}} {{#play26}} - 2.9.9 + 2.9.10 2.6.7 {{/play26}} 0.2.0 diff --git a/libraries/vertx/build.gradle.mustache b/libraries/vertx/build.gradle.mustache index cf71f237698..20aa961eaaf 100644 --- a/libraries/vertx/build.gradle.mustache +++ b/libraries/vertx/build.gradle.mustache @@ -28,8 +28,8 @@ task execute(type:JavaExec) { ext { swagger_annotations_version = "1.5.21" - jackson_version = "{{^threetenbp}}2.9.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" - jackson_databind_version = "{{^threetenbp}}2.9.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" + jackson_version = "{{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" + jackson_databind_version = "{{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" vertx_version = "3.4.2" junit_version = "4.12" } diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache index a2fd9f30ebe..17d2c1261a9 100644 --- a/libraries/vertx/pom.mustache +++ b/libraries/vertx/pom.mustache @@ -289,8 +289,8 @@ UTF-8 3.4.2 1.5.22 - {{^threetenbp}}2.9.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} - {{^threetenbp}}2.9.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} + {{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} + {{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} 0.2.0 4.12 diff --git a/libraries/webclient/pom.mustache b/libraries/webclient/pom.mustache index 4fbf5d9cf1d..c8651f58c58 100644 --- a/libraries/webclient/pom.mustache +++ b/libraries/webclient/pom.mustache @@ -143,8 +143,8 @@ UTF-8 1.5.22 5.0.7.RELEASE - 2.9.9 - 2.9.9 + 2.9.10 + 2.9.10 0.2.0 4.12 3.1.8.RELEASE From 5b76b3d6fc00b6ab7519a2277af1e9f02006cbc1 Mon Sep 17 00:00:00 2001 From: Davide Maestroni Date: Fri, 27 Sep 2019 10:36:04 +0200 Subject: [PATCH 152/370] Fix issue3635 (#3948) * fixed Feign template * regenerated Feign example * update java feign petstore sample --- libraries/feign/EncodingUtils.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/feign/EncodingUtils.mustache b/libraries/feign/EncodingUtils.mustache index 6bf2a0e4bfb..705eb6aa9d3 100644 --- a/libraries/feign/EncodingUtils.mustache +++ b/libraries/feign/EncodingUtils.mustache @@ -77,7 +77,7 @@ public final class EncodingUtils { return null; } try { - return URLEncoder.encode(parameter.toString(), "UTF-8"); + return URLEncoder.encode(parameter.toString(), "UTF-8").replaceAll("\\+", "%20"); } catch (UnsupportedEncodingException e) { // Should never happen, UTF-8 is always supported throw new RuntimeException(e); From f87ff4f5d4878ac0bc094879e48bf305c2a4b562 Mon Sep 17 00:00:00 2001 From: Michael Walser Date: Tue, 1 Oct 2019 07:50:21 +0200 Subject: [PATCH 153/370] [java] Don't import oltu when not necessary (#3950) --- libraries/feign/ApiClient.mustache | 3 +++ libraries/retrofit/ApiClient.mustache | 3 +++ libraries/retrofit2/ApiClient.mustache | 2 ++ 3 files changed, 8 insertions(+) diff --git a/libraries/feign/ApiClient.mustache b/libraries/feign/ApiClient.mustache index 9df586c08cb..0f826eb387b 100644 --- a/libraries/feign/ApiClient.mustache +++ b/libraries/feign/ApiClient.mustache @@ -3,8 +3,11 @@ package {{invokerPackage}}; import java.util.LinkedHashMap; import java.util.Map; +{{#hasOAuthMethods}} import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; +{{/hasOAuthMethods}} + {{#threetenbp}} import org.threeten.bp.*; {{/threetenbp}} diff --git a/libraries/retrofit/ApiClient.mustache b/libraries/retrofit/ApiClient.mustache index 45327813288..c3fd7802393 100644 --- a/libraries/retrofit/ApiClient.mustache +++ b/libraries/retrofit/ApiClient.mustache @@ -7,8 +7,11 @@ import java.lang.reflect.Type; import java.util.LinkedHashMap; import java.util.Map; +{{#hasOAuthMethods}} import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; +{{/hasOAuthMethods}} + import org.joda.time.DateTime; import org.joda.time.LocalDate; import org.joda.time.format.DateTimeFormatter; diff --git a/libraries/retrofit2/ApiClient.mustache b/libraries/retrofit2/ApiClient.mustache index e5dfb17180f..40ab42d2efe 100644 --- a/libraries/retrofit2/ApiClient.mustache +++ b/libraries/retrofit2/ApiClient.mustache @@ -7,8 +7,10 @@ import okhttp3.Interceptor; import okhttp3.OkHttpClient; import okhttp3.RequestBody; import okhttp3.ResponseBody; +{{#hasOAuthMethods}} import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; +{{/hasOAuthMethods}} {{#joda}} import org.joda.time.format.DateTimeFormatter; {{/joda}} From acaa197c21c3ac6b3d377661099d4e1cc07aee08 Mon Sep 17 00:00:00 2001 From: Slavek Kabrda Date: Mon, 7 Oct 2019 11:50:56 +0200 Subject: [PATCH 154/370] [java][client] Fix regression in Java XML serialization. Fixes #4014 (#4023) * Fix regression in Java XML serialization. Fixes #4014 * Also move JSON_PROPERTY_* declaration --- pojo.mustache | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pojo.mustache b/pojo.mustache index 309a42baced..27bbed28420 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -26,6 +26,12 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela {{/mostInnerItems}} {{/isContainer}} {{/isEnum}} + {{#gson}} + public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}"; + {{/gson}} + {{#jackson}} + public static final String JSON_PROPERTY_{{nameInSnakeCase}} = "{{baseName}}"; + {{/jackson}} {{#withXml}} {{#isXmlAttribute}} @XmlAttribute(name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") @@ -48,12 +54,8 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela {{/isXmlAttribute}} {{/withXml}} {{#gson}} - public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}"; @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}}) {{/gson}} - {{#jackson}} - public static final String JSON_PROPERTY_{{nameInSnakeCase}} = "{{baseName}}"; - {{/jackson}} {{#vendorExtensions.isJacksonOptionalNullable}} {{#isContainer}} private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined(); From d2269adcb61af947a2e5cf0eeea1c7fceb1ee805 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 9 Oct 2019 15:16:22 +0800 Subject: [PATCH 155/370] Fix readonly with isReadOnly (#4102) * fix readonly * update samples --- pojo_doc.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pojo_doc.mustache b/pojo_doc.mustache index f297c5bc9f5..38a52e44eb5 100644 --- a/pojo_doc.mustache +++ b/pojo_doc.mustache @@ -4,7 +4,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -{{#vars}}**{{name}}** | {{#isEnum}}[**{{datatypeWithEnum}}**](#{{datatypeWithEnum}}){{/isEnum}}{{^isEnum}}{{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}}{{/isEnum}} | {{description}} | {{^required}} [optional]{{/required}}{{#readOnly}} [readonly]{{/readOnly}} +{{#vars}}**{{name}}** | {{#isEnum}}[**{{datatypeWithEnum}}**](#{{datatypeWithEnum}}){{/isEnum}}{{^isEnum}}{{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}}{{/isEnum}} | {{description}} | {{^required}} [optional]{{/required}}{{#isReadOnly}} [readonly]{{/isReadOnly}} {{/vars}} {{#vars}}{{#isEnum}} From 1287c8d33fcc954241531f95c0d2006858051f36 Mon Sep 17 00:00:00 2001 From: Thomas Joeissient Date: Thu, 10 Oct 2019 09:18:29 -0400 Subject: [PATCH 156/370] Make Resttemplate thread safe by using the withHttpInfo pattern used by many other generated clients (#4049) --- libraries/resttemplate/ApiClient.mustache | 34 ++------------ libraries/resttemplate/api.mustache | 56 +++++++++++++++++++---- 2 files changed, 52 insertions(+), 38 deletions(-) diff --git a/libraries/resttemplate/ApiClient.mustache b/libraries/resttemplate/ApiClient.mustache index 43078344343..df21df17b02 100644 --- a/libraries/resttemplate/ApiClient.mustache +++ b/libraries/resttemplate/ApiClient.mustache @@ -99,9 +99,6 @@ public class ApiClient { private Map authentications; - private HttpStatus statusCode; - private MultiValueMap responseHeaders; - private DateFormat dateFormat; public ApiClient() { @@ -154,22 +151,6 @@ public class ApiClient { return this; } - /** - * Gets the status code of the previous request - * @return HttpStatus the status code - */ - public HttpStatus getStatusCode() { - return statusCode; - } - - /** - * Gets the response headers of the previous request - * @return MultiValueMap a map of response headers - */ - public MultiValueMap getResponseHeaders() { - return responseHeaders; - } - /** * Get authentications (key: authentication name, value: authentication). * @return Map the currently configured authentication types @@ -580,9 +561,9 @@ public class ApiClient { * @param contentType The request's Content-Type header * @param authNames The authentications to apply * @param returnType The return type into which to deserialize the response - * @return The response body in chosen type + * @return ResponseEntity<T> The response of the chosen type */ - public T invokeAPI(String path, HttpMethod method, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { + public ResponseEntity invokeAPI(String path, HttpMethod method, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { updateParamsForAuth(authNames, queryParams, headerParams); final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(path); @@ -624,16 +605,11 @@ public class ApiClient { ResponseEntity responseEntity = restTemplate.exchange(requestEntity, returnType); - statusCode = responseEntity.getStatusCode(); - responseHeaders = responseEntity.getHeaders(); - - if (responseEntity.getStatusCode() == HttpStatus.NO_CONTENT) { - return null; - } else if (responseEntity.getStatusCode().is2xxSuccessful()) { - return responseEntity.getBody(); + if (responseEntity.getStatusCode().is2xxSuccessful()) { + return responseEntity; } else { // The error handler built into the RestTemplate should handle 400 and 500 series errors. - throw new RestClientException("API returned " + statusCode + " and it wasn't handled by the RestTemplate error handler"); + throw new RestClientException("API returned " + responseEntity.getStatusCode() + " and it wasn't handled by the RestTemplate error handler"); } } diff --git a/libraries/resttemplate/api.mustache b/libraries/resttemplate/api.mustache index 79cdcd51ac1..61a0d527204 100644 --- a/libraries/resttemplate/api.mustache +++ b/libraries/resttemplate/api.mustache @@ -25,6 +25,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; {{>generatedAnnotation}} @Component("{{package}}.{{classname}}") @@ -53,16 +54,53 @@ public class {{classname}} { /** * {{summary}} * {{notes}} -{{#responses}} *

{{code}}{{#message}} - {{message}}{{/message}} -{{/responses}}{{#allParams}} * @param {{paramName}} {{description}}{{^description}}The {{paramName}} parameter{{/description}} -{{/allParams}}{{#returnType}} * @return {{returnType}} -{{/returnType}} * @throws RestClientException if an error occurs while attempting to invoke the API -{{#externalDocs}} - * {{description}} - * @see {{summary}} Documentation -{{/externalDocs}} + {{#responses}} + *

{{code}}{{#message}} - {{message}}{{/message}} + {{/responses}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + {{#returnType}} + * @return {{returnType}} + {{/returnType}} + * @throws RestClientException if an error occurs while attempting to invoke the API + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { + {{#returnType}} + return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}).getBody(); + {{/returnType}} + {{^returnType}} + {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{/returnType}} + } + + /** + * {{summary}} + * {{notes}} + {{#responses}} + *

{{code}}{{#message}} - {{message}}{{/message}} + {{/responses}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @return ResponseEntity<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + * @throws RestClientException if an error occurs while attempting to invoke the API + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public ResponseEntity<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { Object postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set @@ -102,7 +140,7 @@ public class {{classname}} { String[] authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; {{#returnType}}ParameterizedTypeReference<{{{returnType}}}> returnType = new ParameterizedTypeReference<{{{returnType}}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference returnType = new ParameterizedTypeReference() {};{{/returnType}} - {{#returnType}}return {{/returnType}}apiClient.invokeAPI(path, HttpMethod.{{httpMethod}}, queryParams, postBody, headerParams, formParams, accept, contentType, authNames, returnType); + return apiClient.invokeAPI(path, HttpMethod.{{httpMethod}}, queryParams, postBody, headerParams, formParams, accept, contentType, authNames, returnType); } {{/operation}} } From 758801857d7a7dcd91dc1c8a13670cf23b51b3d8 Mon Sep 17 00:00:00 2001 From: gurumeditator Date: Thu, 10 Oct 2019 09:34:40 -0400 Subject: [PATCH 157/370] Added new discriminator RawName property to preserve declared discriminator for @JsonTypeInfo annotations (#3320) --- typeInfoAnnotation.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typeInfoAnnotation.mustache b/typeInfoAnnotation.mustache index 8e4b33b7848..4676618e320 100644 --- a/typeInfoAnnotation.mustache +++ b/typeInfoAnnotation.mustache @@ -1,6 +1,6 @@ {{#jackson}} -@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "{{{discriminatorName}}}", visible = true) +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "{{{discriminator.propertyRawName}}}", visible = true) @JsonSubTypes({ {{#discriminator.mappedModels}} @JsonSubTypes.Type(value = {{modelName}}.class, name = "{{^vendorExtensions.x-discriminator-value}}{{mappingName}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}"), From ff5e875afd83339c74a7cb34a6f9b025ee8a1211 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 11 Oct 2019 00:51:20 +0800 Subject: [PATCH 158/370] Rename property name from propertyRawName to propertyBaseName (#4124) * rename property in codegen discriminator * better code format --- typeInfoAnnotation.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typeInfoAnnotation.mustache b/typeInfoAnnotation.mustache index 4676618e320..a8ab10768e6 100644 --- a/typeInfoAnnotation.mustache +++ b/typeInfoAnnotation.mustache @@ -1,6 +1,6 @@ {{#jackson}} -@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "{{{discriminator.propertyRawName}}}", visible = true) +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "{{{discriminator.propertyBaseName}}}", visible = true) @JsonSubTypes({ {{#discriminator.mappedModels}} @JsonSubTypes.Type(value = {{modelName}}.class, name = "{{^vendorExtensions.x-discriminator-value}}{{mappingName}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}"), From 6ae6001f3f1d0fc6f96a74ee0a4655bb04d2296d Mon Sep 17 00:00:00 2001 From: gurumeditator Date: Mon, 14 Oct 2019 10:25:50 -0400 Subject: [PATCH 159/370] [Java] fix jackson-databind-nullable version variable due to Gradle Incompatibility (Template Update) (#4148) * Replaced dashes with underscores in build.gradle files. * Updated mustache template files --- build.gradle.mustache | 4 ++-- libraries/feign/build.gradle.mustache | 4 ++-- libraries/google-api-client/build.gradle.mustache | 4 ++-- libraries/jersey2/build.gradle.mustache | 4 ++-- libraries/rest-assured/build.gradle.mustache | 4 ++-- libraries/resteasy/build.gradle.mustache | 4 ++-- libraries/resttemplate/build.gradle.mustache | 4 ++-- libraries/retrofit2/build.gradle.mustache | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/build.gradle.mustache b/build.gradle.mustache index 99d255c54db..70462ccbd8e 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -138,7 +138,7 @@ ext { swagger_annotations_version = "1.5.22" jackson_version = "{{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" jackson_databind_version = "{{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" - jackson-databind-nullable-version = "0.2.0" + jackson_databind_nullable_version = "0.2.0" jersey_version = "1.19.4" jodatime_version = "2.9.9" junit_version = "4.12" @@ -153,7 +153,7 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" - compile "org.openapitools:jackson-databind-nullable:$jackson-databind-nullable-version" + compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" {{#joda}} compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index a92022e83ae..34a2bb98015 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -122,7 +122,7 @@ ext { swagger_annotations_version = "1.5.22" jackson_version = "2.9.10" jackson_databind_version = "2.9.10" - jackson-databind-nullable-version = "0.2.0" + jackson_databind_nullable_version = "0.2.0" {{#threetenbp}} threepane_version = "2.6.4" {{/threetenbp}} @@ -142,7 +142,7 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" - compile "org.openapitools:jackson-databind-nullable:$jackson-databind-nullable-version" + compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" {{#joda}} compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache index 4471072ec2f..d42c3e13899 100644 --- a/libraries/google-api-client/build.gradle.mustache +++ b/libraries/google-api-client/build.gradle.mustache @@ -122,7 +122,7 @@ ext { swagger_annotations_version = "1.5.22" jackson_version = "2.9.10" jackson_databind_version = "2.9.10" - jackson-databind-nullable-version = "0.2.0" + jackson_databind_nullable_version = "0.2.0" google_api_client_version = "1.23.0" jersey_common_version = "2.25.1" jodatime_version = "2.9.9" @@ -141,7 +141,7 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" - compile "org.openapitools:jackson-databind-nullable:$jackson-databind-nullable-version" + compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" {{#java8}} compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index 588239f5c88..c86178e7d04 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -121,7 +121,7 @@ ext { swagger_annotations_version = "1.5.22" jackson_version = "2.9.10" jackson_databind_version = "2.9.10" - jackson-databind-nullable-version = "0.2.0" + jackson_databind_nullable_version = "0.2.0" {{#supportJava6}} jersey_version = "2.6" commons_io_version=2.5 @@ -145,7 +145,7 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" - compile "org.openapitools:jackson-databind-nullable:$jackson-databind-nullable-version" + compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" {{#joda}} compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} diff --git a/libraries/rest-assured/build.gradle.mustache b/libraries/rest-assured/build.gradle.mustache index d67815a76aa..726c343301e 100644 --- a/libraries/rest-assured/build.gradle.mustache +++ b/libraries/rest-assured/build.gradle.mustache @@ -101,7 +101,7 @@ ext { {{#jackson}} jackson_version = "{{^threetenbp}}2.9.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" jackson_databind_version = "{{^threetenbp}}2.9.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" - jackson-databind-nullable-version = 0.2.0 + jackson_databind_nullable_version = 0.2.0 {{/jackson}} {{#gson}} gson_version = "2.8.5" @@ -125,7 +125,7 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" - compile "org.openapitools:jackson-databind-nullable:$jackson-databind-nullable-version" + compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" {{/jackson}} {{#gson}} compile "io.gsonfire:gson-fire:$gson_fire_version" diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index 1c133a74353..930ae737fdc 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -121,7 +121,7 @@ ext { swagger_annotations_version = "1.5.22" jackson_version = "2.9.10" jackson_databind_version = "2.9.10" - jackson-databind-nullable-version = "0.2.0" + jackson_databind_nullable_version = "0.2.0" threetenbp_version = "2.6.4" resteasy_version = "3.1.3.Final" {{^java8}} @@ -144,7 +144,7 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$threetenbp_version" - compile "org.openapitools:jackson-databind-nullable:$jackson-databind-nullable-version" + compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" {{#java8}} compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index 1815ab926e1..06700890574 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -122,7 +122,7 @@ ext { swagger_annotations_version = "1.5.22" jackson_version = "2.9.10" jackson_databind_version = "2.9.10" - jackson-databind-nullable-version = "0.2.0" + jackson_databind_nullable_version = "0.2.0" spring_web_version = "4.3.9.RELEASE" jodatime_version = "2.9.9" junit_version = "4.12" @@ -139,7 +139,7 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" - compile "org.openapitools:jackson-databind-nullable:$jackson-databind-nullable-version" + compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" {{#java8}} compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index cf02f243950..85aa12d6cca 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -133,7 +133,7 @@ ext { {{#play26}} jackson_version = "2.9.10" jackson_databind_version = "2.9.10" - jackson-databind-nullable-version = "0.2.0" + jackson_databind_nullable_version = "0.2.0" play_version = "2.6.7" {{/play26}} {{/usePlayWS}} @@ -190,7 +190,7 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" - compile "org.openapitools:jackson-databind-nullable:$jackson-databind-nullable-version" + compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" compile "com.fasterxml.jackson.datatype:jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}:$jackson_version" {{/usePlayWS}} From 70ecd333d18c54e8362c9d9d5249685d1f956aed Mon Sep 17 00:00:00 2001 From: Jochen Schalanda Date: Sat, 19 Oct 2019 09:08:56 +0200 Subject: [PATCH 160/370] Update to jackson-datatype-threetenbp 2.9.10 (#4176) * Update to jackson-datatype-threetenbp 2.9.10 * Update to ThreeTen BP 1.4.0 * Fix import and usage of org.threeten.bp.DateTimeUtils * Refresh samples --- CustomInstantDeserializer.mustache | 4 ++-- build.gradle.mustache | 4 ++-- libraries/feign/build.gradle.mustache | 4 ++-- libraries/feign/build.sbt.mustache | 4 ++-- libraries/feign/pom.mustache | 2 +- libraries/google-api-client/build.gradle.mustache | 2 +- libraries/google-api-client/build.sbt.mustache | 8 ++++---- libraries/google-api-client/pom.mustache | 2 +- libraries/jersey2/build.gradle.mustache | 2 +- libraries/jersey2/build.sbt.mustache | 6 +++--- libraries/jersey2/pom.mustache | 2 +- libraries/okhttp-gson/build.gradle.mustache | 2 +- libraries/okhttp-gson/build.sbt.mustache | 2 +- libraries/okhttp-gson/pom.mustache | 2 +- libraries/rest-assured/build.gradle.mustache | 6 +++--- libraries/rest-assured/build.sbt.mustache | 2 +- libraries/rest-assured/pom.mustache | 8 ++++---- libraries/resteasy/build.gradle.mustache | 2 +- libraries/resteasy/build.sbt.mustache | 6 +++--- libraries/resteasy/pom.mustache | 2 +- libraries/resttemplate/build.gradle.mustache | 2 +- libraries/resttemplate/pom.mustache | 6 +++--- libraries/retrofit/build.gradle.mustache | 2 +- libraries/retrofit/build.sbt.mustache | 2 +- libraries/retrofit/pom.mustache | 2 +- libraries/retrofit2/build.gradle.mustache | 2 +- libraries/retrofit2/build.sbt.mustache | 2 +- libraries/retrofit2/pom.mustache | 2 +- libraries/vertx/build.gradle.mustache | 4 ++-- libraries/vertx/pom.mustache | 4 ++-- 30 files changed, 50 insertions(+), 50 deletions(-) diff --git a/CustomInstantDeserializer.mustache b/CustomInstantDeserializer.mustache index dbf4d30e117..5ebea810e1d 100644 --- a/CustomInstantDeserializer.mustache +++ b/CustomInstantDeserializer.mustache @@ -5,12 +5,12 @@ import com.fasterxml.jackson.core.JsonTokenId; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.datatype.threetenbp.DateTimeUtils; import com.fasterxml.jackson.datatype.threetenbp.DecimalUtils; import com.fasterxml.jackson.datatype.threetenbp.deser.ThreeTenDateTimeDeserializerBase; import com.fasterxml.jackson.datatype.threetenbp.function.BiFunction; import com.fasterxml.jackson.datatype.threetenbp.function.Function; import org.threeten.bp.DateTimeException; +import org.threeten.bp.DateTimeUtils; import org.threeten.bp.Instant; import org.threeten.bp.OffsetDateTime; import org.threeten.bp.ZoneId; @@ -205,7 +205,7 @@ public class CustomInstantDeserializer private ZoneId getZone(DeserializationContext context) { // Instants are always in UTC, so don't waste compute cycles - return (_valueClass == Instant.class) ? null : DateTimeUtils.timeZoneToZoneId(context.getTimeZone()); + return (_valueClass == Instant.class) ? null : DateTimeUtils.toZoneId(context.getTimeZone()); } private static class FromIntegerArguments { diff --git a/build.gradle.mustache b/build.gradle.mustache index 70462ccbd8e..2fa65868357 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -136,8 +136,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "{{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" - jackson_databind_version = "{{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" + jackson_version = "2.9.10" + jackson_databind_version = "2.9.10" jackson_databind_nullable_version = "0.2.0" jersey_version = "1.19.4" jodatime_version = "2.9.9" diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index 34a2bb98015..d652ecc8e9d 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -124,7 +124,7 @@ ext { jackson_databind_version = "2.9.10" jackson_databind_nullable_version = "0.2.0" {{#threetenbp}} - threepane_version = "2.6.4" + jackson_threetenbp_version = "2.9.10" {{/threetenbp}} feign_version = "{{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" feign_form_version = "2.1.0" @@ -150,7 +150,7 @@ dependencies { compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$threepane_version" + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threetenbp_version" {{/threetenbp}} compile "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version" compile "com.brsanthu:migbase64:2.2" diff --git a/libraries/feign/build.sbt.mustache b/libraries/feign/build.sbt.mustache index 04091222022..c0622eefdc5 100644 --- a/libraries/feign/build.sbt.mustache +++ b/libraries/feign/build.sbt.mustache @@ -17,8 +17,8 @@ lazy val root = (project in file(".")). "com.fasterxml.jackson.core" % "jackson-core" % "2.9.10" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.10" % "compile", "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10" % "compile", - "com.fasterxml.jackson.datatype" % "jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}" % "2.9.9" % "compile", - "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}" % "2.9.10" % "compile", + "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", "com.brsanthu" % "migbase64" % "2.2" % "compile", "junit" % "junit" % "4.12" % "test", diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index ef60c22df43..ffa03e01b1c 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -318,7 +318,7 @@ 0.2.0 2.9.10 {{#threetenbp}} - 2.6.4 + 2.9.10 {{/threetenbp}} 4.12 1.0.0 diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache index d42c3e13899..9c8d7a8d30e 100644 --- a/libraries/google-api-client/build.gradle.mustache +++ b/libraries/google-api-client/build.gradle.mustache @@ -128,7 +128,7 @@ ext { jodatime_version = "2.9.9" junit_version = "4.12" {{#threetenbp}} - jackson_threeten_version = "2.6.4" + jackson_threeten_version = "2.9.10" {{/threetenbp}} } diff --git a/libraries/google-api-client/build.sbt.mustache b/libraries/google-api-client/build.sbt.mustache index 3dea3928279..2c1ff450e94 100644 --- a/libraries/google-api-client/build.sbt.mustache +++ b/libraries/google-api-client/build.sbt.mustache @@ -16,16 +16,16 @@ lazy val root = (project in file(".")). "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.10" % "compile", "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10" % "compile", {{#withXml}} - "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.9.9" % "compile", + "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.9.10" % "compile", {{/withXml}} {{#joda}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.9" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.10" % "compile", {{/joda}} {{#java8}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.9" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.10" % "compile", {{/java8}} {{#threetenbp}} - "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4" % "compile", + "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", {{/threetenbp}} "junit" % "junit" % "4.12" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index 8bafe1ea9a4..7be1da91a4e 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -313,7 +313,7 @@ 2.9.9 {{/joda}} {{#threetenbp}} - 2.6.4 + 2.9.10 {{/threetenbp}} 1.0.0 4.12 diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index c86178e7d04..ec3b383eea0 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -132,7 +132,7 @@ ext { {{/supportJava6}} junit_version = "4.12" {{#threetenbp}} - threetenbp_version = "2.6.4" + threetenbp_version = "2.9.10" {{/threetenbp}} } diff --git a/libraries/jersey2/build.sbt.mustache b/libraries/jersey2/build.sbt.mustache index ef2e32af36e..e31be933919 100644 --- a/libraries/jersey2/build.sbt.mustache +++ b/libraries/jersey2/build.sbt.mustache @@ -17,13 +17,13 @@ lazy val root = (project in file(".")). "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.10" % "compile", "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10" % "compile", {{#joda}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.9" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.10" % "compile", {{/joda}} {{#java8}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.9" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.10" % "compile", {{/java8}} {{#threetenbp}} - "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4" % "compile", + "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", {{/threetenbp}} {{^java8}} "com.brsanthu" % "migbase64" % "2.2", diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 621228c2a7a..31a1843080e 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -364,7 +364,7 @@ 2.9.10 0.2.0 {{#threetenbp}} - 2.6.4 + 2.9.10 {{/threetenbp}} 1.0.0 4.12 diff --git a/libraries/okhttp-gson/build.gradle.mustache b/libraries/okhttp-gson/build.gradle.mustache index d6ae8e31461..fbf57ba7796 100644 --- a/libraries/okhttp-gson/build.gradle.mustache +++ b/libraries/okhttp-gson/build.gradle.mustache @@ -140,7 +140,7 @@ dependencies { compile 'joda-time:joda-time:2.9.9' {{/joda}} {{#threetenbp}} - compile 'org.threeten:threetenbp:1.3.5' + compile 'org.threeten:threetenbp:1.4.0' {{/threetenbp}} testCompile 'junit:junit:4.12' } diff --git a/libraries/okhttp-gson/build.sbt.mustache b/libraries/okhttp-gson/build.sbt.mustache index e1c68a17514..4d768393264 100644 --- a/libraries/okhttp-gson/build.sbt.mustache +++ b/libraries/okhttp-gson/build.sbt.mustache @@ -21,7 +21,7 @@ lazy val root = (project in file(".")). "joda-time" % "joda-time" % "2.9.9" % "compile", {{/joda}} {{#threetenbp}} - "org.threeten" % "threetenbp" % "1.3.5" % "compile", + "org.threeten" % "threetenbp" % "1.4.0" % "compile", {{/threetenbp}} "io.gsonfire" % "gson-fire" % "1.8.3" % "compile", "javax.annotation" % "jsr250-api" % "1.0" % "compile", diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index 759b9fe8249..cbcdd78f974 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -316,7 +316,7 @@ 2.9.9 {{/joda}} {{#threetenbp}} - 1.3.8 + 1.4.0 {{/threetenbp}} 1.0.0 1.0 diff --git a/libraries/rest-assured/build.gradle.mustache b/libraries/rest-assured/build.gradle.mustache index 726c343301e..c40c9c3eb92 100644 --- a/libraries/rest-assured/build.gradle.mustache +++ b/libraries/rest-assured/build.gradle.mustache @@ -99,8 +99,8 @@ ext { rest_assured_version = "4.0.0" junit_version = "4.12" {{#jackson}} - jackson_version = "{{^threetenbp}}2.9.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" - jackson_databind_version = "{{^threetenbp}}2.9.9{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" + jackson_version = "2.9.10" + jackson_databind_version = "2.9.10" jackson_databind_nullable_version = 0.2.0 {{/jackson}} {{#gson}} @@ -111,7 +111,7 @@ ext { jodatime_version = "2.9.9" {{/joda}} {{#threetenbp}} - threetenbp_version = "1.3.8" + threetenbp_version = "1.4.0" {{/threetenbp}} okio_version = "1.13.0" } diff --git a/libraries/rest-assured/build.sbt.mustache b/libraries/rest-assured/build.sbt.mustache index 5f62ab21481..d8214467ae2 100644 --- a/libraries/rest-assured/build.sbt.mustache +++ b/libraries/rest-assured/build.sbt.mustache @@ -24,7 +24,7 @@ lazy val root = (project in file(".")). "joda-time" % "joda-time" % "2.9.9" % "compile", {{/joda}} {{#threetenbp}} - "org.threeten" % "threetenbp" % "1.3.8" % "compile", + "org.threeten" % "threetenbp" % "1.4.0" % "compile", {{/threetenbp}} "com.squareup.okio" % "okio" % "1.13.0" % "compile", "junit" % "junit" % "4.12" % "test", diff --git a/libraries/rest-assured/pom.mustache b/libraries/rest-assured/pom.mustache index 383403811b8..330fd660725 100644 --- a/libraries/rest-assured/pom.mustache +++ b/libraries/rest-assured/pom.mustache @@ -320,14 +320,14 @@ 2.9.9 {{/joda}} {{#threetenbp}} - 1.3.8 + 1.4.0 {{/threetenbp}} {{#jackson}} - 2.9.9 - 2.9.9 + 2.9.10 + 2.9.10 0.2.0 {{#threetenbp}} - 2.6.4 + 2.9.10 {{/threetenbp}} {{/jackson}} 1.13.0 diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index 930ae737fdc..e45659de524 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -122,7 +122,7 @@ ext { jackson_version = "2.9.10" jackson_databind_version = "2.9.10" jackson_databind_nullable_version = "0.2.0" - threetenbp_version = "2.6.4" + threetenbp_version = "2.9.10" resteasy_version = "3.1.3.Final" {{^java8}} jodatime_version = "2.9.9" diff --git a/libraries/resteasy/build.sbt.mustache b/libraries/resteasy/build.sbt.mustache index 0af339a0da6..bcedcaec343 100644 --- a/libraries/resteasy/build.sbt.mustache +++ b/libraries/resteasy/build.sbt.mustache @@ -16,12 +16,12 @@ lazy val root = (project in file(".")). "com.fasterxml.jackson.core" % "jackson-core" % "2.9.10" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.10" % "compile", "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10" % "compile", - "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4" % "compile", + "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", {{#java8}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.9" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.10" % "compile", {{/java8}} {{^java8}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.9" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.10" % "compile", "joda-time" % "joda-time" % "2.9.9" % "compile", "com.brsanthu" % "migbase64" % "2.2" % "compile", {{/java8}} diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index 4318c37628a..1a12889b965 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -297,7 +297,7 @@ 2.9.10 2.9.10 0.2.0 - 2.6.4 + 2.9.10 {{^java8}} 2.9.9 {{/java8}} diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index 06700890574..7601a8180d1 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -127,7 +127,7 @@ ext { jodatime_version = "2.9.9" junit_version = "4.12" {{#threetenbp}} - jackson_threeten_version = "2.6.4" + jackson_threeten_version = "2.9.10" {{/threetenbp}} } diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache index c48a68e347a..a717eb44127 100644 --- a/libraries/resttemplate/pom.mustache +++ b/libraries/resttemplate/pom.mustache @@ -309,14 +309,14 @@ UTF-8 1.5.22 4.3.9.RELEASE - 2.9.9 - 2.9.9 + 2.9.10 + 2.9.10 0.2.0 {{#joda}} 2.9.9 {{/joda}} {{#threetenbp}} - 2.6.4 + 2.9.10 {{/threetenbp}} 1.0.0 4.12 diff --git a/libraries/retrofit/build.gradle.mustache b/libraries/retrofit/build.gradle.mustache index 3927003a314..a3c7c226f06 100644 --- a/libraries/retrofit/build.gradle.mustache +++ b/libraries/retrofit/build.gradle.mustache @@ -114,7 +114,7 @@ ext { junit_version = "4.12" jodatime_version = "2.9.3" {{#threetenbp}} - threetenbp_version = "1.3.5" + threetenbp_version = "1.4.0" {{/threetenbp}} } diff --git a/libraries/retrofit/build.sbt.mustache b/libraries/retrofit/build.sbt.mustache index 9d5df5e223c..6afa18db865 100644 --- a/libraries/retrofit/build.sbt.mustache +++ b/libraries/retrofit/build.sbt.mustache @@ -15,7 +15,7 @@ lazy val root = (project in file(".")). "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", "joda-time" % "joda-time" % "2.9.3" % "compile", {{#threetenbp}} - "org.threeten" % "threetenbp" % "1.3.5" % "compile", + "org.threeten" % "threetenbp" % "1.4.0" % "compile", {{/threetenbp}} "junit" % "junit" % "4.12" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" diff --git a/libraries/retrofit/pom.mustache b/libraries/retrofit/pom.mustache index 5e91585eedc..73d9b4d565a 100644 --- a/libraries/retrofit/pom.mustache +++ b/libraries/retrofit/pom.mustache @@ -276,7 +276,7 @@ 2.7.5 2.9.9 {{#threetenbp}} - 1.3.5 + 1.4.0 {{/threetenbp}} 1.0.1 1.0.0 diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index 85aa12d6cca..e7f778ba5a0 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -149,7 +149,7 @@ ext { jodatime_version = "2.9.9" {{/joda}} {{#threetenbp}} - threetenbp_version = "1.3.5" + threetenbp_version = "1.4.0" {{/threetenbp}} json_fire_version = "1.8.0" } diff --git a/libraries/retrofit2/build.sbt.mustache b/libraries/retrofit2/build.sbt.mustache index 78f7e5786af..c6fc88aa0aa 100644 --- a/libraries/retrofit2/build.sbt.mustache +++ b/libraries/retrofit2/build.sbt.mustache @@ -50,7 +50,7 @@ lazy val root = (project in file(".")). "joda-time" % "joda-time" % "2.9.9" % "compile", {{/joda}} {{#threetenbp}} - "org.threeten" % "threetenbp" % "1.3.5" % "compile", + "org.threeten" % "threetenbp" % "1.4.0" % "compile", {{/threetenbp}} "io.gsonfire" % "gson-fire" % "1.8.0" % "compile", "junit" % "junit" % "4.12" % "test", diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index 8bca88942d3..d32445d02f1 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -401,7 +401,7 @@ 2.9.9 {{/joda}} {{#threetenbp}} - 1.3.8 + 1.4.0 {{/threetenbp}} 1.0.1 4.12 diff --git a/libraries/vertx/build.gradle.mustache b/libraries/vertx/build.gradle.mustache index 20aa961eaaf..68dce22f06a 100644 --- a/libraries/vertx/build.gradle.mustache +++ b/libraries/vertx/build.gradle.mustache @@ -28,8 +28,8 @@ task execute(type:JavaExec) { ext { swagger_annotations_version = "1.5.21" - jackson_version = "{{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" - jackson_databind_version = "{{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" + jackson_version = "2.9.10" + jackson_databind_version = "2.9.10" vertx_version = "3.4.2" junit_version = "4.12" } diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache index 17d2c1261a9..df558861387 100644 --- a/libraries/vertx/pom.mustache +++ b/libraries/vertx/pom.mustache @@ -289,8 +289,8 @@ UTF-8 3.4.2 1.5.22 - {{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} - {{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} + 2.9.10 + 2.9.10 0.2.0 4.12 From 347953d23dc30588cc609049df2b1dea7c36e5a9 Mon Sep 17 00:00:00 2001 From: atsharp Date: Sat, 19 Oct 2019 05:05:02 -0500 Subject: [PATCH 161/370] [Java] Support cookie-based security schemas in Java clients (#4155) * Adding cookie support and cookie-based AuthKeys to Java clients * Fix indentation * Revert accidental change * Updating samples * Fixing tests and regenerating samples --- ApiClient.mustache | 41 +++++++++++--- api.mustache | 9 +++- auth/ApiKeyAuth.mustache | 4 +- auth/Authentication.mustache | 3 +- auth/HttpBasicAuth.mustache | 2 +- auth/HttpBearerAuth.mustache | 2 +- auth/OAuth.mustache | 2 +- libraries/feign/ApiClient.mustache | 2 +- libraries/feign/auth/ApiKeyAuth.mustache | 2 + libraries/jersey2/ApiClient.mustache | 32 +++++++++-- libraries/jersey2/api.mustache | 9 +++- libraries/okhttp-gson/ApiClient.mustache | 52 ++++++++++++++---- libraries/okhttp-gson/api.mustache | 9 +++- .../okhttp-gson/auth/HttpBasicAuth.mustache | 2 +- .../okhttp-gson/auth/RetryingOAuth.mustache | 2 +- libraries/resteasy/ApiClient.mustache | 28 ++++++++-- libraries/resteasy/api.mustache | 9 +++- libraries/resttemplate/ApiClient.mustache | 50 +++++++++++++++-- libraries/resttemplate/api.mustache | 9 +++- .../resttemplate/auth/ApiKeyAuth.mustache | 6 ++- .../resttemplate/auth/Authentication.mustache | 7 +-- .../resttemplate/auth/HttpBasicAuth.mustache | 2 +- .../resttemplate/auth/HttpBearerAuth.mustache | 2 +- libraries/resttemplate/auth/OAuth.mustache | 2 +- libraries/retrofit/ApiClient.mustache | 10 ++-- libraries/retrofit/auth/ApiKeyAuth.mustache | 6 ++- libraries/retrofit2/ApiClient.mustache | 2 +- libraries/retrofit2/auth/ApiKeyAuth.mustache | 4 ++ .../play-common/auth/ApiKeyAuth.mustache | 4 +- libraries/retrofit2/play24/ApiClient.mustache | 9 ++-- .../play24/Play24CallFactory.mustache | 26 +++++++++ libraries/retrofit2/play25/ApiClient.mustache | 9 ++-- .../play25/Play25CallFactory.mustache | 31 ++++++++++- libraries/retrofit2/play26/ApiClient.mustache | 7 +-- .../play26/Play26CallFactory.mustache | 40 ++++++++++++++ libraries/vertx/ApiClient.mustache | 36 +++++++++++-- libraries/vertx/apiImpl.mustache | 10 +++- libraries/vertx/auth/ApiKeyAuth.mustache | 4 +- libraries/vertx/auth/Authentication.mustache | 3 +- libraries/vertx/auth/HttpBasicAuth.mustache | 2 +- libraries/vertx/auth/HttpBearerAuth.mustache | 2 +- libraries/vertx/auth/OAuth.mustache | 2 +- libraries/webclient/ApiClient.mustache | 53 +++++++++++++++---- libraries/webclient/api.mustache | 16 +++--- libraries/webclient/auth/ApiKeyAuth.mustache | 6 ++- .../webclient/auth/Authentication.mustache | 7 +-- .../webclient/auth/HttpBasicAuth.mustache | 2 +- .../webclient/auth/HttpBearerAuth.mustache | 2 +- libraries/webclient/auth/OAuth.mustache | 2 +- 49 files changed, 469 insertions(+), 114 deletions(-) diff --git a/ApiClient.mustache b/ApiClient.mustache index 66d9c572088..1ae6c36f68a 100644 --- a/ApiClient.mustache +++ b/ApiClient.mustache @@ -29,6 +29,7 @@ import com.sun.jersey.api.client.WebResource.Builder; import com.sun.jersey.multipart.FormDataMultiPart; import com.sun.jersey.multipart.file.FileDataBodyPart; +import javax.ws.rs.core.Cookie; import javax.ws.rs.core.Response.Status.Family; import javax.ws.rs.core.MediaType; @@ -60,6 +61,7 @@ import {{invokerPackage}}.auth.OAuth; {{>generatedAnnotation}} public class ApiClient { private Map defaultHeaderMap = new HashMap(); + private Map defaultCookieMap = new HashMap(); private String basePath = "{{{basePath}}}"; private boolean debugging = false; private int connectionTimeout = 0; @@ -239,7 +241,7 @@ public class ApiClient { /** * Helper method to set API key value for the first API key authentication. - * @param apiKey API key + * @param apiKey the API key */ public void setApiKey(String apiKey) { for (Authentication auth : authentications.values()) { @@ -250,7 +252,7 @@ public class ApiClient { } throw new RuntimeException("No API key authentication configured!"); } - + /** * Helper method to set API key prefix for the first API key authentication. * @param apiKeyPrefix API key prefix @@ -318,6 +320,18 @@ public class ApiClient { return this; } + /** + * Add a default cookie. + * + * @param key The cookie's key + * @param value The cookie's value + * @return API client + */ + public ApiClient addDefaultCookie(String key, String value) { + defaultCookieMap.put(key, value); + return this; + } + /** * Check that whether debugging is enabled for this API client. * @return True if debugging is on @@ -652,12 +666,12 @@ public class ApiClient { return url.toString(); } - private ClientResponse getAPIResponse(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map formParams, String accept, String contentType, String[] authNames) throws ApiException { + private ClientResponse getAPIResponse(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames) throws ApiException { if (body != null && !formParams.isEmpty()) { throw new ApiException(500, "Cannot have body and form params"); } - updateParamsForAuth(authNames, queryParams, headerParams); + updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); final String url = buildUrl(path, queryParams, collectionQueryParams); Builder builder; @@ -676,6 +690,15 @@ public class ApiClient { } } + for (Entry keyValue : cookieParams.entrySet()) { + builder = builder.cookie(new Cookie(keyValue.getKey(), keyValue.getValue())); + } + for (Map.Entry keyValue : defaultCookieMap.entrySet()) { + if (!cookieParams.containsKey(keyValue.getKey())) { + builder = builder.cookie(new Cookie(keyValue.getKey(), keyValue.getValue())); + } + } + ClientResponse response = null; if ("GET".equals(method)) { @@ -706,6 +729,7 @@ public class ApiClient { * @param collectionQueryParams The collection query parameters * @param body The request body object - if it is not binary, otherwise null * @param headerParams The header parameters + * @param cookieParams The cookie parameters * @param formParams The form parameters * @param accept The request's Accept header * @param contentType The request's Content-Type header @@ -714,9 +738,9 @@ public class ApiClient { * @return The response body in type of string * @throws ApiException API exception */ - public T invokeAPI(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { + public T invokeAPI(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { - ClientResponse response = getAPIResponse(path, method, queryParams, collectionQueryParams, body, headerParams, formParams, accept, contentType, authNames); + ClientResponse response = getAPIResponse(path, method, queryParams, collectionQueryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames); statusCode = response.getStatusInfo().getStatusCode(); responseHeaders = response.getHeaders(); @@ -753,12 +777,13 @@ public class ApiClient { * @param authNames The authentications to apply * @param queryParams Query parameters * @param headerParams Header parameters + * @param cookieParams Cookie parameters */ - private void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams) { + private void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams, Map cookieParams) { for (String authName : authNames) { Authentication auth = authentications.get(authName); if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); - auth.applyToParams(queryParams, headerParams); + auth.applyToParams(queryParams, headerParams, cookieParams); } } diff --git a/api.mustache b/api.mustache index fa23d312502..11fc64de646 100644 --- a/api.mustache +++ b/api.mustache @@ -79,6 +79,7 @@ public class {{classname}} { {{javaUtilPrefix}}List localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); {{javaUtilPrefix}}List localVarCollectionQueryParams = new {{javaUtilPrefix}}ArrayList(); {{javaUtilPrefix}}Map localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarCookieParams = new {{javaUtilPrefix}}HashMap(); {{javaUtilPrefix}}Map localVarFormParams = new {{javaUtilPrefix}}HashMap(); {{#queryParams}} @@ -89,6 +90,10 @@ public class {{classname}} { localVarHeaderParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); {{/headerParams}} + {{#cookieParams}}if ({{paramName}} != null) + localVarCookieParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); + {{/cookieParams}} + {{#formParams}}if ({{paramName}} != null) localVarFormParams.put("{{baseName}}", {{paramName}}); {{/formParams}} @@ -107,9 +112,9 @@ public class {{classname}} { {{#returnType}} GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {}; - return apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType); + return apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType); {{/returnType}}{{^returnType}} - apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, null); + apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, null); {{/returnType}} } {{/operation}} diff --git a/auth/ApiKeyAuth.mustache b/auth/ApiKeyAuth.mustache index 5af060f1173..991ae235003 100644 --- a/auth/ApiKeyAuth.mustache +++ b/auth/ApiKeyAuth.mustache @@ -45,7 +45,7 @@ public class ApiKeyAuth implements Authentication { } @Override - public void applyToParams(List queryParams, Map headerParams) { + public void applyToParams(List queryParams, Map headerParams, Map cookieParams) { if (apiKey == null) { return; } @@ -59,6 +59,8 @@ public class ApiKeyAuth implements Authentication { queryParams.add(new Pair(paramName, value)); } else if ("header".equals(location)) { headerParams.put(paramName, value); + } else if ("cookie".equals(location)) { + cookieParams.put(paramName, value); } } } diff --git a/auth/Authentication.mustache b/auth/Authentication.mustache index 26174fa3b59..033de98d562 100644 --- a/auth/Authentication.mustache +++ b/auth/Authentication.mustache @@ -13,6 +13,7 @@ public interface Authentication { * * @param queryParams List of query parameters * @param headerParams Map of header parameters + * @param cookieParams Map of cookie parameters */ - void applyToParams(List queryParams, Map headerParams); + void applyToParams(List queryParams, Map headerParams, Map cookieParams); } diff --git a/auth/HttpBasicAuth.mustache b/auth/HttpBasicAuth.mustache index 015e042e171..4d362cbaf54 100644 --- a/auth/HttpBasicAuth.mustache +++ b/auth/HttpBasicAuth.mustache @@ -41,7 +41,7 @@ public class HttpBasicAuth implements Authentication { } @Override - public void applyToParams(List queryParams, Map headerParams) { + public void applyToParams(List queryParams, Map headerParams, Map cookieParams) { if (username == null && password == null) { return; } diff --git a/auth/HttpBearerAuth.mustache b/auth/HttpBearerAuth.mustache index 1d195865439..322281f8716 100644 --- a/auth/HttpBearerAuth.mustache +++ b/auth/HttpBearerAuth.mustache @@ -35,7 +35,7 @@ public class HttpBearerAuth implements Authentication { } @Override - public void applyToParams(List queryParams, Map headerParams) { + public void applyToParams(List queryParams, Map headerParams, Map cookieParams) { if(bearerToken == null) { return; } diff --git a/auth/OAuth.mustache b/auth/OAuth.mustache index ffc9923d1fe..5cb98e7cb3b 100644 --- a/auth/OAuth.mustache +++ b/auth/OAuth.mustache @@ -20,7 +20,7 @@ public class OAuth implements Authentication { } @Override - public void applyToParams(List queryParams, Map headerParams) { + public void applyToParams(List queryParams, Map headerParams, Map cookieParams) { if (accessToken != null) { headerParams.put("Authorization", "Bearer " + accessToken); } diff --git a/libraries/feign/ApiClient.mustache b/libraries/feign/ApiClient.mustache index 0f826eb387b..47e993012f2 100644 --- a/libraries/feign/ApiClient.mustache +++ b/libraries/feign/ApiClient.mustache @@ -70,7 +70,7 @@ public class ApiClient { {{/isBasicBasic}} {{/isBasic}} {{#isApiKey}} - auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"); + auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"); {{/isApiKey}} {{#isOAuth}} auth = new OAuth(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{#hasMore}}, {{/hasMore}}{{/scopes}}"); diff --git a/libraries/feign/auth/ApiKeyAuth.mustache b/libraries/feign/auth/ApiKeyAuth.mustache index 9982cd7fc49..c03fe5c0bc0 100644 --- a/libraries/feign/auth/ApiKeyAuth.mustache +++ b/libraries/feign/auth/ApiKeyAuth.mustache @@ -36,6 +36,8 @@ public class ApiKeyAuth implements RequestInterceptor { template.query(paramName, apiKey); } else if ("header".equals(location)) { template.header(paramName, apiKey); + } else if ("cookie".equals(location)) { + template.header("Cookie", String.format("%s=%s", paramName, apiKey)); } } } diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 4d2c3e21b61..0aa3683cf35 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -62,6 +62,7 @@ import {{invokerPackage}}.auth.OAuth; {{>generatedAnnotation}} public class ApiClient { protected Map defaultHeaderMap = new HashMap(); + protected Map defaultCookieMap = new HashMap(); protected String basePath = "{{{basePath}}}"; protected boolean debugging = false; protected int connectionTimeout = 0; @@ -246,6 +247,18 @@ public class ApiClient { return this; } + /** + * Add a default cookie. + * + * @param key The cookie's key + * @param value The cookie's value + * @return API client + */ + public ApiClient addDefaultCookie(String key, String value) { + defaultCookieMap.put(key, value); + return this; + } + /** * Check that whether debugging is enabled for this API client. * @return True if debugging is switched on @@ -316,7 +329,7 @@ public class ApiClient { public int getReadTimeout() { return readTimeout; } - + /** * Set the read timeout (in milliseconds). * A value of 0 means no timeout, otherwise values must be between 1 and @@ -662,6 +675,7 @@ public class ApiClient { * @param queryParams The query parameters * @param body The request body object * @param headerParams The header parameters + * @param cookieParams The cookie parameters * @param formParams The form parameters * @param accept The request's Accept header * @param contentType The request's Content-Type header @@ -670,8 +684,8 @@ public class ApiClient { * @return The response body in type of string * @throws ApiException API exception */ - public ApiResponse invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { - updateParamsForAuth(authNames, queryParams, headerParams); + public ApiResponse invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { + updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); // Not using `.target(this.basePath).path(path)` below, // to support (constant) query string in `path`, e.g. "/posts?draft=1" @@ -694,6 +708,13 @@ public class ApiClient { } } + for (Entry entry : cookieParams.entrySet()) { + String value = entry.getValue(); + if (value != null) { + invocationBuilder = invocationBuilder.cookie(entry.getKey(), value); + } + } + for (Entry entry : defaultHeaderMap.entrySet()) { String key = entry.getKey(); if (!headerParams.containsKey(key)) { @@ -819,12 +840,13 @@ public class ApiClient { * @param authNames The authentications to apply * @param queryParams List of query parameters * @param headerParams Map of header parameters + * @param cookieParams Map of cookie parameters */ - protected void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams) { + protected void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams, Map cookieParams) { for (String authName : authNames) { Authentication auth = authentications.get(authName); if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); - auth.applyToParams(queryParams, headerParams); + auth.applyToParams(queryParams, headerParams, cookieParams); } } } diff --git a/libraries/jersey2/api.mustache b/libraries/jersey2/api.mustache index 89131a0f943..f3e27a079c2 100644 --- a/libraries/jersey2/api.mustache +++ b/libraries/jersey2/api.mustache @@ -121,6 +121,7 @@ public class {{classname}} { // query params {{javaUtilPrefix}}List localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); {{javaUtilPrefix}}Map localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarCookieParams = new {{javaUtilPrefix}}HashMap(); {{javaUtilPrefix}}Map localVarFormParams = new {{javaUtilPrefix}}HashMap(); {{#queryParams}} @@ -131,6 +132,10 @@ public class {{classname}} { localVarHeaderParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); {{/headerParams}} + {{#cookieParams}}if ({{paramName}} != null) + localVarCookieParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); + {{/cookieParams}} + {{#formParams}}if ({{paramName}} != null) localVarFormParams.put("{{baseName}}", {{paramName}}); {{/formParams}} @@ -149,9 +154,9 @@ public class {{classname}} { {{#returnType}} GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {}; - return apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType); + return apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType); {{/returnType}}{{^returnType}} - return apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, null); + return apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, null); {{/returnType}} } {{/operation}} diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index 682bf945069..f81ed11659b 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -65,6 +65,7 @@ public class ApiClient { private String basePath = "{{{basePath}}}"; private boolean debugging = false; private Map defaultHeaderMap = new HashMap(); + private Map defaultCookieMap = new HashMap(); private String tempFolderPath = null; private Map authentications; @@ -92,7 +93,7 @@ public class ApiClient { // Setup authentications (key: authentication name, value: authentication).{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} - authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} // Prevent the authentications from being modified. authentications = Collections.unmodifiableMap(authentications); @@ -442,6 +443,18 @@ public class ApiClient { return this; } + /** + * Add a default cookie. + * + * @param key The cookie's key + * @param value The cookie's value + * @return ApiClient + */ + public ApiClient addDefaultCookie(String key, String value) { + defaultCookieMap.put(key, value); + return this; + } + /** * Check that whether debugging is enabled for this API client. * @@ -1069,14 +1082,15 @@ public class ApiClient { * @param collectionQueryParams The collection query parameters * @param body The request body object * @param headerParams The header parameters + * @param cookieParams The cookie parameters * @param formParams The form parameters * @param authNames The authentications to apply * @param callback Callback for upload/download progress * @return The HTTP call * @throws ApiException If fail to serialize the request body object */ - public Call buildCall(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map formParams, String[] authNames, ApiCallback callback) throws ApiException { - Request request = buildRequest(path, method, queryParams, collectionQueryParams, body, headerParams, formParams, authNames, callback); + public Call buildCall(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String[] authNames, ApiCallback callback) throws ApiException { + Request request = buildRequest(path, method, queryParams, collectionQueryParams, body, headerParams, cookieParams, formParams, authNames, callback); return httpClient.newCall(request); } @@ -1090,18 +1104,20 @@ public class ApiClient { * @param collectionQueryParams The collection query parameters * @param body The request body object * @param headerParams The header parameters + * @param cookieParams The cookie parameters * @param formParams The form parameters * @param authNames The authentications to apply * @param callback Callback for upload/download progress * @return The HTTP request * @throws ApiException If fail to serialize the request body object */ - public Request buildRequest(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map formParams, String[] authNames, ApiCallback callback) throws ApiException { - updateParamsForAuth(authNames, queryParams, headerParams); + public Request buildRequest(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String[] authNames, ApiCallback callback) throws ApiException { + updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); final String url = buildUrl(path, queryParams, collectionQueryParams); final Request.Builder reqBuilder = new Request.Builder().url(url); processHeaderParams(headerParams, reqBuilder); + processCookieParams(cookieParams, reqBuilder); String contentType = (String) headerParams.get("Content-Type"); // ensuring a default content type @@ -1196,8 +1212,8 @@ public class ApiClient { /** * Set header parameters to the request builder, including default headers. * - * @param headerParams Header parameters in the ofrm of Map - * @param reqBuilder Reqeust.Builder + * @param headerParams Header parameters in the form of Map + * @param reqBuilder Request.Builder */ public void processHeaderParams(Map headerParams, Request.Builder reqBuilder) { for (Entry param : headerParams.entrySet()) { @@ -1210,20 +1226,38 @@ public class ApiClient { } } + /** + * Set cookie parameters to the request builder, including default cookies. + * + * @param cookieParams Cookie parameters in the form of Map + * @param reqBuilder Request.Builder + */ + public void processCookieParams(Map cookieParams, Request.Builder reqBuilder) { + for (Entry param : cookieParams.entrySet()) { + reqBuilder.addHeader("Cookie", String.format("%s=%s", param.getKey(), param.getValue())); + } + for (Entry param : defaultCookieMap.entrySet()) { + if (!cookieParams.containsKey(param.getKey())) { + reqBuilder.addHeader("Cookie", String.format("%s=%s", param.getKey(), param.getValue())); + } + } + } + /** * Update query and header parameters based on authentication settings. * * @param authNames The authentications to apply * @param queryParams List of query parameters * @param headerParams Map of header parameters + * @param cookieParams Map of cookie parameters */ - public void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams) { + public void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams, Map cookieParams) { for (String authName : authNames) { Authentication auth = authentications.get(authName); if (auth == null) { throw new RuntimeException("Authentication undefined: " + authName); } - auth.applyToParams(queryParams, headerParams); + auth.applyToParams(queryParams, headerParams, cookieParams); } } diff --git a/libraries/okhttp-gson/api.mustache b/libraries/okhttp-gson/api.mustache index 26015967b40..98bcd3d4654 100644 --- a/libraries/okhttp-gson/api.mustache +++ b/libraries/okhttp-gson/api.mustache @@ -111,6 +111,13 @@ public class {{classname}} { } {{/headerParams}} + {{javaUtilPrefix}}Map localVarCookieParams = new {{javaUtilPrefix}}HashMap(); + {{#cookieParams}} + if ({{paramName}} != null) { + localVarCookieParams.put("{{baseName}}", localVarApiClient.parameterToString({{paramName}})); + } + + {{/cookieParams}} {{javaUtilPrefix}}Map localVarFormParams = new {{javaUtilPrefix}}HashMap(); {{#formParams}} if ({{paramName}} != null) { @@ -133,7 +140,7 @@ public class {{classname}} { localVarHeaderParams.put("Content-Type", localVarContentType); String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; - return localVarApiClient.buildCall(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAuthNames, _callback); + return localVarApiClient.buildCall(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); } {{#isDeprecated}} diff --git a/libraries/okhttp-gson/auth/HttpBasicAuth.mustache b/libraries/okhttp-gson/auth/HttpBasicAuth.mustache index 6356e227a1e..9cff50a7475 100644 --- a/libraries/okhttp-gson/auth/HttpBasicAuth.mustache +++ b/libraries/okhttp-gson/auth/HttpBasicAuth.mustache @@ -32,7 +32,7 @@ public class HttpBasicAuth implements Authentication { } @Override - public void applyToParams(List queryParams, Map headerParams) { + public void applyToParams(List queryParams, Map headerParams, Map cookieParams) { if (username == null && password == null) { return; } diff --git a/libraries/okhttp-gson/auth/RetryingOAuth.mustache b/libraries/okhttp-gson/auth/RetryingOAuth.mustache index d3f6d90abba..94f1d6afcf9 100644 --- a/libraries/okhttp-gson/auth/RetryingOAuth.mustache +++ b/libraries/okhttp-gson/auth/RetryingOAuth.mustache @@ -169,7 +169,7 @@ public class RetryingOAuth extends OAuth implements Interceptor { // Applying authorization to parameters is performed in the retryingIntercept method @Override - public void applyToParams(List queryParams, Map headerParams) { + public void applyToParams(List queryParams, Map headerParams, Map cookieParams) { // No implementation necessary } } diff --git a/libraries/resteasy/ApiClient.mustache b/libraries/resteasy/ApiClient.mustache index ca672da4998..16ec4c4508f 100644 --- a/libraries/resteasy/ApiClient.mustache +++ b/libraries/resteasy/ApiClient.mustache @@ -50,6 +50,7 @@ import {{invokerPackage}}.auth.OAuth; {{>generatedAnnotation}} public class ApiClient { private Map defaultHeaderMap = new HashMap(); + private Map defaultCookieMap = new HashMap(); private String basePath = "{{{basePath}}}"; private boolean debugging = false; @@ -82,7 +83,7 @@ public class ApiClient { authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} - authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} // Prevent the authentications from being modified. authentications = Collections.unmodifiableMap(authentications); @@ -611,6 +612,7 @@ public class ApiClient { * @param queryParams The query parameters * @param body The request body object * @param headerParams The header parameters + * @param cookieParams The cookie parameters * @param formParams The form parameters * @param accept The request's Accept header * @param contentType The request's Content-Type header @@ -619,8 +621,8 @@ public class ApiClient { * @return The response body in type of string * @throws ApiException if the invocation failed */ - public T invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { - updateParamsForAuth(authNames, queryParams, headerParams); + public T invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { + updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); // Not using `.target(this.basePath).path(path)` below, // to support (constant) query string in `path`, e.g. "/posts?draft=1" @@ -652,6 +654,22 @@ public class ApiClient { } } + for (Entry cookieParamsEntry : cookieParams.entrySet()) { + String value = cookieParamsEntry.getValue(); + if (value != null) { + invocationBuilder = invocationBuilder.cookie(cookieParamsEntry.getKey(), value); + } + } + + for (Entry defaultCookieEntry: defaultHeaderMap.entrySet()) { + if (!cookieParams.containsKey(defaultCookieEntry.getKey())) { + String value = defaultCookieEntry.getValue(); + if (value != null) { + invocationBuilder = invocationBuilder.cookie(defaultCookieEntry.getKey(), value); + } + } + } + Entity entity = serialize(body, formParams, contentType); Response response = null; @@ -734,11 +752,11 @@ public class ApiClient { * * @param authNames The authentications to apply */ - private void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams) { + private void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams, Map cookieParams) { for (String authName : authNames) { Authentication auth = authentications.get(authName); if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); - auth.applyToParams(queryParams, headerParams); + auth.applyToParams(queryParams, headerParams, cookieParams); } } } diff --git a/libraries/resteasy/api.mustache b/libraries/resteasy/api.mustache index e13ddbc9e16..fcb2268a100 100644 --- a/libraries/resteasy/api.mustache +++ b/libraries/resteasy/api.mustache @@ -71,6 +71,7 @@ public class {{classname}} { // query params {{javaUtilPrefix}}List localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); {{javaUtilPrefix}}Map localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarCookieParams = new {{javaUtilPrefix}}HashMap(); {{javaUtilPrefix}}Map localVarFormParams = new {{javaUtilPrefix}}HashMap(); {{#queryParams}} @@ -81,6 +82,10 @@ public class {{classname}} { localVarHeaderParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); {{/headerParams}} + {{#cookieParams}}if ({{paramName}} != null) + localVarCookieParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); + {{/cookieParams}} + {{#formParams}}if ({{paramName}} != null) localVarFormParams.put("{{baseName}}", {{paramName}}); {{/formParams}} @@ -99,9 +104,9 @@ public class {{classname}} { {{#returnType}} GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {}; - return apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType); + return apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType); {{/returnType}}{{^returnType}} - apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, null); + apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, null); {{/returnType}} } {{/operation}} diff --git a/libraries/resttemplate/ApiClient.mustache b/libraries/resttemplate/ApiClient.mustache index df21df17b02..5abf07fc02c 100644 --- a/libraries/resttemplate/ApiClient.mustache +++ b/libraries/resttemplate/ApiClient.mustache @@ -92,6 +92,7 @@ public class ApiClient { private boolean debugging = false; private HttpHeaders defaultHeaders = new HttpHeaders(); + private MultiValueMap defaultCookies = new LinkedMultiValueMap(); private String basePath = "{{basePath}}"; @@ -280,6 +281,21 @@ public class ApiClient { return this; } + /** + * Add a default cookie. + * + * @param name The cookie's name + * @param value The cookie's value + * @return ApiClient this client + */ + public ApiClient addDefaultCookie(String name, String value) { + if (defaultCookies.containsKey(name)) { + defaultCookies.remove(name); + } + defaultCookies.add(name, value); + return this; + } + public void setDebugging(boolean debugging) { List currentInterceptors = this.restTemplate.getInterceptors(); if(debugging) { @@ -556,6 +572,7 @@ public class ApiClient { * @param queryParams The query parameters * @param body The request body object * @param headerParams The header parameters + * @param cookieParams The cookie parameters * @param formParams The form parameters * @param accept The request's Accept header * @param contentType The request's Content-Type header @@ -563,8 +580,8 @@ public class ApiClient { * @param returnType The return type into which to deserialize the response * @return ResponseEntity<T> The response of the chosen type */ - public ResponseEntity invokeAPI(String path, HttpMethod method, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { - updateParamsForAuth(authNames, queryParams, headerParams); + public ResponseEntity invokeAPI(String path, HttpMethod method, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap cookieParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { + updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(path); if (queryParams != null) { @@ -600,6 +617,8 @@ public class ApiClient { addHeadersToRequest(headerParams, requestBuilder); addHeadersToRequest(defaultHeaders, requestBuilder); + addCookiesToRequest(cookieParams, requestBuilder); + addCookiesToRequest(defaultCookies, requestBuilder); RequestEntity requestEntity = requestBuilder.body(selectBody(body, formParams, contentType)); @@ -629,6 +648,29 @@ public class ApiClient { } } + /** + * Add cookies to the request that is being built + * @param cookies The cookies to add + * @param requestBuilder The current request + */ + protected void addCookiesToRequest(MultiValueMap cookies, BodyBuilder requestBuilder) { + if (!cookies.isEmpty()) { + requestBuilder.header("Cookie", buildCookieHeader(cookies)); + } + } + + private String buildCookieHeader(MultiValueMap cookies) { + final StringBuilder cookieValue = new StringBuilder(); + String delimiter = ""; + for (final Map.Entry> entry : cookies.entrySet()) { + for (String value : entry.getValue()) { + cookieValue.append(String.format("%s%s=%s", delimiter, entry.getKey(), entry.getValue())); + delimiter = "; "; + } + } + return cookieValue.toString(); + } + /** * Build the RestTemplate used to make HTTP requests. * @return RestTemplate @@ -668,13 +710,13 @@ public class ApiClient { * @param queryParams The query parameters * @param headerParams The header parameters */ - private void updateParamsForAuth(String[] authNames, MultiValueMap queryParams, HttpHeaders headerParams) { + private void updateParamsForAuth(String[] authNames, MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams) { for (String authName : authNames) { Authentication auth = authentications.get(authName); if (auth == null) { throw new RestClientException("Authentication undefined: " + authName); } - auth.applyToParams(queryParams, headerParams); + auth.applyToParams(queryParams, headerParams, cookieParams); } } diff --git a/libraries/resttemplate/api.mustache b/libraries/resttemplate/api.mustache index 61a0d527204..64655e429d8 100644 --- a/libraries/resttemplate/api.mustache +++ b/libraries/resttemplate/api.mustache @@ -115,6 +115,7 @@ public class {{classname}} { final MultiValueMap queryParams = new LinkedMultiValueMap(); final HttpHeaders headerParams = new HttpHeaders(); + final MultiValueMap cookieParams = new LinkedMultiValueMap(); final MultiValueMap formParams = new LinkedMultiValueMap();{{#hasQueryParams}} {{#queryParams}}queryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{#hasMore}} @@ -122,7 +123,11 @@ public class {{classname}} { {{#headerParams}}if ({{paramName}} != null) headerParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{#hasMore}} - {{/hasMore}}{{/headerParams}}{{/hasHeaderParams}}{{#hasFormParams}} + {{/hasMore}}{{/headerParams}}{{/hasHeaderParams}}{{#hasCookieParams}} + + {{#cookieParams}}if ({{paramName}} != null) + cookieParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{#hasMore}} + {{/hasMore}}{{/cookieParams}}{{/hasCookieParams}}{{#hasFormParams}} {{#formParams}}if ({{paramName}} != null) formParams.add("{{baseName}}", {{#isFile}}new FileSystemResource({{paramName}}){{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} @@ -140,7 +145,7 @@ public class {{classname}} { String[] authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; {{#returnType}}ParameterizedTypeReference<{{{returnType}}}> returnType = new ParameterizedTypeReference<{{{returnType}}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference returnType = new ParameterizedTypeReference() {};{{/returnType}} - return apiClient.invokeAPI(path, HttpMethod.{{httpMethod}}, queryParams, postBody, headerParams, formParams, accept, contentType, authNames, returnType); + return apiClient.invokeAPI(path, HttpMethod.{{httpMethod}}, queryParams, postBody, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType); } {{/operation}} } diff --git a/libraries/resttemplate/auth/ApiKeyAuth.mustache b/libraries/resttemplate/auth/ApiKeyAuth.mustache index 8b8c40fde75..857403b27cf 100644 --- a/libraries/resttemplate/auth/ApiKeyAuth.mustache +++ b/libraries/resttemplate/auth/ApiKeyAuth.mustache @@ -41,7 +41,7 @@ public class ApiKeyAuth implements Authentication { } @Override - public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams) { + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams) { if (apiKey == null) { return; } @@ -55,6 +55,8 @@ public class ApiKeyAuth implements Authentication { queryParams.add(paramName, value); } else if (location.equals("header")) { headerParams.add(paramName, value); - } + } else if (location.equals("cookie")) { + cookieParams.add(paramName, value); + } } } diff --git a/libraries/resttemplate/auth/Authentication.mustache b/libraries/resttemplate/auth/Authentication.mustache index 586de70836a..8e53c2ba08e 100644 --- a/libraries/resttemplate/auth/Authentication.mustache +++ b/libraries/resttemplate/auth/Authentication.mustache @@ -4,10 +4,11 @@ import org.springframework.http.HttpHeaders; import org.springframework.util.MultiValueMap; public interface Authentication { - /** + /** * Apply authentication settings to header and / or query parameters. - * @param queryParams The query parameters for the request + * @param queryParams The query parameters for the request * @param headerParams The header parameters for the request + * @param cookieParams The cookie parameters for the request */ - public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams); + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams); } diff --git a/libraries/resttemplate/auth/HttpBasicAuth.mustache b/libraries/resttemplate/auth/HttpBasicAuth.mustache index 5f535b3698a..5b07cb907bb 100644 --- a/libraries/resttemplate/auth/HttpBasicAuth.mustache +++ b/libraries/resttemplate/auth/HttpBasicAuth.mustache @@ -29,7 +29,7 @@ public class HttpBasicAuth implements Authentication { } @Override - public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams) { + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams) { if (username == null && password == null) { return; } diff --git a/libraries/resttemplate/auth/HttpBearerAuth.mustache b/libraries/resttemplate/auth/HttpBearerAuth.mustache index 0426b7a6984..1d1610c61c4 100644 --- a/libraries/resttemplate/auth/HttpBearerAuth.mustache +++ b/libraries/resttemplate/auth/HttpBearerAuth.mustache @@ -25,7 +25,7 @@ public class HttpBearerAuth implements Authentication { } @Override - public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams) { + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams) { if (bearerToken == null) { return; } diff --git a/libraries/resttemplate/auth/OAuth.mustache b/libraries/resttemplate/auth/OAuth.mustache index fbb2f7f9c72..7889f1582de 100644 --- a/libraries/resttemplate/auth/OAuth.mustache +++ b/libraries/resttemplate/auth/OAuth.mustache @@ -16,7 +16,7 @@ public class OAuth implements Authentication { } @Override - public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams) { + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams) { if (accessToken != null) { headerParams.add(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken); } diff --git a/libraries/retrofit/ApiClient.mustache b/libraries/retrofit/ApiClient.mustache index c3fd7802393..a4a99fea9ee 100644 --- a/libraries/retrofit/ApiClient.mustache +++ b/libraries/retrofit/ApiClient.mustache @@ -70,7 +70,7 @@ public class ApiClient { {{/isBasicBasic}} {{/isBasic}} {{#isApiKey}} - auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"); + auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"); {{/isApiKey}} {{#isOAuth}} auth = new OAuth(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{#hasMore}}, {{/hasMore}}{{/scopes}}"); @@ -152,7 +152,7 @@ public class ApiClient { public S createService(Class serviceClass) { return adapterBuilder.build().create(serviceClass); - + } /** @@ -246,7 +246,7 @@ public class ApiClient { } } } - + /** * Helper method to configure the oauth accessCode/implicit flow parameters * @param clientId Client ID @@ -268,7 +268,7 @@ public class ApiClient { } } } - + /** * Configures a listener which is notified when a new access token is received. * @param accessTokenListener Access token listener @@ -316,7 +316,7 @@ public class ApiClient { public OkHttpClient getOkClient() { return okClient; } - + public void addAuthsToOkClient(OkHttpClient okClient) { for(Interceptor apiAuthorization : apiAuthorizations.values()) { okClient.interceptors().add(apiAuthorization); diff --git a/libraries/retrofit/auth/ApiKeyAuth.mustache b/libraries/retrofit/auth/ApiKeyAuth.mustache index f6a86f22ab4..69205bb2083 100644 --- a/libraries/retrofit/auth/ApiKeyAuth.mustache +++ b/libraries/retrofit/auth/ApiKeyAuth.mustache @@ -46,7 +46,7 @@ public class ApiKeyAuth implements Interceptor { if (newQuery == null) { newQuery = paramValue; } else { - newQuery += "&" + paramValue; + newQuery += "&" + paramValue; } URI newUri; @@ -62,6 +62,10 @@ public class ApiKeyAuth implements Interceptor { request = request.newBuilder() .addHeader(paramName, apiKey) .build(); + } else if ("cookie".equals(location)) { + request = request.newBuilder() + .addHeader("Cookie", String.format("%s=%s", paramName, apiKey)) + .build(); } return chain.proceed(request); } diff --git a/libraries/retrofit2/ApiClient.mustache b/libraries/retrofit2/ApiClient.mustache index 40ab42d2efe..88f0a67004c 100644 --- a/libraries/retrofit2/ApiClient.mustache +++ b/libraries/retrofit2/ApiClient.mustache @@ -71,7 +71,7 @@ public class ApiClient { auth = new HttpBearerAuth("{{scheme}}"); {{/isBasicBasic}}{{/isBasic}} {{#isApiKey}} - auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"); + auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"); {{/isApiKey}} {{#isOAuth}} auth = new OAuth(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{#hasMore}}, {{/hasMore}}{{/scopes}}"); diff --git a/libraries/retrofit2/auth/ApiKeyAuth.mustache b/libraries/retrofit2/auth/ApiKeyAuth.mustache index 2f4bae3dd02..bcc62b284a5 100644 --- a/libraries/retrofit2/auth/ApiKeyAuth.mustache +++ b/libraries/retrofit2/auth/ApiKeyAuth.mustache @@ -62,6 +62,10 @@ public class ApiKeyAuth implements Interceptor { request = request.newBuilder() .addHeader(paramName, apiKey) .build(); + } else if ("cookie".equals(location)) { + request = request.newBuilder() + .addHeader("Cookie", String.format("%s=%s", paramName, apiKey)) + .build(); } return chain.proceed(request); } diff --git a/libraries/retrofit2/play-common/auth/ApiKeyAuth.mustache b/libraries/retrofit2/play-common/auth/ApiKeyAuth.mustache index 5652db326b5..220d896533c 100644 --- a/libraries/retrofit2/play-common/auth/ApiKeyAuth.mustache +++ b/libraries/retrofit2/play-common/auth/ApiKeyAuth.mustache @@ -48,7 +48,7 @@ public class ApiKeyAuth implements Authentication { } @Override - public void applyToParams(List queryParams, Map headerParams) { + public void applyToParams(List queryParams, Map headerParams, Map cookieParams) { if (apiKey == null) { return; } @@ -62,6 +62,8 @@ public class ApiKeyAuth implements Authentication { queryParams.add(new Pair(paramName, value)); } else if ("header".equals(location)) { headerParams.put(paramName, value); + } else if ("cookie".equals(location)) { + cookieParams.put(paramName, value); } } } diff --git a/libraries/retrofit2/play24/ApiClient.mustache b/libraries/retrofit2/play24/ApiClient.mustache index 2395426ab2c..2c1f1f7bbe6 100644 --- a/libraries/retrofit2/play24/ApiClient.mustache +++ b/libraries/retrofit2/play24/ApiClient.mustache @@ -45,7 +45,7 @@ public class ApiClient { authentications = new HashMap<{{#supportJava6}}String, Authentication{{/supportJava6}}>();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} // authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} // authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} - authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} // authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} // Prevent the authentications from being modified. authentications = Collections.unmodifiableMap(authentications); @@ -61,13 +61,14 @@ public class ApiClient { } Map extraHeaders = new HashMap<{{#supportJava6}}String, String{{/supportJava6}}>(); + Map extraCookies = new HashMap<{{#supportJava6}}String, String{{/supportJava6}}>(); List extraQueryParams = new ArrayList<{{#supportJava6}}Pair{{/supportJava6}}>(); for (String authName : authentications.keySet()) { Authentication auth = authentications.get(authName); if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); - auth.applyToParams(extraQueryParams, extraHeaders); + auth.applyToParams(extraQueryParams, extraHeaders, extraCookies); } ObjectMapper mapper = Json.mapper(); @@ -78,7 +79,7 @@ public class ApiClient { .baseUrl(basePath) .addConverterFactory(ScalarsConverterFactory.create()) .addConverterFactory(JacksonConverterFactory.create(mapper)) - .callFactory(new Play24CallFactory(wsClient, extraHeaders, extraQueryParams)) + .callFactory(new Play24CallFactory(wsClient, extraHeaders, extraCookies, extraQueryParams)) .addCallAdapterFactory(new Play24CallAdapterFactory()) .build() .create(serviceClass); @@ -139,5 +140,3 @@ public class ApiClient { } - - diff --git a/libraries/retrofit2/play24/Play24CallFactory.mustache b/libraries/retrofit2/play24/Play24CallFactory.mustache index 5572ac47619..344fadd2e3e 100644 --- a/libraries/retrofit2/play24/Play24CallFactory.mustache +++ b/libraries/retrofit2/play24/Play24CallFactory.mustache @@ -7,6 +7,7 @@ import play.libs.F; import play.libs.ws.WSClient; import play.libs.ws.WSRequest; import play.libs.ws.WSResponse; +import play.libs.ws.WSCookie; import java.io.IOException; import java.net.MalformedURLException; @@ -29,6 +30,9 @@ public class Play24CallFactory implements okhttp3.Call.Factory { /** Extra headers to add to request */ private Map extraHeaders = new HashMap<>(); + /** Extra cookies to add to request */ + private Map extraCookies = new HashMap<>(); + /** Extra query parameters to add to request */ private List extraQueryParams = new ArrayList<>(); @@ -37,10 +41,12 @@ public class Play24CallFactory implements okhttp3.Call.Factory { } public Play24CallFactory(WSClient wsClient, Map extraHeaders, + Map extraCookies, List extraQueryParams) { this.wsClient = wsClient; this.extraHeaders.putAll(extraHeaders); + this.extraCookies.putAll(extraCookies); this.extraQueryParams.addAll(extraQueryParams); } @@ -51,6 +57,9 @@ public class Play24CallFactory implements okhttp3.Call.Factory { for (Map.Entry header : this.extraHeaders.entrySet()) { rb.addHeader(header.getKey(), header.getValue()); } + for (Map.Entry cookie : this.extraCookies.entrySet()) { + rb.addHeader("Cookie", String.format("%s=%s", cookie.getKey(), cookie.getValue())); + } // add extra query params if (!this.extraQueryParams.isEmpty()) { @@ -130,6 +139,7 @@ public class Play24CallFactory implements okhttp3.Call.Factory { try { wsRequest = wsClient.url(request.url().uri().toString()); addHeaders(wsRequest); + addCookies(wsRequest); if (request.body() != null) { addBody(wsRequest); } @@ -149,6 +159,19 @@ public class Play24CallFactory implements okhttp3.Call.Factory { } } + private void addCookies(WSRequest wsRequest) { + final List cookies = request.headers("Cookie"); + if (!cookies.isEmpty()) { + String delimiter = ""; + final StringBuilder cookieHeader = new StringBuilder(); + for (final String cookie : cookies) { + cookieHeader.append(String.format("%s%s", delimiter, cookie)); + delimiter = "; "; + } + wsRequest.setHeader("Cookie", cookieHeader.toString()); + } + } + private void addBody(WSRequest wsRequest) throws IOException { Buffer buffer = new Buffer(); request.body().writeTo(buffer); @@ -186,6 +209,9 @@ public class Play24CallFactory implements okhttp3.Call.Factory { builder.addHeader(entry.getKey(), value); } } + for (final WSCookie cookie : r.getCookies()) { + builder.addHeader("Cookie", String.format("%s=%s", cookie.getName(), cookie.getValue())); + } builder.protocol(Protocol.HTTP_1_1); return builder.build(); diff --git a/libraries/retrofit2/play25/ApiClient.mustache b/libraries/retrofit2/play25/ApiClient.mustache index 221d52c4e9b..90f439091cc 100644 --- a/libraries/retrofit2/play25/ApiClient.mustache +++ b/libraries/retrofit2/play25/ApiClient.mustache @@ -44,7 +44,7 @@ public class ApiClient { // Setup authentications (key: authentication name, value: authentication). authentications = new HashMap<{{#supportJava6}}String, Authentication{{/supportJava6}}>();{{#authMethods}}{{#isBasic}} // authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} - authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"query"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} // authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} // Prevent the authentications from being modified. authentications = Collections.unmodifiableMap(authentications); @@ -60,13 +60,14 @@ public class ApiClient { } Map extraHeaders = new HashMap<{{#supportJava6}}String, String{{/supportJava6}}>(); + Map extraCookies = new HashMap<{{#supportJava6}}String, String{{/supportJava6}}>(); List extraQueryParams = new ArrayList<{{#supportJava6}}Pair{{/supportJava6}}>(); for (String authName : authentications.keySet()) { Authentication auth = authentications.get(authName); if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); - auth.applyToParams(extraQueryParams, extraHeaders); + auth.applyToParams(extraQueryParams, extraHeaders, extraCookies); } ObjectMapper mapper = Json.mapper(); @@ -77,7 +78,7 @@ public class ApiClient { .baseUrl(basePath) .addConverterFactory(ScalarsConverterFactory.create()) .addConverterFactory(JacksonConverterFactory.create(mapper)) - .callFactory(new Play25CallFactory(wsClient, extraHeaders, extraQueryParams)) + .callFactory(new Play25CallFactory(wsClient, extraHeaders, extraCookies, extraQueryParams)) .addCallAdapterFactory(new Play25CallAdapterFactory()) .build() .create(serviceClass); @@ -138,5 +139,3 @@ public class ApiClient { } - - diff --git a/libraries/retrofit2/play25/Play25CallFactory.mustache b/libraries/retrofit2/play25/Play25CallFactory.mustache index fd0057a0e0b..a9f19474f67 100644 --- a/libraries/retrofit2/play25/Play25CallFactory.mustache +++ b/libraries/retrofit2/play25/Play25CallFactory.mustache @@ -9,6 +9,7 @@ import play.libs.ws.WSClient; import play.libs.ws.WSRequest; import play.libs.ws.WSResponse; import play.libs.ws.WSRequestFilter; +import play.libs.ws.WSCookie; import java.io.IOException; import java.net.MalformedURLException; @@ -32,9 +33,12 @@ public class Play25CallFactory implements okhttp3.Call.Factory { /** Extra headers to add to request */ private Map extraHeaders = new HashMap<>(); + /** Extra cookies to add to request */ + private Map extraCookies = new HashMap<>(); + /** Extra query parameters to add to request */ private List extraQueryParams = new ArrayList<>(); - + /** Filters (interceptors) */ private List filters = new ArrayList<>(); @@ -48,10 +52,12 @@ public class Play25CallFactory implements okhttp3.Call.Factory { } public Play25CallFactory(WSClient wsClient, Map extraHeaders, + Map extraCookies, List extraQueryParams) { this.wsClient = wsClient; this.extraHeaders.putAll(extraHeaders); + this.extraCookies.putAll(extraCookies); this.extraQueryParams.addAll(extraQueryParams); } @@ -62,6 +68,9 @@ public class Play25CallFactory implements okhttp3.Call.Factory { for (Map.Entry header : this.extraHeaders.entrySet()) { rb.addHeader(header.getKey(), header.getValue()); } + for (Map.Entry cookie : this.extraCookies.entrySet()) { + rb.addHeader("Cookie", String.format("%s=%s", cookie.getKey(), cookie.getValue())); + } // add extra query params if (!this.extraQueryParams.isEmpty()) { @@ -143,6 +152,7 @@ public class Play25CallFactory implements okhttp3.Call.Factory { try { wsRequest = wsClient.url(request.url().uri().toString()); addHeaders(wsRequest); + addCookies(wsRequest); if (request.body() != null) { addBody(wsRequest); } @@ -163,6 +173,19 @@ public class Play25CallFactory implements okhttp3.Call.Factory { } } + private void addCookies(WSRequest wsRequest) { + final List cookies = request.headers("Cookie"); + if (!cookies.isEmpty()) { + String delimiter = ""; + final StringBuilder cookieHeader = new StringBuilder(); + for (final String cookie : cookies) { + cookieHeader.append(String.format("%s%s", delimiter, cookie)); + delimiter = "; "; + } + wsRequest.setHeader("Cookie", cookieHeader.toString()); + } + } + private void addBody(WSRequest wsRequest) throws IOException { Buffer buffer = new Buffer(); request.body().writeTo(buffer); @@ -198,12 +221,16 @@ public class Play25CallFactory implements okhttp3.Call.Factory { } }); - + for (Map.Entry> entry : r.getAllHeaders().entrySet()) { for (String value : entry.getValue()) { builder.addHeader(entry.getKey(), value); } } + for (final WSCookie cookie : r.getCookies()) { + builder.addHeader("Cookie", String.format("%s=%s", cookie.getName(), cookie.getValue())); + } + builder.protocol(Protocol.HTTP_1_1); return builder.build(); diff --git a/libraries/retrofit2/play26/ApiClient.mustache b/libraries/retrofit2/play26/ApiClient.mustache index 166fb088019..1346ae85694 100644 --- a/libraries/retrofit2/play26/ApiClient.mustache +++ b/libraries/retrofit2/play26/ApiClient.mustache @@ -58,7 +58,7 @@ public class ApiClient { // Setup authentications (key: authentication name, value: authentication). authentications = new HashMap<>();{{#authMethods}}{{#isBasic}} // authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} - authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} // authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} // Prevent the authentications from being modified. authentications = Collections.unmodifiableMap(authentications); @@ -73,17 +73,18 @@ public class ApiClient { } Map extraHeaders = new HashMap<>(); + Map extraCookies = new HashMap<>(); List extraQueryParams = new ArrayList<>(); for (String authName : authentications.keySet()) { Authentication auth = authentications.get(authName); if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); - auth.applyToParams(extraQueryParams, extraHeaders); + auth.applyToParams(extraQueryParams, extraHeaders, extraCookies); } if (callFactory == null) { - callFactory = new Play26CallFactory(wsClient, extraHeaders, extraQueryParams); + callFactory = new Play26CallFactory(wsClient, extraHeaders, extraCookies, extraQueryParams); } if (callAdapterFactory == null) { callAdapterFactory = new Play26CallAdapterFactory(); diff --git a/libraries/retrofit2/play26/Play26CallFactory.mustache b/libraries/retrofit2/play26/Play26CallFactory.mustache index b46b3af0eda..f65c921a752 100644 --- a/libraries/retrofit2/play26/Play26CallFactory.mustache +++ b/libraries/retrofit2/play26/Play26CallFactory.mustache @@ -9,6 +9,8 @@ import play.libs.ws.WSClient; import play.libs.ws.WSRequest; import play.libs.ws.WSResponse; import play.libs.ws.WSRequestFilter; +import play.libs.ws.WSCookie; +import play.libs.ws.WSCookieBuilder; import java.io.IOException; import java.net.MalformedURLException; @@ -32,6 +34,9 @@ public class Play26CallFactory implements okhttp3.Call.Factory { /** Extra headers to add to request */ private Map extraHeaders = new HashMap<>(); + /** Extra cookies to add to request */ + private Map extraCookies = new HashMap<>(); + /** Extra query parameters to add to request */ private List extraQueryParams = new ArrayList<>(); @@ -51,10 +56,12 @@ public class Play26CallFactory implements okhttp3.Call.Factory { } public Play26CallFactory(WSClient wsClient, Map extraHeaders, + Map extraCookies, List extraQueryParams) { this.wsClient = wsClient; this.extraHeaders.putAll(extraHeaders); + this.extraCookies.putAll(extraCookies); this.extraQueryParams.addAll(extraQueryParams); } @@ -70,6 +77,9 @@ public class Play26CallFactory implements okhttp3.Call.Factory { for (Map.Entry header : this.extraHeaders.entrySet()) { rb.addHeader(header.getKey(), header.getValue()); } + for (Map.Entry cookie : this.extraCookies.entrySet()) { + rb.addHeader("Cookie", String.format("%s=%s", cookie.getKey(), cookie.getValue())); + } // add extra query params if (!this.extraQueryParams.isEmpty()) { @@ -160,6 +170,7 @@ public class Play26CallFactory implements okhttp3.Call.Factory { wsRequest.addQueryParameter(queryParam, url.queryParameter(queryParam)); }); addHeaders(wsRequest); + addCookies(wsRequest); if (request.body() != null) { addBody(wsRequest); } @@ -180,6 +191,32 @@ public class Play26CallFactory implements okhttp3.Call.Factory { } } + private void addCookies(WSRequest wsRequest) { + for (final WSCookie cookie : getCookies()) { + wsRequest.addCookie(cookie); + } + } + + List getCookies() { + final List cookies = new ArrayList<>(); + for (final String cookieString : request.headers("Cookie")) { + for (String cookie : cookieString.split(";")) { + cookie = cookie.trim(); + final String[] nameAndValue = cookie.split("="); + if (nameAndValue.length != 2) { + continue; + } + cookies.add( + new WSCookieBuilder() + .setName(nameAndValue[0]) + .setValue(nameAndValue[1]) + .build() + ); + } + } + return cookies; + } + private void addBody(WSRequest wsRequest) throws IOException { MediaType mediaType = request.body().contentType(); if (mediaType != null) { @@ -220,6 +257,9 @@ public class Play26CallFactory implements okhttp3.Call.Factory { builder.addHeader(entry.getKey(), value); } } + for (final WSCookie cookie : r.getCookies()) { + builder.addHeader("Cookie", String.format("%s=%s", cookie.getName(), cookie.getValue())); + } builder.message(r.getStatusText()); builder.protocol(Protocol.HTTP_1_1); diff --git a/libraries/vertx/ApiClient.mustache b/libraries/vertx/ApiClient.mustache index 571a3e4e63f..bc19a925308 100644 --- a/libraries/vertx/ApiClient.mustache +++ b/libraries/vertx/ApiClient.mustache @@ -49,6 +49,7 @@ public class ApiClient { private final String identifier; private MultiMap defaultHeaders = MultiMap.caseInsensitiveMultiMap(); + private MultiMap defaultCookies = MultiMap.caseInsensitiveMultiMap(); private Map authentications; private String basePath = "{{{basePath}}}"; private DateFormat dateFormat; @@ -85,7 +86,7 @@ public class ApiClient { this.authentications = new HashMap<>();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} - authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} // Prevent the authentications from being modified. this.authentications = Collections.unmodifiableMap(authentications); @@ -147,6 +148,15 @@ public class ApiClient { return this; } + public MultiMap getDefaultCookies() { + return defaultHeaders; + } + + public ApiClient addDefaultCookie(String key, String value) { + defaultCookies.add(key, value); + return this; + } + /** * Get authentications (key: authentication name, value: authentication). * @@ -431,6 +441,7 @@ public class ApiClient { * @param queryParams The query parameters * @param body The request body object * @param headerParams The header parameters + * @param cookieParams The cookie parameters * @param formParams The form parameters * @param accepts The request's Accept headers * @param contentTypes The request's Content-Type headers @@ -439,10 +450,10 @@ public class ApiClient { * @param resultHandler The asynchronous response handler */ public void invokeAPI(String path, String method, List queryParams, Object body, MultiMap headerParams, - Map formParams, String[] accepts, String[] contentTypes, String[] authNames, + MultiMap cookieParams, Map formParams, String[] accepts, String[] contentTypes, String[] authNames, TypeReference returnType, Handler> resultHandler) { - updateParamsForAuth(authNames, queryParams, headerParams); + updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); if (accepts != null && accepts.length > 0) { headerParams.add(HttpHeaders.ACCEPT, selectHeaderAccept(accepts)); @@ -477,6 +488,9 @@ public class ApiClient { } }); + final MultiMap cookies = MultiMap.caseInsensitiveMultiMap().addAll(cookieParams).addAll(defaultCookies); + request.putHeader("Cookie", buildCookieHeader(cookies)); + Handler>> responseHandler = buildResponseHandler(returnType, resultHandler); if (body != null) { sendBody(request, responseHandler, body); @@ -489,6 +503,18 @@ public class ApiClient { } } + private String buildCookieHeader(MultiMap cookies) { + final StringBuilder cookieValue = new StringBuilder(); + String delimiter = ""; + for (final Map.Entry entry : cookies.entries()) { + if (entry.getValue() != null) { + cookieValue.append(String.format("%s%s=%s", delimiter, entry.getKey(), entry.getValue())); + delimiter = "; "; + } + } + return cookieValue.toString(); + } + /** * Sanitize filename by removing path. * e.g. ../../sun.gif becomes sun.gif @@ -619,11 +645,11 @@ public class ApiClient { * * @param authNames The authentications to apply */ - protected void updateParamsForAuth(String[] authNames, List queryParams, MultiMap headerParams) { + protected void updateParamsForAuth(String[] authNames, List queryParams, MultiMap headerParams, MultiMap cookieParams) { for (String authName : authNames) { Authentication auth = authentications.get(authName); if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); - auth.applyToParams(queryParams, headerParams); + auth.applyToParams(queryParams, headerParams, cookieParams); } } } diff --git a/libraries/vertx/apiImpl.mustache b/libraries/vertx/apiImpl.mustache index 2cdac042865..5ea569f4ab2 100644 --- a/libraries/vertx/apiImpl.mustache +++ b/libraries/vertx/apiImpl.mustache @@ -72,6 +72,12 @@ public class {{classname}}Impl implements {{classname}} { localVarHeaderParams.add("{{baseName}}", apiClient.parameterToString({{paramName}})); {{/headerParams}} + // cookie params + MultiMap localVarCookieParams = MultiMap.caseInsensitiveMultiMap(); + {{#cookieParams}}if ({{paramName}} != null) + localVarCookieParams.add("{{baseName}}", apiClient.parameterToString({{paramName}})); + {{/cookieParams}} + // form params // TODO: sending files within multipart/form-data is not supported yet (because of vertx web-client) Map localVarFormParams = new HashMap<>(); @@ -83,8 +89,8 @@ public class {{classname}}Impl implements {{classname}} { String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; {{#returnType}} TypeReference<{{{returnType}}}> localVarReturnType = new TypeReference<{{{returnType}}}>() {}; - apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarBody, localVarHeaderParams, localVarFormParams, localVarAccepts, localVarContentTypes, localVarAuthNames, localVarReturnType, resultHandler);{{/returnType}}{{^returnType}} - apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarBody, localVarHeaderParams, localVarFormParams, localVarAccepts, localVarContentTypes, localVarAuthNames, null, resultHandler);{{/returnType}} + apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccepts, localVarContentTypes, localVarAuthNames, localVarReturnType, resultHandler);{{/returnType}}{{^returnType}} + apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccepts, localVarContentTypes, localVarAuthNames, null, resultHandler);{{/returnType}} } {{/operation}} } diff --git a/libraries/vertx/auth/ApiKeyAuth.mustache b/libraries/vertx/auth/ApiKeyAuth.mustache index 43b1866e460..fadbd33e565 100644 --- a/libraries/vertx/auth/ApiKeyAuth.mustache +++ b/libraries/vertx/auth/ApiKeyAuth.mustache @@ -45,7 +45,7 @@ public class ApiKeyAuth implements Authentication { } @Override - public void applyToParams(List queryParams, MultiMap headerParams) { + public void applyToParams(List queryParams, MultiMap headerParams, MultiMap cookieParams) { if (apiKey == null) { return; } @@ -59,6 +59,8 @@ public class ApiKeyAuth implements Authentication { queryParams.add(new Pair(paramName, value)); } else if ("header".equals(location)) { headerParams.add(paramName, value); + } else if ("cookie".equals(location)) { + cookieParams.add(paramName, value); } } } diff --git a/libraries/vertx/auth/Authentication.mustache b/libraries/vertx/auth/Authentication.mustache index 5dccb93f2ac..9d546c30058 100644 --- a/libraries/vertx/auth/Authentication.mustache +++ b/libraries/vertx/auth/Authentication.mustache @@ -13,6 +13,7 @@ public interface Authentication { * * @param queryParams List of query parameters * @param headerParams Map of header parameters + * @param cookieParams Map of cookie parameters */ - void applyToParams(List queryParams, MultiMap headerParams); + void applyToParams(List queryParams, MultiMap headerParams, MultiMap cookieParams); } diff --git a/libraries/vertx/auth/HttpBasicAuth.mustache b/libraries/vertx/auth/HttpBasicAuth.mustache index 43862b508b6..9bca5090a99 100644 --- a/libraries/vertx/auth/HttpBasicAuth.mustache +++ b/libraries/vertx/auth/HttpBasicAuth.mustache @@ -30,7 +30,7 @@ public class HttpBasicAuth implements Authentication { } @Override - public void applyToParams(List queryParams, MultiMap headerParams) { + public void applyToParams(List queryParams, MultiMap headerParams, MultiMap cookieParams) { if (username == null && password == null) { return; } diff --git a/libraries/vertx/auth/HttpBearerAuth.mustache b/libraries/vertx/auth/HttpBearerAuth.mustache index 3dfc23800a6..208eedb7122 100644 --- a/libraries/vertx/auth/HttpBearerAuth.mustache +++ b/libraries/vertx/auth/HttpBearerAuth.mustache @@ -26,7 +26,7 @@ public class HttpBearerAuth implements Authentication { } @Override - public void applyToParams(List queryParams, MultiMap headerParams) { + public void applyToParams(List queryParams, MultiMap headerParams, MultiMap cookieParams) { if (bearerToken == null) { return; } diff --git a/libraries/vertx/auth/OAuth.mustache b/libraries/vertx/auth/OAuth.mustache index f3c5b34ee11..5bebabf90a7 100644 --- a/libraries/vertx/auth/OAuth.mustache +++ b/libraries/vertx/auth/OAuth.mustache @@ -20,7 +20,7 @@ public class OAuth implements Authentication { } @Override - public void applyToParams(List queryParams, MultiMap headerParams) { + public void applyToParams(List queryParams, MultiMap headerParams, MultiMap cookieParams) { if (accessToken != null) { headerParams.add("Authorization", "Bearer " + accessToken); } diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index 2e08f6da5f2..fe6c6d14cb1 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -82,6 +82,7 @@ public class ApiClient { } private HttpHeaders defaultHeaders = new HttpHeaders(); + private MultiValueMap defaultCookies = new LinkedMultiValueMap(); private String basePath = "{{basePath}}"; @@ -129,7 +130,7 @@ public class ApiClient { authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} - authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} // Prevent the authentications from being modified. authentications = Collections.unmodifiableMap(authentications); @@ -298,6 +299,21 @@ public class ApiClient { return this; } + /** + * Add a default cookie. + * + * @param name The cookie's name + * @param value The cookie's value + * @return ApiClient this client + */ + public ApiClient addDefaultCookie(String name, String value) { + if (defaultCookies.containsKey(name)) { + defaultCookies.remove(name); + } + defaultCookies.add(name, value); + return this; + } + /** * Get the date format used to parse/format date parameters. * @return DateFormat format @@ -507,8 +523,8 @@ public class ApiClient { * @param returnType The return type into which to deserialize the response * @return The response body in chosen type */ - public Mono invokeAPI(String path, HttpMethod method, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { - final WebClient.RequestBodySpec requestBuilder = prepareRequest(path, method, queryParams, body, headerParams, formParams, accept, contentType, authNames); + public Mono invokeAPI(String path, HttpMethod method, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap cookieParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { + final WebClient.RequestBodySpec requestBuilder = prepareRequest(path, method, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames); return requestBuilder.retrieve().bodyToMono(returnType); } @@ -528,13 +544,13 @@ public class ApiClient { * @param returnType The return type into which to deserialize the response * @return The response body in chosen type */ - public Flux invokeFluxAPI(String path, HttpMethod method, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { - final WebClient.RequestBodySpec requestBuilder = prepareRequest(path, method, queryParams, body, headerParams, formParams, accept, contentType, authNames); + public Flux invokeFluxAPI(String path, HttpMethod method, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap cookieParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { + final WebClient.RequestBodySpec requestBuilder = prepareRequest(path, method, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames); return requestBuilder.retrieve().bodyToFlux(returnType); } - private WebClient.RequestBodySpec prepareRequest(String path, HttpMethod method, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames) { - updateParamsForAuth(authNames, queryParams, headerParams); + private WebClient.RequestBodySpec prepareRequest(String path, HttpMethod method, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap cookieParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames) { + updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(path); if (queryParams != null) { @@ -563,6 +579,8 @@ public class ApiClient { addHeadersToRequest(headerParams, requestBuilder); addHeadersToRequest(defaultHeaders, requestBuilder); + addCookiesToRequest(cookieParams, requestBuilder); + addCookiesToRequest(defaultCookies, requestBuilder); requestBuilder.body(selectBody(body, formParams, contentType)); return requestBuilder; @@ -584,20 +602,37 @@ public class ApiClient { } } + /** + * Add cookies to the request that is being built + * @param cookies The cookies to add + * @param requestBuilder The current request + */ + protected void addCookiesToRequest(MultiValueMap cookies, WebClient.RequestBodySpec requestBuilder) { + for (Entry> entry : cookies.entrySet()) { + List values = entry.getValue(); + for(String value : values) { + if (value != null) { + requestBuilder.cookie(entry.getKey(), value); + } + } + } + } + /** * Update query and header parameters based on authentication settings. * * @param authNames The authentications to apply * @param queryParams The query parameters * @param headerParams The header parameters + * @param cookieParams the cookie parameters */ - private void updateParamsForAuth(String[] authNames, MultiValueMap queryParams, HttpHeaders headerParams) { + private void updateParamsForAuth(String[] authNames, MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams) { for (String authName : authNames) { Authentication auth = authentications.get(authName); if (auth == null) { throw new RestClientException("Authentication undefined: " + authName); } - auth.applyToParams(queryParams, headerParams); + auth.applyToParams(queryParams, headerParams, cookieParams); } } diff --git a/libraries/webclient/api.mustache b/libraries/webclient/api.mustache index 33da1d14576..9d7c243fe07 100644 --- a/libraries/webclient/api.mustache +++ b/libraries/webclient/api.mustache @@ -72,18 +72,22 @@ public class {{classname}} { final Map uriVariables = new HashMap();{{#pathParams}} uriVariables.put("{{baseName}}", {{{paramName}}});{{/pathParams}}{{/hasPathParams}} String path = UriComponentsBuilder.fromPath("{{{path}}}"){{#hasPathParams}}.buildAndExpand(uriVariables){{/hasPathParams}}{{^hasPathParams}}.build(){{/hasPathParams}}.toUriString(); - + final MultiValueMap queryParams = new LinkedMultiValueMap(); final HttpHeaders headerParams = new HttpHeaders(); + final MultiValueMap cookieParams = new LinkedMultiValueMap(); final MultiValueMap formParams = new LinkedMultiValueMap();{{#hasQueryParams}} - + {{#queryParams}}queryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{#hasMore}} {{/hasMore}}{{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}} - + {{#headerParams}}if ({{paramName}} != null) headerParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{#hasMore}} - {{/hasMore}}{{/headerParams}}{{/hasHeaderParams}}{{#hasFormParams}} - + {{/hasMore}}{{/headerParams}}{{/hasHeaderParams}}{{#hasCookieParams}} + + {{#cookieParams}}cookieParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{#hasMore}} + {{/hasMore}}{{/cookieParams}}{{/hasCookieParams}}{{#hasFormParams}} + {{#formParams}}if ({{paramName}} != null) formParams.add("{{baseName}}", {{#isFile}}new FileSystemResource({{paramName}}){{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} {{/hasMore}}{{/formParams}}{{/hasFormParams}} @@ -100,7 +104,7 @@ public class {{classname}} { String[] authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; {{#returnType}}ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}> returnType = new ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference returnType = new ParameterizedTypeReference() {};{{/returnType}} - return apiClient.{{#isListContainer}}invokeFluxAPI{{/isListContainer}}{{^isListContainer}}invokeAPI{{/isListContainer}}(path, HttpMethod.{{httpMethod}}, queryParams, postBody, headerParams, formParams, accept, contentType, authNames, returnType); + return apiClient.{{#isListContainer}}invokeFluxAPI{{/isListContainer}}{{^isListContainer}}invokeAPI{{/isListContainer}}(path, HttpMethod.{{httpMethod}}, queryParams, postBody, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType); } {{/operation}} } diff --git a/libraries/webclient/auth/ApiKeyAuth.mustache b/libraries/webclient/auth/ApiKeyAuth.mustache index 8b8c40fde75..857403b27cf 100644 --- a/libraries/webclient/auth/ApiKeyAuth.mustache +++ b/libraries/webclient/auth/ApiKeyAuth.mustache @@ -41,7 +41,7 @@ public class ApiKeyAuth implements Authentication { } @Override - public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams) { + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams) { if (apiKey == null) { return; } @@ -55,6 +55,8 @@ public class ApiKeyAuth implements Authentication { queryParams.add(paramName, value); } else if (location.equals("header")) { headerParams.add(paramName, value); - } + } else if (location.equals("cookie")) { + cookieParams.add(paramName, value); + } } } diff --git a/libraries/webclient/auth/Authentication.mustache b/libraries/webclient/auth/Authentication.mustache index 586de70836a..8e53c2ba08e 100644 --- a/libraries/webclient/auth/Authentication.mustache +++ b/libraries/webclient/auth/Authentication.mustache @@ -4,10 +4,11 @@ import org.springframework.http.HttpHeaders; import org.springframework.util.MultiValueMap; public interface Authentication { - /** + /** * Apply authentication settings to header and / or query parameters. - * @param queryParams The query parameters for the request + * @param queryParams The query parameters for the request * @param headerParams The header parameters for the request + * @param cookieParams The cookie parameters for the request */ - public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams); + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams); } diff --git a/libraries/webclient/auth/HttpBasicAuth.mustache b/libraries/webclient/auth/HttpBasicAuth.mustache index 5f535b3698a..5b07cb907bb 100644 --- a/libraries/webclient/auth/HttpBasicAuth.mustache +++ b/libraries/webclient/auth/HttpBasicAuth.mustache @@ -29,7 +29,7 @@ public class HttpBasicAuth implements Authentication { } @Override - public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams) { + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams) { if (username == null && password == null) { return; } diff --git a/libraries/webclient/auth/HttpBearerAuth.mustache b/libraries/webclient/auth/HttpBearerAuth.mustache index 67d5c6c56d0..027c128f474 100644 --- a/libraries/webclient/auth/HttpBearerAuth.mustache +++ b/libraries/webclient/auth/HttpBearerAuth.mustache @@ -25,7 +25,7 @@ public class HttpBearerAuth implements Authentication { } @Override - public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams) { + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams) { if (bearerToken == null) { return; } diff --git a/libraries/webclient/auth/OAuth.mustache b/libraries/webclient/auth/OAuth.mustache index fbb2f7f9c72..7889f1582de 100644 --- a/libraries/webclient/auth/OAuth.mustache +++ b/libraries/webclient/auth/OAuth.mustache @@ -16,7 +16,7 @@ public class OAuth implements Authentication { } @Override - public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams) { + public void applyToParams(MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams) { if (accessToken != null) { headerParams.add(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken); } From 5a0092c28812a4e987679c012648bc1b047ad6b9 Mon Sep 17 00:00:00 2001 From: Slavek Kabrda Date: Tue, 22 Oct 2019 10:17:27 +0200 Subject: [PATCH 162/370] [java][client] Don't include nullable attributes twice in serialized JSON (#3923) * [java][client] Don't include nullable attributes twice in serialized JSON * Get rid of the extra added whitespace * Regenerate samples --- pojo.mustache | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/pojo.mustache b/pojo.mustache index 27bbed28420..1ec15aa3984 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -182,6 +182,10 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela {{#vendorExtensions.extraAnnotation}} {{{vendorExtensions.extraAnnotation}}} {{/vendorExtensions.extraAnnotation}} +{{#vendorExtensions.isJacksonOptionalNullable}} + {{!unannotated, Jackson would pick this up automatically and add it *in addition* to the _JsonNullable getter field}} + @JsonIgnore +{{/vendorExtensions.isJacksonOptionalNullable}} {{^vendorExtensions.isJacksonOptionalNullable}}{{#jackson}}{{> jackson_annotations}}{{/jackson}}{{/vendorExtensions.isJacksonOptionalNullable}} public {{{datatypeWithEnum}}} {{getter}}() { {{#vendorExtensions.isJacksonOptionalNullable}} @@ -202,16 +206,15 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela public JsonNullable<{{{datatypeWithEnum}}}> {{getter}}_JsonNullable() { return {{name}}; } - {{/vendorExtensions.isJacksonOptionalNullable}} - - {{^isReadOnly}} - {{#vendorExtensions.isJacksonOptionalNullable}} + {{/vendorExtensions.isJacksonOptionalNullable}}{{#vendorExtensions.isJacksonOptionalNullable}} @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) - public void {{setter}}_JsonNullable(JsonNullable<{{{datatypeWithEnum}}}> {{name}}) { + {{#isReadOnly}}private{{/isReadOnly}}{{^isReadOnly}}public{{/isReadOnly}} void {{setter}}_JsonNullable(JsonNullable<{{{datatypeWithEnum}}}> {{name}}) { + {{! For getters/setters that have name differing from attribute name, we must include setter (albeit private) for jackson to be able to set the attribute}} this.{{name}} = {{name}}; } {{/vendorExtensions.isJacksonOptionalNullable}} + {{^isReadOnly}} public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { {{#vendorExtensions.isJacksonOptionalNullable}} this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); From 5b36c0ac45f4d445b458c2aeef7e6372d13e261e Mon Sep 17 00:00:00 2001 From: Fabio Kung Date: Thu, 24 Oct 2019 03:15:10 -0700 Subject: [PATCH 163/370] okhttp-gson: fix SSL settings with okhttp3 (#4226) The old code used to work with older okhttp (< 3), but will throw NullPointerExceptions with okhttp3. --- libraries/okhttp-gson/ApiClient.mustache | 55 +++++++++++++----------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index f81ed11659b..3856ddf8c19 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -4,6 +4,7 @@ package {{invokerPackage}}; import okhttp3.*; import okhttp3.internal.http.HttpMethod; +import okhttp3.internal.tls.OkHostnameVerifier; import okhttp3.logging.HttpLoggingInterceptor; import okhttp3.logging.HttpLoggingInterceptor.Level; import okio.BufferedSink; @@ -1340,8 +1341,8 @@ public class ApiClient { */ private void applySslSettings() { try { - TrustManager[] trustManagers = null; - HostnameVerifier hostnameVerifier = null; + TrustManager[] trustManagers; + HostnameVerifier hostnameVerifier; if (!verifyingSsl) { trustManagers = new TrustManager[]{ new X509TrustManager() { @@ -1359,40 +1360,42 @@ public class ApiClient { } } }; - SSLContext sslContext = SSLContext.getInstance("TLS"); hostnameVerifier = new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }; - } else if (sslCaCert != null) { - char[] password = null; // Any password will work. - CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); - Collection certificates = certificateFactory.generateCertificates(sslCaCert); - if (certificates.isEmpty()) { - throw new IllegalArgumentException("expected non-empty set of trusted certificates"); - } - KeyStore caKeyStore = newEmptyKeyStore(password); - int index = 0; - for (Certificate certificate : certificates) { - String certificateAlias = "ca" + Integer.toString(index++); - caKeyStore.setCertificateEntry(certificateAlias, certificate); - } + } else { TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - trustManagerFactory.init(caKeyStore); - trustManagers = trustManagerFactory.getTrustManagers(); - } - if (keyManagers != null || trustManagers != null) { - SSLContext sslContext = SSLContext.getInstance("TLS"); - sslContext.init(keyManagers, trustManagers, new SecureRandom()); - httpClient = httpClient.newBuilder().sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustManagers[0]).build(); - } else { - httpClient = httpClient.newBuilder().sslSocketFactory(null, (X509TrustManager) trustManagers[0]).build(); + if (sslCaCert == null) { + trustManagerFactory.init((KeyStore) null); + } else { + char[] password = null; // Any password will work. + CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); + Collection certificates = certificateFactory.generateCertificates(sslCaCert); + if (certificates.isEmpty()) { + throw new IllegalArgumentException("expected non-empty set of trusted certificates"); + } + KeyStore caKeyStore = newEmptyKeyStore(password); + int index = 0; + for (Certificate certificate : certificates) { + String certificateAlias = "ca" + Integer.toString(index++); + caKeyStore.setCertificateEntry(certificateAlias, certificate); + } + trustManagerFactory.init(caKeyStore); + } + trustManagers = trustManagerFactory.getTrustManagers(); + hostnameVerifier = OkHostnameVerifier.INSTANCE; } - httpClient = httpClient.newBuilder().hostnameVerifier(hostnameVerifier).build(); + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(keyManagers, trustManagers, new SecureRandom()); + httpClient = httpClient.newBuilder() + .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustManagers[0]) + .hostnameVerifier(hostnameVerifier) + .build(); } catch (GeneralSecurityException e) { throw new RuntimeException(e); } From 08d32e7b52bd31cb54d752cf1c27e63acca6ef8d Mon Sep 17 00:00:00 2001 From: Addy Naik <48064952+addynaik@users.noreply.github.com> Date: Tue, 29 Oct 2019 01:21:17 -0400 Subject: [PATCH 164/370] Add bearer token authentication documentation to template (#4278) * add bearer token authenticationdocumentation to template * Use correct method * Add the get parameter back --- README.mustache | 7 +++++-- api_doc.mustache | 7 +++++-- libraries/okhttp-gson/README.mustache | 7 +++++-- libraries/okhttp-gson/api_doc.mustache | 7 +++++-- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/README.mustache b/README.mustache index ff0026651fe..f1bb9f234cd 100644 --- a/README.mustache +++ b/README.mustache @@ -89,11 +89,14 @@ public class {{{classname}}}Example { public static void main(String[] args) { ApiClient defaultClient = Configuration.getDefaultApiClient(); defaultClient.setBasePath("{{{basePath}}}"); - {{#hasAuthMethods}}{{#authMethods}}{{#isBasic}} + {{#hasAuthMethods}}{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} // Configure HTTP basic authorization: {{{name}}} HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); {{{name}}}.setUsername("YOUR USERNAME"); - {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasic}}{{#isApiKey}} + {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasicBasic}}{{#isBasicBearer}} + // Configure HTTP bearer authorization: {{{name}}} + HttpBearerAuth {{{name}}} = (HttpBearerAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setBearerToken("BEARER TOKEN");{{/isBasicBearer}}{{/isBasic}}{{#isApiKey}} // Configure API key authorization: {{{name}}} ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); {{{name}}}.setApiKey("YOUR API KEY"); diff --git a/api_doc.mustache b/api_doc.mustache index 3a9d2886266..edc837f486e 100644 --- a/api_doc.mustache +++ b/api_doc.mustache @@ -36,11 +36,14 @@ public class Example { ApiClient defaultClient = Configuration.getDefaultApiClient(); defaultClient.setBasePath("{{{basePath}}}"); {{#hasAuthMethods}} - {{#authMethods}}{{#isBasic}} + {{#authMethods}}{{#isBasic}}{{#isBasicBasic}} // Configure HTTP basic authorization: {{{name}}} HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); {{{name}}}.setUsername("YOUR USERNAME"); - {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasic}}{{#isApiKey}} + {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasicBasic}}{{#isBasicBearer}} + // Configure HTTP bearer authorization: {{{name}}} + HttpBearerAuth {{{name}}} = (HttpBearerAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setBearerToken("BEARER TOKEN");{{/isBasicBearer}}{{/isBasic}}{{#isApiKey}} // Configure API key authorization: {{{name}}} ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); {{{name}}}.setApiKey("YOUR API KEY"); diff --git a/libraries/okhttp-gson/README.mustache b/libraries/okhttp-gson/README.mustache index 07636f62a4e..e459ad31713 100644 --- a/libraries/okhttp-gson/README.mustache +++ b/libraries/okhttp-gson/README.mustache @@ -90,11 +90,14 @@ public class Example { ApiClient defaultClient = Configuration.getDefaultApiClient(); defaultClient.setBasePath("{{{basePath}}}"); {{#hasAuthMethods}} - {{#authMethods}}{{#isBasic}} + {{#authMethods}}{{#isBasic}}{{#isBasicBasic}} // Configure HTTP basic authorization: {{{name}}} HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); {{{name}}}.setUsername("YOUR USERNAME"); - {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasic}}{{#isApiKey}} + {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasicBasic}}{{#isBasicBearer}} + // Configure HTTP bearer authorization: {{{name}}} + HttpBearerAuth {{{name}}} = (HttpBearerAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setBearerToken("BEARER TOKEN");{{/isBasicBearer}}{{/isBasic}}{{#isApiKey}} // Configure API key authorization: {{{name}}} ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); {{{name}}}.setApiKey("YOUR API KEY"); diff --git a/libraries/okhttp-gson/api_doc.mustache b/libraries/okhttp-gson/api_doc.mustache index 720b4d3c5ee..c7ce067ce13 100644 --- a/libraries/okhttp-gson/api_doc.mustache +++ b/libraries/okhttp-gson/api_doc.mustache @@ -34,11 +34,14 @@ public class Example { ApiClient defaultClient = Configuration.getDefaultApiClient(); defaultClient.setBasePath("{{{basePath}}}"); {{#hasAuthMethods}} - {{#authMethods}}{{#isBasic}} + {{#authMethods}}{{#isBasic}}{{#isBasicBasic}} // Configure HTTP basic authorization: {{{name}}} HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); {{{name}}}.setUsername("YOUR USERNAME"); - {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasic}}{{#isApiKey}} + {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasicBasic}}{{#isBasicBearer}} + // Configure HTTP bearer authorization: {{{name}}} + HttpBearerAuth {{{name}}} = (HttpBearerAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setBearerToken("BEARER TOKEN");{{/isBasicBearer}}{{/isBasic}}{{#isApiKey}} // Configure API key authorization: {{{name}}} ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); {{{name}}}.setApiKey("YOUR API KEY"); From d422ef47b01fe2a02d8e562957547a9dd603a1fe Mon Sep 17 00:00:00 2001 From: Sai Giridhar P Date: Wed, 30 Oct 2019 14:39:25 +0530 Subject: [PATCH 165/370] feat(documentation): Adding model documentation (#4308) --- pojo_doc.mustache | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pojo_doc.mustache b/pojo_doc.mustache index 38a52e44eb5..d03e0275726 100644 --- a/pojo_doc.mustache +++ b/pojo_doc.mustache @@ -1,5 +1,7 @@ # {{classname}} +{{#description}}{{description}} +{{/description}} ## Properties Name | Type | Description | Notes From 5c78753b13787082595bb6e5eabcf23e6048b66f Mon Sep 17 00:00:00 2001 From: William Cheng Date: Thu, 31 Oct 2019 09:10:05 +0800 Subject: [PATCH 166/370] Do not HTML escaped the description in the doc (#4321) * html escaped the description in the doc * update python oas3 sample --- pojo_doc.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pojo_doc.mustache b/pojo_doc.mustache index d03e0275726..313e61ba7e6 100644 --- a/pojo_doc.mustache +++ b/pojo_doc.mustache @@ -1,6 +1,6 @@ # {{classname}} -{{#description}}{{description}} +{{#description}}{{&description}} {{/description}} ## Properties From bd52a262cd9b3ea1b821a78aa0baf898b850e2a6 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 1 Nov 2019 11:16:36 +0800 Subject: [PATCH 167/370] fix security alerts reported by github (#4344) --- libraries/feign/build.gradle.mustache | 2 +- libraries/feign/build.sbt.mustache | 2 +- libraries/feign/pom.mustache | 2 +- libraries/webclient/pom.mustache | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index d652ecc8e9d..e70e3e2945f 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -121,7 +121,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" jackson_version = "2.9.10" - jackson_databind_version = "2.9.10" + jackson_databind_version = "2.9.10.1" jackson_databind_nullable_version = "0.2.0" {{#threetenbp}} jackson_threetenbp_version = "2.9.10" diff --git a/libraries/feign/build.sbt.mustache b/libraries/feign/build.sbt.mustache index c0622eefdc5..61273efb773 100644 --- a/libraries/feign/build.sbt.mustache +++ b/libraries/feign/build.sbt.mustache @@ -16,7 +16,7 @@ lazy val root = (project in file(".")). "io.github.openfeign.form" % "feign-form" % "2.1.0" % "compile", "com.fasterxml.jackson.core" % "jackson-core" % "2.9.10" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.10" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10.1" % "compile", "com.fasterxml.jackson.datatype" % "jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}" % "2.9.10" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index ffa03e01b1c..7910027eb91 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -316,7 +316,7 @@ 2.1.0 2.9.10 0.2.0 - 2.9.10 + 2.9.10.1 {{#threetenbp}} 2.9.10 {{/threetenbp}} diff --git a/libraries/webclient/pom.mustache b/libraries/webclient/pom.mustache index c8651f58c58..4b11dd276bb 100644 --- a/libraries/webclient/pom.mustache +++ b/libraries/webclient/pom.mustache @@ -144,7 +144,7 @@ 1.5.22 5.0.7.RELEASE 2.9.10 - 2.9.10 + 2.9.10.1 0.2.0 4.12 3.1.8.RELEASE From 26b651982ce83673b1dcb70373cdc9b8b5c98fbd Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 6 Nov 2019 10:27:08 +0800 Subject: [PATCH 168/370] Fix Jackson databind security issue (#4370) * fix jackson databind security issue * update groovy sample * fix groovy dep version --- build.gradle.mustache | 2 +- libraries/google-api-client/build.gradle.mustache | 2 +- libraries/google-api-client/build.sbt.mustache | 2 +- libraries/google-api-client/pom.mustache | 2 +- libraries/jersey2/build.gradle.mustache | 2 +- libraries/jersey2/build.sbt.mustache | 2 +- libraries/jersey2/pom.mustache | 2 +- libraries/resteasy/build.gradle.mustache | 2 +- libraries/resteasy/build.sbt.mustache | 2 +- libraries/resteasy/pom.mustache | 2 +- libraries/resttemplate/build.gradle.mustache | 2 +- libraries/resttemplate/pom.mustache | 2 +- libraries/retrofit2/build.gradle.mustache | 2 +- libraries/retrofit2/build.sbt.mustache | 2 +- libraries/retrofit2/pom.mustache | 2 +- libraries/vertx/build.gradle.mustache | 2 +- libraries/vertx/pom.mustache | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/build.gradle.mustache b/build.gradle.mustache index 2fa65868357..47059d550b1 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -137,7 +137,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" jackson_version = "2.9.10" - jackson_databind_version = "2.9.10" + jackson_databind_version = "2.9.10.1" jackson_databind_nullable_version = "0.2.0" jersey_version = "1.19.4" jodatime_version = "2.9.9" diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache index 9c8d7a8d30e..57deb75c560 100644 --- a/libraries/google-api-client/build.gradle.mustache +++ b/libraries/google-api-client/build.gradle.mustache @@ -121,7 +121,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" jackson_version = "2.9.10" - jackson_databind_version = "2.9.10" + jackson_databind_version = "2.9.10.1" jackson_databind_nullable_version = "0.2.0" google_api_client_version = "1.23.0" jersey_common_version = "2.25.1" diff --git a/libraries/google-api-client/build.sbt.mustache b/libraries/google-api-client/build.sbt.mustache index 2c1ff450e94..2af4dd8dfdb 100644 --- a/libraries/google-api-client/build.sbt.mustache +++ b/libraries/google-api-client/build.sbt.mustache @@ -14,7 +14,7 @@ lazy val root = (project in file(".")). "org.glassfish.jersey.core" % "jersey-common" % "2.25.1", "com.fasterxml.jackson.core" % "jackson-core" % "2.9.10" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.10" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10.1" % "compile", {{#withXml}} "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.9.10" % "compile", {{/withXml}} diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index 7be1da91a4e..89f8be6132c 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -307,7 +307,7 @@ 1.30.2 2.25.1 2.9.10 - 2.9.10 + 2.9.10.1 0.2.0 {{#joda}} 2.9.9 diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index ec3b383eea0..998d6ebc8b4 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -120,7 +120,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" jackson_version = "2.9.10" - jackson_databind_version = "2.9.10" + jackson_databind_version = "2.9.10.1" jackson_databind_nullable_version = "0.2.0" {{#supportJava6}} jersey_version = "2.6" diff --git a/libraries/jersey2/build.sbt.mustache b/libraries/jersey2/build.sbt.mustache index e31be933919..61f8e283787 100644 --- a/libraries/jersey2/build.sbt.mustache +++ b/libraries/jersey2/build.sbt.mustache @@ -15,7 +15,7 @@ lazy val root = (project in file(".")). "org.glassfish.jersey.media" % "jersey-media-json-jackson" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, "com.fasterxml.jackson.core" % "jackson-core" % "2.9.10" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.10" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10.1" % "compile", {{#joda}} "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.10" % "compile", {{/joda}} diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 31a1843080e..5a108ed6ee4 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -361,7 +361,7 @@ 3.6 {{/supportJava6}} 2.9.10 - 2.9.10 + 2.9.10.1 0.2.0 {{#threetenbp}} 2.9.10 diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index e45659de524..bf9f5408c2a 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -120,7 +120,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" jackson_version = "2.9.10" - jackson_databind_version = "2.9.10" + jackson_databind_version = "2.9.10.1" jackson_databind_nullable_version = "0.2.0" threetenbp_version = "2.9.10" resteasy_version = "3.1.3.Final" diff --git a/libraries/resteasy/build.sbt.mustache b/libraries/resteasy/build.sbt.mustache index bcedcaec343..95ab58d1f9d 100644 --- a/libraries/resteasy/build.sbt.mustache +++ b/libraries/resteasy/build.sbt.mustache @@ -15,7 +15,7 @@ lazy val root = (project in file(".")). "org.jboss.resteasy" % "resteasy-jackson2-provider" % "3.1.3.Final" % "compile", "com.fasterxml.jackson.core" % "jackson-core" % "2.9.10" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.10" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10.1" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", {{#java8}} "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.10" % "compile", diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index 1a12889b965..16a1a3fe1fa 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -295,7 +295,7 @@ 1.5.22 3.1.3.Final 2.9.10 - 2.9.10 + 2.9.10.1 0.2.0 2.9.10 {{^java8}} diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index 7601a8180d1..1c631f1a557 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -121,7 +121,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" jackson_version = "2.9.10" - jackson_databind_version = "2.9.10" + jackson_databind_version = "2.9.10.1" jackson_databind_nullable_version = "0.2.0" spring_web_version = "4.3.9.RELEASE" jodatime_version = "2.9.9" diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache index a717eb44127..eb3ddfb12f9 100644 --- a/libraries/resttemplate/pom.mustache +++ b/libraries/resttemplate/pom.mustache @@ -310,7 +310,7 @@ 1.5.22 4.3.9.RELEASE 2.9.10 - 2.9.10 + 2.9.10.1 0.2.0 {{#joda}} 2.9.9 diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index e7f778ba5a0..ddeb061cd02 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -132,7 +132,7 @@ ext { {{/play25}} {{#play26}} jackson_version = "2.9.10" - jackson_databind_version = "2.9.10" + jackson_databind_version = "2.9.10.1" jackson_databind_nullable_version = "0.2.0" play_version = "2.6.7" {{/play26}} diff --git a/libraries/retrofit2/build.sbt.mustache b/libraries/retrofit2/build.sbt.mustache index c6fc88aa0aa..ecae66c6a85 100644 --- a/libraries/retrofit2/build.sbt.mustache +++ b/libraries/retrofit2/build.sbt.mustache @@ -25,7 +25,7 @@ lazy val root = (project in file(".")). "com.typesafe.play" % "play-java-ws_2.11" % "2.5.15" % "compile", "com.fasterxml.jackson.core" % "jackson-core" % "2.9.10" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.10" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10.1" % "compile", {{/play25}} {{#play26}} "com.typesafe.play" % "play-ahc-ws_2.12" % "2.6.7" % "compile", diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index d32445d02f1..428e4203763 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -375,7 +375,7 @@ 1.8.3 1.5.22 {{#usePlayWS}} - 2.9.10 + 2.9.10.1 {{#play24}} 2.6.6 2.4.11 diff --git a/libraries/vertx/build.gradle.mustache b/libraries/vertx/build.gradle.mustache index 68dce22f06a..862aee9f785 100644 --- a/libraries/vertx/build.gradle.mustache +++ b/libraries/vertx/build.gradle.mustache @@ -29,7 +29,7 @@ task execute(type:JavaExec) { ext { swagger_annotations_version = "1.5.21" jackson_version = "2.9.10" - jackson_databind_version = "2.9.10" + jackson_databind_version = "2.9.10.1" vertx_version = "3.4.2" junit_version = "4.12" } diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache index df558861387..cdbb87d1800 100644 --- a/libraries/vertx/pom.mustache +++ b/libraries/vertx/pom.mustache @@ -290,7 +290,7 @@ 3.4.2 1.5.22 2.9.10 - 2.9.10 + 2.9.10.1 0.2.0 4.12 From 78be2c87a81519d5e544ebe5ec27e17d5d5784a7 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Date: Tue, 12 Nov 2019 09:15:34 +0100 Subject: [PATCH 169/370] [Java]: Client resttemplate and webclient: array parameters of type integer in path badly generated (#4379) * 4375: Client resttemplate and webclient: array parameters of type integer in path badly generated * 4375: Fix samples * 4375: Fix samples * 4375: Fix samples --- libraries/resttemplate/ApiClient.mustache | 4 ++-- libraries/webclient/ApiClient.mustache | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/resttemplate/ApiClient.mustache b/libraries/resttemplate/ApiClient.mustache index 5abf07fc02c..2a327daca24 100644 --- a/libraries/resttemplate/ApiClient.mustache +++ b/libraries/resttemplate/ApiClient.mustache @@ -84,7 +84,7 @@ public class ApiClient { this.separator = separator; } - private String collectionToString(Collection collection) { + private String collectionToString(Collection collection) { return StringUtils.collectionToDelimitedString(collection, separator); } } @@ -407,7 +407,7 @@ public class ApiClient { * @param values The values of the parameter. * @return String representation of the parameter */ - public String collectionPathParameterToString(CollectionFormat collectionFormat, Collection values) { + public String collectionPathParameterToString(CollectionFormat collectionFormat, Collection values) { // create the value based on the collection format if (CollectionFormat.MULTI.equals(collectionFormat)) { // not valid for path params diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index fe6c6d14cb1..5437bb15b32 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -76,7 +76,7 @@ public class ApiClient { this.separator = separator; } - private String collectionToString(Collection collection) { + private String collectionToString(Collection collection) { return StringUtils.collectionToDelimitedString(collection, separator); } } From 81fdc4ff5f52572ce59e4980205068dc799026f9 Mon Sep 17 00:00:00 2001 From: atsharp Date: Tue, 12 Nov 2019 02:17:38 -0600 Subject: [PATCH 170/370] [Java] Refactor webClient generator to use URI templates to capture correct metrics (#4314) * Fixing URI templating for webclients to support Spring metric collection * Revert accidental change to test --- libraries/webclient/ApiClient.mustache | 14 ++++++++------ libraries/webclient/api.mustache | 9 ++++----- libraries/webclient/pom.mustache | 2 +- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index 5437bb15b32..013ab6dc0e5 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -513,6 +513,7 @@ public class ApiClient { * @param the return type to use * @param path The sub-path of the HTTP URL * @param method The request method + * @param pathParams The path parameters * @param queryParams The query parameters * @param body The request body object * @param headerParams The header parameters @@ -523,8 +524,8 @@ public class ApiClient { * @param returnType The return type into which to deserialize the response * @return The response body in chosen type */ - public Mono invokeAPI(String path, HttpMethod method, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap cookieParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { - final WebClient.RequestBodySpec requestBuilder = prepareRequest(path, method, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames); + public Mono invokeAPI(String path, HttpMethod method, Map pathParams, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap cookieParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { + final WebClient.RequestBodySpec requestBuilder = prepareRequest(path, method, pathParams, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames); return requestBuilder.retrieve().bodyToMono(returnType); } @@ -534,6 +535,7 @@ public class ApiClient { * @param the return type to use * @param path The sub-path of the HTTP URL * @param method The request method + * @param pathParams The path parameters * @param queryParams The query parameters * @param body The request body object * @param headerParams The header parameters @@ -544,12 +546,12 @@ public class ApiClient { * @param returnType The return type into which to deserialize the response * @return The response body in chosen type */ - public Flux invokeFluxAPI(String path, HttpMethod method, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap cookieParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { - final WebClient.RequestBodySpec requestBuilder = prepareRequest(path, method, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames); + public Flux invokeFluxAPI(String path, HttpMethod method, Map pathParams, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap cookieParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { + final WebClient.RequestBodySpec requestBuilder = prepareRequest(path, method, pathParams, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames); return requestBuilder.retrieve().bodyToFlux(returnType); } - private WebClient.RequestBodySpec prepareRequest(String path, HttpMethod method, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap cookieParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames) { + private WebClient.RequestBodySpec prepareRequest(String path, HttpMethod method, Map pathParams, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap cookieParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames) { updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(path); @@ -569,7 +571,7 @@ public class ApiClient { builder.queryParams(queryParams); } - final WebClient.RequestBodySpec requestBuilder = webClient.method(method).uri(builder.build(true).toUri()); + final WebClient.RequestBodySpec requestBuilder = webClient.method(method).uri(builder.encode().toUriString(), pathParams); if(accept != null) { requestBuilder.accept(accept.toArray(new MediaType[accept.size()])); } diff --git a/libraries/webclient/api.mustache b/libraries/webclient/api.mustache index 9d7c243fe07..3212ffb1438 100644 --- a/libraries/webclient/api.mustache +++ b/libraries/webclient/api.mustache @@ -67,11 +67,10 @@ public class {{classname}} { if ({{paramName}} == null) { throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); } - {{/required}}{{/allParams}}{{#hasPathParams}} + {{/required}}{{/allParams}} // create path and map variables - final Map uriVariables = new HashMap();{{#pathParams}} - uriVariables.put("{{baseName}}", {{{paramName}}});{{/pathParams}}{{/hasPathParams}} - String path = UriComponentsBuilder.fromPath("{{{path}}}"){{#hasPathParams}}.buildAndExpand(uriVariables){{/hasPathParams}}{{^hasPathParams}}.build(){{/hasPathParams}}.toUriString(); + final Map pathParams = new HashMap();{{#hasPathParams}}{{#pathParams}} + pathParams.put("{{baseName}}", {{{paramName}}});{{/pathParams}}{{/hasPathParams}} final MultiValueMap queryParams = new LinkedMultiValueMap(); final HttpHeaders headerParams = new HttpHeaders(); @@ -104,7 +103,7 @@ public class {{classname}} { String[] authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; {{#returnType}}ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}> returnType = new ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference returnType = new ParameterizedTypeReference() {};{{/returnType}} - return apiClient.{{#isListContainer}}invokeFluxAPI{{/isListContainer}}{{^isListContainer}}invokeAPI{{/isListContainer}}(path, HttpMethod.{{httpMethod}}, queryParams, postBody, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType); + return apiClient.{{#isListContainer}}invokeFluxAPI{{/isListContainer}}{{^isListContainer}}invokeAPI{{/isListContainer}}("{{{path}}}", HttpMethod.{{httpMethod}}, pathParams, queryParams, postBody, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType); } {{/operation}} } diff --git a/libraries/webclient/pom.mustache b/libraries/webclient/pom.mustache index 4b11dd276bb..f32f6ee5f45 100644 --- a/libraries/webclient/pom.mustache +++ b/libraries/webclient/pom.mustache @@ -142,7 +142,7 @@ UTF-8 1.5.22 - 5.0.7.RELEASE + 5.0.8.RELEASE 2.9.10 2.9.10.1 0.2.0 From 0efbb92d78281c9e7b1d42e6e965edbb6e95796e Mon Sep 17 00:00:00 2001 From: Eric Feliksik Date: Wed, 13 Nov 2019 06:28:50 +0100 Subject: [PATCH 171/370] Re-interrupt the thread in the generated code (#4382) * Re-interrupt the thread in the generated code, otherwise the client has to check for the type of the cause of the thrown exception. * update samples --- libraries/native/api.mustache | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/native/api.mustache b/libraries/native/api.mustache index f045c81743e..8c545a015f4 100644 --- a/libraries/native/api.mustache +++ b/libraries/native/api.mustache @@ -148,7 +148,10 @@ public class {{classname}} { {{#returnType}} return memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference<{{{returnType}}}>() {}); {{/returnType}} - } catch (IOException | InterruptedException e) { + } catch (IOException e) { + throw new ApiException(e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); throw new ApiException(e); } } From 75a0fd01ce9af84163e9aa05ce484e091a4dd0c5 Mon Sep 17 00:00:00 2001 From: Min Kim <291271447@qq.com> Date: Thu, 14 Nov 2019 13:09:23 +0800 Subject: [PATCH 172/370] recursive equal on reflection (#4475) --- pojo.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pojo.mustache b/pojo.mustache index 1ec15aa3984..9814954cc4b 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -231,7 +231,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcela @Override public boolean equals(java.lang.Object o) { {{#useReflectionEqualsHashCode}} - return EqualsBuilder.reflectionEquals(this, o); + return EqualsBuilder.reflectionEquals(this, o, false, null, true); {{/useReflectionEqualsHashCode}} {{^useReflectionEqualsHashCode}} if (this == o) { From 179231ab3a548ce78949b28abfe9268c893c9f3a Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Date: Sun, 17 Nov 2019 02:01:40 +0100 Subject: [PATCH 173/370] [BUG] [Java] Client resttemplate and webclient. Form Params are badly added when they are lists (#4461) * 4383: Client resttemplate and webclient. Form Params are badly added when they are lists * 4383: Force redeploy * 4383: Fix test * 4383: Fix map * 4383: revert change * 4383: Fix test resttemplate-withXml --- libraries/resttemplate/api.mustache | 4 ++-- libraries/webclient/api.mustache | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/resttemplate/api.mustache b/libraries/resttemplate/api.mustache index 64655e429d8..dc6d434c3e4 100644 --- a/libraries/resttemplate/api.mustache +++ b/libraries/resttemplate/api.mustache @@ -116,7 +116,7 @@ public class {{classname}} { final MultiValueMap queryParams = new LinkedMultiValueMap(); final HttpHeaders headerParams = new HttpHeaders(); final MultiValueMap cookieParams = new LinkedMultiValueMap(); - final MultiValueMap formParams = new LinkedMultiValueMap();{{#hasQueryParams}} + final MultiValueMap formParams = new LinkedMultiValueMap();{{#hasQueryParams}} {{#queryParams}}queryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{#hasMore}} {{/hasMore}}{{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}} @@ -130,7 +130,7 @@ public class {{classname}} { {{/hasMore}}{{/cookieParams}}{{/hasCookieParams}}{{#hasFormParams}} {{#formParams}}if ({{paramName}} != null) - formParams.add("{{baseName}}", {{#isFile}}new FileSystemResource({{paramName}}){{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} + formParams.{{^collectionFormat}}add{{/collectionFormat}}{{#collectionFormat}}put{{/collectionFormat}}("{{baseName}}", {{#isFile}}new FileSystemResource({{paramName}}){{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} {{/hasMore}}{{/formParams}}{{/hasFormParams}} final String[] accepts = { {{#hasProduces}} diff --git a/libraries/webclient/api.mustache b/libraries/webclient/api.mustache index 3212ffb1438..96066577b0e 100644 --- a/libraries/webclient/api.mustache +++ b/libraries/webclient/api.mustache @@ -88,7 +88,7 @@ public class {{classname}} { {{/hasMore}}{{/cookieParams}}{{/hasCookieParams}}{{#hasFormParams}} {{#formParams}}if ({{paramName}} != null) - formParams.add("{{baseName}}", {{#isFile}}new FileSystemResource({{paramName}}){{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} + formParams.add{{#collectionFormat}}All{{/collectionFormat}}("{{baseName}}", {{#isFile}}new FileSystemResource({{paramName}}){{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} {{/hasMore}}{{/formParams}}{{/hasFormParams}} final String[] accepts = { {{#hasProduces}} From 7a237d59c989c5c7748831f40cb171a8aded1dbd Mon Sep 17 00:00:00 2001 From: Toby Murray Date: Mon, 25 Nov 2019 09:34:31 -0500 Subject: [PATCH 174/370] [JAVA] Update Gradle in generated Java projects from 2.14.1 to 6.0.1 (#4536) * Update Gradle in generated Java projects from 2.14.1 to 6.0.1 * Upgrade Java 11 native Gradle from 5.5 to 6.0.1 When Java 11 native client library was introduced it was introduced with an overridden version of the Gradle wrapper (5.5 instead of 2.14.1). From looking at that PR, there doesn't appear to be any specific reason for the versions to differ. This removes the only override of the Gradle wrapper so all the Java projects are up to date and shares the same version. --- gradle-wrapper.jar | Bin 55190 -> 58702 bytes gradle-wrapper.properties.mustache | 2 +- gradlew.bat.mustache | 18 +- gradlew.mustache | 51 +++-- libraries/native/gradle-wrapper.jar | Bin 55616 -> 0 bytes .../native/gradle-wrapper.properties.mustache | 5 - libraries/native/gradlew.bat.mustache | 100 ---------- libraries/native/gradlew.mustache | 188 ------------------ 8 files changed, 49 insertions(+), 315 deletions(-) delete mode 100644 libraries/native/gradle-wrapper.jar delete mode 100644 libraries/native/gradle-wrapper.properties.mustache delete mode 100644 libraries/native/gradlew.bat.mustache delete mode 100755 libraries/native/gradlew.mustache diff --git a/gradle-wrapper.jar b/gradle-wrapper.jar index 87b738cbd051603d91cc39de6cb000dd98fe6b02..cc4fdc293d0e50b0ad9b65c16e7ddd1db2f6025b 100644 GIT binary patch delta 19358 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 gi|X0BE&rYTd7Zfqxa|GnRTZ+!>V{XEk%Q#I#Q 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 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/libraries/native/gradlew.mustache b/libraries/native/gradlew.mustache deleted file mode 100755 index 8e25e6c19d5..00000000000 --- a/libraries/native/gradlew.mustache +++ /dev/null @@ -1,188 +0,0 @@ -#!/usr/bin/env sh - -# -# Copyright 2015 the original author or authors. -# -# 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 -# -# https://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. -# - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn () { - echo "$*" -} - -die () { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - -exec "$JAVACMD" "$@" From 831e31889f422f17c90df2a3c529a868ef3ddb51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Thu, 28 Nov 2019 09:54:10 +0100 Subject: [PATCH 175/370] [java][client][restassured] add getAllOperations() (#4631) * [java][client][restassured] add getAllOperations() * Update samples --- libraries/rest-assured/Oper.mustache | 13 +++++++++++++ libraries/rest-assured/api.mustache | 12 +++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 libraries/rest-assured/Oper.mustache diff --git a/libraries/rest-assured/Oper.mustache b/libraries/rest-assured/Oper.mustache new file mode 100644 index 00000000000..b8684665b56 --- /dev/null +++ b/libraries/rest-assured/Oper.mustache @@ -0,0 +1,13 @@ +{{>licenseInfo}} + +package {{apiPackage}}; + +import io.restassured.response.Response; + +import java.util.function.Function; + +public interface Oper { + + T execute(Function handler); + +} diff --git a/libraries/rest-assured/api.mustache b/libraries/rest-assured/api.mustache index db803e8f2e1..2016726a9cb 100644 --- a/libraries/rest-assured/api.mustache +++ b/libraries/rest-assured/api.mustache @@ -56,6 +56,15 @@ public class {{classname}} { return reqSpec; } + public List getAllOperations() { + return Arrays.asList( +{{#operations}} +{{#operation}} + {{operationId}}(){{^-last}},{{/-last}} +{{/operation}} +{{/operations}} + ); + } {{#operations}} {{#operation}} @@ -107,7 +116,7 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public static class {{operationIdCamelCase}}Oper { + public static class {{operationIdCamelCase}}Oper implements Oper { public static final Method REQ_METHOD = {{httpMethod}}; public static final String REQ_URI = "{{path}}"; @@ -134,6 +143,7 @@ public class {{classname}} { * @param type * @return type */ + @Override public T execute(Function handler) { return handler.apply(RestAssured.given().spec(reqSpec.build()).expect().spec(respSpec.build()).when().request(REQ_METHOD, REQ_URI)); } From a05079ad742ec6a437f08391d90dea459c5f1a74 Mon Sep 17 00:00:00 2001 From: Oleh Kurpiak Date: Tue, 3 Dec 2019 15:09:39 +0200 Subject: [PATCH 176/370] [#4025] custom java annotations (#4026) * custom java annotations --- additionalModelTypeAnnotations.mustache | 2 ++ pojo.mustache | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 additionalModelTypeAnnotations.mustache diff --git a/additionalModelTypeAnnotations.mustache b/additionalModelTypeAnnotations.mustache new file mode 100644 index 00000000000..e5dc1ac1295 --- /dev/null +++ b/additionalModelTypeAnnotations.mustache @@ -0,0 +1,2 @@ +{{#additionalModelTypeAnnotations}}{{.}} +{{/additionalModelTypeAnnotations}} \ No newline at end of file diff --git a/pojo.mustache b/pojo.mustache index 9814954cc4b..796f9a7ec14 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -9,7 +9,7 @@ {{/vars}} }) {{/jackson}} -{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcelableModel}}implements Parcelable {{#serializableModel}}, Serializable {{/serializableModel}}{{/parcelableModel}}{{^parcelableModel}}{{#serializableModel}}implements Serializable {{/serializableModel}}{{/parcelableModel}}{ {{#serializableModel}} private static final long serialVersionUID = 1L; From 4b0f3287d31fabb5ea9d7e0e2cbc966610a68ae1 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Date: Wed, 4 Dec 2019 03:06:42 +0100 Subject: [PATCH 177/370] Error in the reactive client when the path variables are a list (#4687) (#4689) * Error in the reactive client when the path variables are a list (#4687) * Update samples (#4687) --- libraries/webclient/ApiClient.mustache | 24 +++++++++++++++++++++++- libraries/webclient/api.mustache | 3 ++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index 013ab6dc0e5..e21f3847641 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -497,7 +497,7 @@ public class ApiClient { formParams .toSingleValueMap() .entrySet() - .forEach(es -> map.add(es.getKey(), (String) es.getValue())); + .forEach(es -> map.add(es.getKey(), String.valueOf(es.getValue()))); return BodyInserters.fromFormData(map); } else if(MediaType.MULTIPART_FORM_DATA.equals(contentType)) { @@ -638,6 +638,28 @@ public class ApiClient { } } + /** + * Formats the specified collection path parameter to a string value. + * + * @param collectionFormat The collection format of the parameter. + * @param values The values of the parameter. + * @return String representation of the parameter + */ + public String collectionPathParameterToString(CollectionFormat collectionFormat, Collection values) { + // create the value based on the collection format + if (CollectionFormat.MULTI.equals(collectionFormat)) { + // not valid for path params + return parameterToString(values); + } + + // collectionFormat is assumed to be "csv" by default + if(collectionFormat == null) { + collectionFormat = CollectionFormat.CSV; + } + + return collectionFormat.collectionToString(values); + } + private class ApiClientHttpRequestInterceptor implements ClientHttpRequestInterceptor { private final Log log = LogFactory.getLog(ApiClientHttpRequestInterceptor.class); diff --git a/libraries/webclient/api.mustache b/libraries/webclient/api.mustache index 96066577b0e..9138d7d2e7a 100644 --- a/libraries/webclient/api.mustache +++ b/libraries/webclient/api.mustache @@ -70,7 +70,8 @@ public class {{classname}} { {{/required}}{{/allParams}} // create path and map variables final Map pathParams = new HashMap();{{#hasPathParams}}{{#pathParams}} - pathParams.put("{{baseName}}", {{{paramName}}});{{/pathParams}}{{/hasPathParams}} + pathParams.put("{{baseName}}", {{#collectionFormat}}apiClient.collectionPathParameterToString(ApiClient.CollectionFormat.valueOf("csv".toUpperCase()), {{/collectionFormat}}{{{paramName}}}{{#collectionFormat}}){{/collectionFormat}});{{/pathParams}}{{/hasPathParams}} + final MultiValueMap queryParams = new LinkedMultiValueMap(); final HttpHeaders headerParams = new HttpHeaders(); From 8d14aaa5641804f9fcd8f84b4ccde6495b567697 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Mon, 9 Dec 2019 22:41:50 -0500 Subject: [PATCH 178/370] [REQ] Java Microprofile REST Client Template (#4713) * Add a Java Library called microprofile. * Fix formatting --- libraries/microprofile/README.mustache | 10 + libraries/microprofile/api.mustache | 61 ++++++ libraries/microprofile/api_exception.mustache | 23 +++ .../api_exception_mapper.mustache | 22 +++ libraries/microprofile/api_test.mustache | 75 ++++++++ .../microprofile/beanValidation.mustache | 4 + .../microprofile/beanValidationCore.mustache | 20 ++ .../beanValidationHeaderParams.mustache | 1 + .../beanValidationPathParams.mustache | 1 + .../beanValidationQueryParams.mustache | 1 + libraries/microprofile/bodyParams.mustache | 1 + .../microprofile/bodyParamsImpl.mustache | 1 + libraries/microprofile/enumClass.mustache | 33 ++++ .../microprofile/enumOuterClass.mustache | 48 +++++ libraries/microprofile/formParams.mustache | 1 + .../microprofile/formParamsImpl.mustache | 1 + .../microprofile/generatedAnnotation.mustache | 1 + libraries/microprofile/headerParams.mustache | 1 + .../microprofile/headerParamsImpl.mustache | 1 + libraries/microprofile/licenseInfo.mustache | 23 +++ libraries/microprofile/model.mustache | 23 +++ libraries/microprofile/pathParams.mustache | 1 + .../microprofile/pathParamsImpl.mustache | 1 + libraries/microprofile/pojo.mustache | 129 +++++++++++++ libraries/microprofile/pom.mustache | 173 ++++++++++++++++++ libraries/microprofile/queryParams.mustache | 1 + .../microprofile/queryParamsImpl.mustache | 1 + libraries/microprofile/returnTypes.mustache | 4 + 28 files changed, 662 insertions(+) create mode 100644 libraries/microprofile/README.mustache create mode 100644 libraries/microprofile/api.mustache create mode 100644 libraries/microprofile/api_exception.mustache create mode 100644 libraries/microprofile/api_exception_mapper.mustache create mode 100644 libraries/microprofile/api_test.mustache create mode 100644 libraries/microprofile/beanValidation.mustache create mode 100644 libraries/microprofile/beanValidationCore.mustache create mode 100644 libraries/microprofile/beanValidationHeaderParams.mustache create mode 100644 libraries/microprofile/beanValidationPathParams.mustache create mode 100644 libraries/microprofile/beanValidationQueryParams.mustache create mode 100644 libraries/microprofile/bodyParams.mustache create mode 100644 libraries/microprofile/bodyParamsImpl.mustache create mode 100644 libraries/microprofile/enumClass.mustache create mode 100644 libraries/microprofile/enumOuterClass.mustache create mode 100644 libraries/microprofile/formParams.mustache create mode 100644 libraries/microprofile/formParamsImpl.mustache create mode 100644 libraries/microprofile/generatedAnnotation.mustache create mode 100644 libraries/microprofile/headerParams.mustache create mode 100644 libraries/microprofile/headerParamsImpl.mustache create mode 100644 libraries/microprofile/licenseInfo.mustache create mode 100644 libraries/microprofile/model.mustache create mode 100644 libraries/microprofile/pathParams.mustache create mode 100644 libraries/microprofile/pathParamsImpl.mustache create mode 100644 libraries/microprofile/pojo.mustache create mode 100644 libraries/microprofile/pom.mustache create mode 100644 libraries/microprofile/queryParams.mustache create mode 100644 libraries/microprofile/queryParamsImpl.mustache create mode 100644 libraries/microprofile/returnTypes.mustache diff --git a/libraries/microprofile/README.mustache b/libraries/microprofile/README.mustache new file mode 100644 index 00000000000..576e70fe8ba --- /dev/null +++ b/libraries/microprofile/README.mustache @@ -0,0 +1,10 @@ +# {{appName}} - MicroProfile Rest Client + +{{#appDescription}} +{{{appDescription}}} + +{{/appDescription}} +## Overview +This API client was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. +[MicroProfile Rest Client](https://github.com/eclipse/microprofile-rest-client) is a type-safe way of calling +REST services. The generated client contains an interface which acts as the client, you can inject it into dependent classes. diff --git a/libraries/microprofile/api.mustache b/libraries/microprofile/api.mustache new file mode 100644 index 00000000000..1830838da8e --- /dev/null +++ b/libraries/microprofile/api.mustache @@ -0,0 +1,61 @@ +{{>licenseInfo}} +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} + +import java.io.InputStream; +import java.io.OutputStream; +import java.util.List; +import java.util.Map; +import javax.ws.rs.*; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.MediaType; +{{^disableMultipart}} +import org.apache.cxf.jaxrs.ext.multipart.*; +{{/disableMultipart}} + +import org.eclipse.microprofile.rest.client.annotation.RegisterProvider; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +{{#appName}} +/** + * {{{appName}}} + * + {{#appDescription}} + *

{{{appDescription}}} + * + {{/appDescription}} + */ +{{/appName}} + +@RegisterRestClient +@RegisterProvider(ApiExceptionMapper.class) +@Path("{{^useAnnotatedBasePath}}/{{/useAnnotatedBasePath}}{{#useAnnotatedBasePath}}{{contextPath}}{{/useAnnotatedBasePath}}") +public interface {{classname}} { +{{#operations}} +{{#operation}} + + {{#summary}} + /** + * {{summary}} + * + {{#notes}} + * {{notes}} + * + {{/notes}} + */ + {{/summary}} + @{{httpMethod}} + {{#subresourceOperation}}@Path("{{{path}}}"){{/subresourceOperation}} +{{#hasConsumes}} + @Consumes({ {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} }) +{{/hasConsumes}} +{{#hasProduces}} + @Produces({ {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }) +{{/hasProduces}} + public {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{nickname}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException, ProcessingException; +{{/operation}} +} +{{/operations}} + diff --git a/libraries/microprofile/api_exception.mustache b/libraries/microprofile/api_exception.mustache new file mode 100644 index 00000000000..fc5c5e5000a --- /dev/null +++ b/libraries/microprofile/api_exception.mustache @@ -0,0 +1,23 @@ +{{>licenseInfo}} +package {{apiPackage}}; + +import javax.ws.rs.core.Response; + +public class ApiException extends Exception { + + private static final long serialVersionUID = 1L; + private Response response; + + public ApiException() { + super(); + } + + public ApiException(Response response) { + super("Api response has status code " + response.getStatus()); + this.response = response; + } + + public Response getResponse() { + return this.response; + } +} diff --git a/libraries/microprofile/api_exception_mapper.mustache b/libraries/microprofile/api_exception_mapper.mustache new file mode 100644 index 00000000000..9c5988414cd --- /dev/null +++ b/libraries/microprofile/api_exception_mapper.mustache @@ -0,0 +1,22 @@ +{{>licenseInfo}} +package {{apiPackage}}; + +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.Provider; +import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper; + +@Provider +public class ApiExceptionMapper + implements ResponseExceptionMapper { + + @Override + public boolean handles(int status, MultivaluedMap headers) { + return status >= 400; + } + + @Override + public ApiException toThrowable(Response response) { + return new ApiException(response); + } +} diff --git a/libraries/microprofile/api_test.mustache b/libraries/microprofile/api_test.mustache new file mode 100644 index 00000000000..8177ac16dad --- /dev/null +++ b/libraries/microprofile/api_test.mustache @@ -0,0 +1,75 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Test; +import org.junit.Before; +import static org.junit.Assert.*; + +import org.eclipse.microprofile.rest.client.RestClientBuilder; + +import java.net.URL; +import java.net.MalformedURLException; +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + + + +/** + {{#appName}} + * {{{appName}}} Test + * + {{/appName}} + * API tests for {{classname}} + */ +{{#generateSpringBootApplication}} +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = SpringBootApplication.class) +@WebAppConfiguration +@IntegrationTest("server.port=0") +{{/generateSpringBootApplication}} +public class {{classname}}Test { + + private {{classname}} client; + private String baseUrl = "http://localhost:9080"; + + @Before + public void setup() throws MalformedURLException { + client = RestClientBuilder.newBuilder() + .baseUrl(new URL(baseUrl)) + .register(ApiException.class) + .build({{classname}}.class); + } + + {{#operations}}{{#operation}} + /** + {{#summary}} + * {{summary}} + * + {{#notes}} + * {{notes}} + * + {{/notes}} + {{/summary}} + * @throws ApiException + * if the Api call fails + */ + @Test + public void {{operationId}}Test() { + // TODO: test validations + {{#allParams}} + {{^isFile}}{{{dataType}}} {{paramName}} = null;{{/isFile}}{{#isFile}}org.apache.cxf.jaxrs.ext.multipart.Attachment {{paramName}} = null;{{/isFile}} + {{/allParams}} + //{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + //{{#returnType}}assertNotNull(response);{{/returnType}} + + + } + {{/operation}}{{/operations}} +} diff --git a/libraries/microprofile/beanValidation.mustache b/libraries/microprofile/beanValidation.mustache new file mode 100644 index 00000000000..c8c6946fef6 --- /dev/null +++ b/libraries/microprofile/beanValidation.mustache @@ -0,0 +1,4 @@ +{{#required}} + @NotNull +{{/required}} +{{>beanValidationCore}} \ No newline at end of file diff --git a/libraries/microprofile/beanValidationCore.mustache b/libraries/microprofile/beanValidationCore.mustache new file mode 100644 index 00000000000..8bcdce3df16 --- /dev/null +++ b/libraries/microprofile/beanValidationCore.mustache @@ -0,0 +1,20 @@ +{{#pattern}} @Pattern(regexp="{{{pattern}}}"){{/pattern}}{{! +minLength && maxLength set +}}{{#minLength}}{{#maxLength}} @Size(min={{minLength}},max={{maxLength}}){{/maxLength}}{{/minLength}}{{! +minLength set, maxLength not +}}{{#minLength}}{{^maxLength}} @Size(min={{minLength}}){{/maxLength}}{{/minLength}}{{! +minLength not set, maxLength set +}}{{^minLength}}{{#maxLength}} @Size(max={{maxLength}}){{/maxLength}}{{/minLength}}{{! +@Size: minItems && maxItems set +}}{{#minItems}}{{#maxItems}} @Size(min={{minItems}},max={{maxItems}}){{/maxItems}}{{/minItems}}{{! +@Size: minItems set, maxItems not +}}{{#minItems}}{{^maxItems}} @Size(min={{minItems}}){{/maxItems}}{{/minItems}}{{! +@Size: minItems not set && maxItems set +}}{{^minItems}}{{#maxItems}} @Size(max={{maxItems}}){{/maxItems}}{{/minItems}}{{! +check for integer or long / all others=decimal type with @Decimal* +isInteger set +}}{{#isInteger}}{{#minimum}} @Min({{minimum}}){{/minimum}}{{#maximum}} @Max({{maximum}}){{/maximum}}{{/isInteger}}{{! +isLong set +}}{{#isLong}}{{#minimum}} @Min({{minimum}}L){{/minimum}}{{#maximum}} @Max({{maximum}}L){{/maximum}}{{/isLong}}{{! +Not Integer, not Long => we have a decimal value! +}}{{^isInteger}}{{^isLong}}{{#minimum}} @DecimalMin("{{minimum}}"){{/minimum}}{{#maximum}} @DecimalMax("{{maximum}}"){{/maximum}}{{/isLong}}{{/isInteger}} \ No newline at end of file diff --git a/libraries/microprofile/beanValidationHeaderParams.mustache b/libraries/microprofile/beanValidationHeaderParams.mustache new file mode 100644 index 00000000000..f8eef8f94c7 --- /dev/null +++ b/libraries/microprofile/beanValidationHeaderParams.mustache @@ -0,0 +1 @@ +{{#required}} @NotNull{{/required}}{{>beanValidationCore}} \ No newline at end of file diff --git a/libraries/microprofile/beanValidationPathParams.mustache b/libraries/microprofile/beanValidationPathParams.mustache new file mode 100644 index 00000000000..051bd53c0a5 --- /dev/null +++ b/libraries/microprofile/beanValidationPathParams.mustache @@ -0,0 +1 @@ +{{! PathParam is always required, no @NotNull necessary }}{{>beanValidationCore}} \ No newline at end of file diff --git a/libraries/microprofile/beanValidationQueryParams.mustache b/libraries/microprofile/beanValidationQueryParams.mustache new file mode 100644 index 00000000000..f8eef8f94c7 --- /dev/null +++ b/libraries/microprofile/beanValidationQueryParams.mustache @@ -0,0 +1 @@ +{{#required}} @NotNull{{/required}}{{>beanValidationCore}} \ No newline at end of file diff --git a/libraries/microprofile/bodyParams.mustache b/libraries/microprofile/bodyParams.mustache new file mode 100644 index 00000000000..be56da7535b --- /dev/null +++ b/libraries/microprofile/bodyParams.mustache @@ -0,0 +1 @@ +{{#isBodyParam}}{{#useBeanValidation}}@Valid {{/useBeanValidation}}{{{dataType}}} {{paramName}}{{/isBodyParam}} \ No newline at end of file diff --git a/libraries/microprofile/bodyParamsImpl.mustache b/libraries/microprofile/bodyParamsImpl.mustache new file mode 100644 index 00000000000..c7d1abfe527 --- /dev/null +++ b/libraries/microprofile/bodyParamsImpl.mustache @@ -0,0 +1 @@ +{{#isBodyParam}}{{{dataType}}} {{paramName}}{{/isBodyParam}} \ No newline at end of file diff --git a/libraries/microprofile/enumClass.mustache b/libraries/microprofile/enumClass.mustache new file mode 100644 index 00000000000..5bdcf238a2c --- /dev/null +++ b/libraries/microprofile/enumClass.mustache @@ -0,0 +1,33 @@ +@XmlType(name="{{datatypeWithEnum}}") +@XmlEnum({{dataType}}.class) +public enum {{datatypeWithEnum}} { + + {{#allowableValues}} +{{#enumVars}}@XmlEnumValue({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) {{name}}({{dataType}}.valueOf({{{value}}})){{^-last}}, {{/-last}}{{#-last}};{{/-last}}{{/enumVars}} + {{/allowableValues}} + + + private {{dataType}} value; + + {{datatypeWithEnum}} ({{dataType}} v) { + value = v; + } + + public {{dataType}} value() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + + public static {{datatypeWithEnum}} fromValue(String v) { + for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + if (String.valueOf(b.value).equals(v)) { + return b; + } + } + {{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + v + "'");{{/useNullForUnknownEnumValue}} + } +} diff --git a/libraries/microprofile/enumOuterClass.mustache b/libraries/microprofile/enumOuterClass.mustache new file mode 100644 index 00000000000..df2c7287396 --- /dev/null +++ b/libraries/microprofile/enumOuterClass.mustache @@ -0,0 +1,48 @@ +{{#jackson}} +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +{{/jackson}} + +/** + * {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}} + */ +public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} { + {{#gson}} + {{#allowableValues}}{{#enumVars}} + @SerializedName({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) + {{{name}}}({{{value}}}){{^-last}}, + {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}} + {{/gson}} + {{^gson}} + {{#allowableValues}}{{#enumVars}} + {{{name}}}({{{value}}}){{^-last}}, + {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}} + {{/gson}} + + private {{{dataType}}} value; + + {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}({{{dataType}}} value) { + this.value = value; + } + + @Override +{{#jackson}} + @JsonValue +{{/jackson}} + public String toString() { + return String.valueOf(value); + } + +{{#jackson}} + @JsonCreator +{{/jackson}} + public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue(String text) { + for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + if (String.valueOf(b.value).equals(text)) { + return b; + } + } + {{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + text + "'");{{/useNullForUnknownEnumValue}} + } + +} diff --git a/libraries/microprofile/formParams.mustache b/libraries/microprofile/formParams.mustache new file mode 100644 index 00000000000..97216dc1806 --- /dev/null +++ b/libraries/microprofile/formParams.mustache @@ -0,0 +1 @@ +{{#isFormParam}}{{^isFile}}@Multipart(value = "{{baseName}}"{{^required}}, required = false{{/required}}) {{{dataType}}} {{paramName}}{{/isFile}}{{#isFile}} @Multipart(value = "{{baseName}}" {{^required}}, required = false{{/required}}) Attachment {{paramName}}Detail{{/isFile}}{{/isFormParam}} \ No newline at end of file diff --git a/libraries/microprofile/formParamsImpl.mustache b/libraries/microprofile/formParamsImpl.mustache new file mode 100644 index 00000000000..2be40e1ddd3 --- /dev/null +++ b/libraries/microprofile/formParamsImpl.mustache @@ -0,0 +1 @@ +{{#isFormParam}}{{^isFile}}{{{dataType}}} {{paramName}}{{/isFile}}{{#isFile}} Attachment {{paramName}}Detail{{/isFile}}{{/isFormParam}} \ No newline at end of file diff --git a/libraries/microprofile/generatedAnnotation.mustache b/libraries/microprofile/generatedAnnotation.mustache new file mode 100644 index 00000000000..49110fc1ad9 --- /dev/null +++ b/libraries/microprofile/generatedAnnotation.mustache @@ -0,0 +1 @@ +@javax.annotation.Generated(value = "{{generatorClass}}", date = "{{generatedDate}}") \ No newline at end of file diff --git a/libraries/microprofile/headerParams.mustache b/libraries/microprofile/headerParams.mustache new file mode 100644 index 00000000000..4a9009e76a2 --- /dev/null +++ b/libraries/microprofile/headerParams.mustache @@ -0,0 +1 @@ +{{#isHeaderParam}}@HeaderParam("{{baseName}}") {{#useBeanValidation}}{{>beanValidationHeaderParams}}{{/useBeanValidation}} {{{dataType}}} {{paramName}}{{/isHeaderParam}} \ No newline at end of file diff --git a/libraries/microprofile/headerParamsImpl.mustache b/libraries/microprofile/headerParamsImpl.mustache new file mode 100644 index 00000000000..bd03573d196 --- /dev/null +++ b/libraries/microprofile/headerParamsImpl.mustache @@ -0,0 +1 @@ +{{#isHeaderParam}}{{{dataType}}} {{paramName}}{{/isHeaderParam}} \ No newline at end of file diff --git a/libraries/microprofile/licenseInfo.mustache b/libraries/microprofile/licenseInfo.mustache new file mode 100644 index 00000000000..02acad802ec --- /dev/null +++ b/libraries/microprofile/licenseInfo.mustache @@ -0,0 +1,23 @@ +/** + * {{{appName}}} + * {{{appDescription}}} + * + * {{#version}}The version of the OpenAPI document: {{{version}}}{{/version}} + * {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}} + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + * + * 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. + */ diff --git a/libraries/microprofile/model.mustache b/libraries/microprofile/model.mustache new file mode 100644 index 00000000000..5272ff09487 --- /dev/null +++ b/libraries/microprofile/model.mustache @@ -0,0 +1,23 @@ +{{>licenseInfo}} +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} +{{#serializableModel}} +import java.io.Serializable; +{{/serializableModel}} +{{#useBeanValidation}} +import javax.validation.constraints.*; +import javax.validation.Valid; +{{/useBeanValidation}} + +{{#models}} +{{#model}} +{{#isEnum}} +{{>enumOuterClass}} +{{/isEnum}} +{{^isEnum}} +{{>pojo}} +{{/isEnum}} +{{/model}} +{{/models}} diff --git a/libraries/microprofile/pathParams.mustache b/libraries/microprofile/pathParams.mustache new file mode 100644 index 00000000000..9e8455d5ac7 --- /dev/null +++ b/libraries/microprofile/pathParams.mustache @@ -0,0 +1 @@ +{{#isPathParam}}@PathParam("{{baseName}}"){{#useBeanValidation}}{{>beanValidationPathParams}}{{/useBeanValidation}} {{{dataType}}} {{paramName}}{{/isPathParam}} \ No newline at end of file diff --git a/libraries/microprofile/pathParamsImpl.mustache b/libraries/microprofile/pathParamsImpl.mustache new file mode 100644 index 00000000000..6829cf8c7a6 --- /dev/null +++ b/libraries/microprofile/pathParamsImpl.mustache @@ -0,0 +1 @@ +{{#isPathParam}}{{{dataType}}} {{paramName}}{{/isPathParam}} \ No newline at end of file diff --git a/libraries/microprofile/pojo.mustache b/libraries/microprofile/pojo.mustache new file mode 100644 index 00000000000..a7d3ddb77c1 --- /dev/null +++ b/libraries/microprofile/pojo.mustache @@ -0,0 +1,129 @@ +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlEnumValue; +import javax.json.bind.annotation.JsonbProperty; + +{{#withXml}} +@XmlAccessorType(XmlAccessType.FIELD) +{{#hasVars}} @XmlType(name = "{{classname}}", propOrder = + { {{#vars}}"{{name}}"{{^-last}}, {{/-last}}{{/vars}} +}){{/hasVars}} +{{^hasVars}}@XmlType(name = "{{classname}}"){{/hasVars}} +{{^parent}}@XmlRootElement(name="{{classname}}"){{/parent}} +{{/withXml}} +{{#description}} +/** + * {{{description}}} + **/ +{{/description}} +public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}}{{#serializableModel}} implements Serializable{{/serializableModel}} { + {{#vars}}{{#isEnum}}{{^isContainer}} +{{>enumClass}}{{/isContainer}}{{#isContainer}}{{#mostInnerItems}} +{{>enumClass}}{{/mostInnerItems}}{{/isContainer}}{{/isEnum}} +{{#withXml}} + @XmlElement(name="{{baseName}}"{{#required}}, required = {{required}}{{/required}}) +{{/withXml}} +{{#description}} + /** + * {{{description}}} + **/ +{{/description}} +{{#isContainer}} + private {{{datatypeWithEnum}}} {{name}}{{#required}} = {{{defaultValue}}}{{/required}}{{^required}} = null{{/required}}; +{{/isContainer}} +{{^isContainer}} + private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; +{{/isContainer}} + {{/vars}} + + {{#vars}} + /** + {{#description}} + * {{description}} + {{/description}} + {{^description}} + * Get {{name}} + {{/description}} + {{#minimum}} + * minimum: {{minimum}} + {{/minimum}} + {{#maximum}} + * maximum: {{maximum}} + {{/maximum}} + * @return {{name}} + **/ + @JsonbProperty("{{baseName}}") +{{#vendorExtensions.extraAnnotation}} + {{{vendorExtensions.extraAnnotation}}} +{{/vendorExtensions.extraAnnotation}} +{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} {{#isEnum}}{{^isListContainer}}{{^isMapContainer}}public {{dataType}} {{getter}}() { + if ({{name}} == null) { + return null; + } + return {{name}}.value(); + }{{/isMapContainer}}{{/isListContainer}}{{/isEnum}}{{#isEnum}}{{#isListContainer}}public {{{datatypeWithEnum}}} {{getter}}() { + return {{name}}; + }{{/isListContainer}}{{/isEnum}}{{#isEnum}}{{#isMapContainer}}public {{{datatypeWithEnum}}} {{getter}}() { + return {{name}}; + }{{/isMapContainer}}{{/isEnum}}{{^isEnum}}public {{{datatypeWithEnum}}} {{getter}}() { + return {{name}}; + }{{/isEnum}} + + {{^isReadOnly}} + /** + * Set {{name}} + **/ + public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { + this.{{name}} = {{name}}; + } + + public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { + this.{{name}} = {{name}}; + return this; + } + {{#isListContainer}} + + public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { + this.{{name}}.add({{name}}Item); + return this; + } + {{/isListContainer}} + {{#isMapContainer}} + + public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { + this.{{name}}.put(key, {{name}}Item); + return this; + } + {{/isMapContainer}} + {{/isReadOnly}} + + {{/vars}} + + /** + * Create a string representation of this pojo. + **/ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class {{classname}} {\n"); + {{#parent}}sb.append(" ").append(toIndentedString(super.toString())).append("\n");{{/parent}} + {{#vars}}sb.append(" {{name}}: ").append(toIndentedString({{name}})).append("\n"); + {{/vars}}sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private static String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/libraries/microprofile/pom.mustache b/libraries/microprofile/pom.mustache new file mode 100644 index 00000000000..95ffef03353 --- /dev/null +++ b/libraries/microprofile/pom.mustache @@ -0,0 +1,173 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{#appDescription}} + {{appDescription}} + {{/appDescription}} + {{artifactVersion}} + + src/main/java + + + maven-failsafe-plugin + 2.6 + + + + integration-test + verify + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.9.1 + + + add-source + generate-sources + + add-source + + + + src/gen/java + + + + + + + + + + junit + junit + ${junit-version} + test + +{{#useBeanValidation}} + + + javax.validation + validation-api + ${beanvalidation-version} + provided + +{{/useBeanValidation}} + + + org.eclipse.microprofile.rest.client + microprofile-rest-client-api + 1.2.1 + + + + + javax.ws.rs + javax.ws.rs-api + 2.1.1 + provided + + + + io.smallrye + smallrye-rest-client + 1.2.1 + test + + + + io.smallrye + smallrye-config + 1.3.5 + test + + + {{^disableMultipart}} + + org.apache.cxf + cxf-rt-rs-extension-providers + 3.2.6 + + {{/disableMultipart}} + + + javax.json.bind + javax.json.bind-api + 1.0 + + + javax.xml.bind + jaxb-api + 2.2.11 + + + com.sun.xml.bind + jaxb-core + 2.2.11 + + + com.sun.xml.bind + jaxb-impl + 2.2.11 + + + javax.activation + activation + 1.1.1 + + +{{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-jaxrs-version} + +{{/java8}} +{{^java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-jaxrs-version} + +{{/java8}} +{{#useBeanValidationFeature}} + + org.hibernate + hibernate-validator + 5.2.2.Final + +{{/useBeanValidationFeature}} + + + + sonatype-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + true + + + + + 1.8 + ${java.version} + ${java.version} + 1.5.18 + 9.2.9.v20150224 + 4.12 + 1.1.7 + 2.5 +{{#useBeanValidation}} + 1.1.0.Final +{{/useBeanValidation}} + 3.2.7 + 2.9.7 + UTF-8 + + diff --git a/libraries/microprofile/queryParams.mustache b/libraries/microprofile/queryParams.mustache new file mode 100644 index 00000000000..ca2c6e106f7 --- /dev/null +++ b/libraries/microprofile/queryParams.mustache @@ -0,0 +1 @@ +{{#isQueryParam}}@QueryParam("{{baseName}}"){{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}} {{^isContainer}}{{#defaultValue}}@DefaultValue({{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{{defaultValue}}}{{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}) {{/defaultValue}}{{/isContainer}}{{{dataType}}} {{paramName}}{{/isQueryParam}} \ No newline at end of file diff --git a/libraries/microprofile/queryParamsImpl.mustache b/libraries/microprofile/queryParamsImpl.mustache new file mode 100644 index 00000000000..ff79730471d --- /dev/null +++ b/libraries/microprofile/queryParamsImpl.mustache @@ -0,0 +1 @@ +{{#isQueryParam}}{{{dataType}}} {{paramName}}{{/isQueryParam}} \ No newline at end of file diff --git a/libraries/microprofile/returnTypes.mustache b/libraries/microprofile/returnTypes.mustache new file mode 100644 index 00000000000..6af86ffe4e4 --- /dev/null +++ b/libraries/microprofile/returnTypes.mustache @@ -0,0 +1,4 @@ +{{#useGenericResponse}}Response{{/useGenericResponse}}{{! non-generic response: +}}{{^useGenericResponse}}{{! +}}{{{returnType}}}{{! +}}{{/useGenericResponse}} \ No newline at end of file From 7e019d6a2670742f284ff5577c54787984dd2ef1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Fri, 20 Dec 2019 16:18:47 +0100 Subject: [PATCH 179/370] [java] Update jackson_databind_nullable_version to 0.2.1 (#4839) * [java] Update jackson_databind_nullable_version to 0.2.1 * Update samples * FIx typo --- build.gradle.mustache | 2 +- libraries/feign/build.gradle.mustache | 2 +- libraries/feign/pom.mustache | 2 +- libraries/google-api-client/build.gradle.mustache | 2 +- libraries/google-api-client/pom.mustache | 2 +- libraries/jersey2/build.gradle.mustache | 2 +- libraries/jersey2/pom.mustache | 2 +- libraries/native/pom.mustache | 2 +- libraries/rest-assured/build.gradle.mustache | 2 +- libraries/rest-assured/pom.mustache | 2 +- libraries/resteasy/build.gradle.mustache | 2 +- libraries/resteasy/pom.mustache | 2 +- libraries/resttemplate/build.gradle.mustache | 2 +- libraries/resttemplate/pom.mustache | 2 +- libraries/retrofit2/build.gradle.mustache | 2 +- libraries/retrofit2/pom.mustache | 2 +- libraries/vertx/pom.mustache | 2 +- libraries/webclient/pom.mustache | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/build.gradle.mustache b/build.gradle.mustache index 47059d550b1..1aa650293b1 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -138,7 +138,7 @@ ext { swagger_annotations_version = "1.5.22" jackson_version = "2.9.10" jackson_databind_version = "2.9.10.1" - jackson_databind_nullable_version = "0.2.0" + jackson_databind_nullable_version = "0.2.1" jersey_version = "1.19.4" jodatime_version = "2.9.9" junit_version = "4.12" diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index e70e3e2945f..fcdbf1c4f2b 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -122,7 +122,7 @@ ext { swagger_annotations_version = "1.5.22" jackson_version = "2.9.10" jackson_databind_version = "2.9.10.1" - jackson_databind_nullable_version = "0.2.0" + jackson_databind_nullable_version = "0.2.1" {{#threetenbp}} jackson_threetenbp_version = "2.9.10" {{/threetenbp}} diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index 7910027eb91..fd0315830ed 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -315,7 +315,7 @@ {{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}} 2.1.0 2.9.10 - 0.2.0 + 0.2.1 2.9.10.1 {{#threetenbp}} 2.9.10 diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache index 57deb75c560..aa26930fd96 100644 --- a/libraries/google-api-client/build.gradle.mustache +++ b/libraries/google-api-client/build.gradle.mustache @@ -122,7 +122,7 @@ ext { swagger_annotations_version = "1.5.22" jackson_version = "2.9.10" jackson_databind_version = "2.9.10.1" - jackson_databind_nullable_version = "0.2.0" + jackson_databind_nullable_version = "0.2.1" google_api_client_version = "1.23.0" jersey_common_version = "2.25.1" jodatime_version = "2.9.9" diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index 89f8be6132c..4e17016acb6 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -308,7 +308,7 @@ 2.25.1 2.9.10 2.9.10.1 - 0.2.0 + 0.2.1 {{#joda}} 2.9.9 {{/joda}} diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index 998d6ebc8b4..56d0e55fcb5 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -121,7 +121,7 @@ ext { swagger_annotations_version = "1.5.22" jackson_version = "2.9.10" jackson_databind_version = "2.9.10.1" - jackson_databind_nullable_version = "0.2.0" + jackson_databind_nullable_version = "0.2.1" {{#supportJava6}} jersey_version = "2.6" commons_io_version=2.5 diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 5a108ed6ee4..21f566f2c43 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -362,7 +362,7 @@ {{/supportJava6}} 2.9.10 2.9.10.1 - 0.2.0 + 0.2.1 {{#threetenbp}} 2.9.10 {{/threetenbp}} diff --git a/libraries/native/pom.mustache b/libraries/native/pom.mustache index e3fe7f74118..75f54dab22f 100644 --- a/libraries/native/pom.mustache +++ b/libraries/native/pom.mustache @@ -215,7 +215,7 @@ 11 11 2.9.9 - 0.2.0 + 0.2.1 4.12 diff --git a/libraries/rest-assured/build.gradle.mustache b/libraries/rest-assured/build.gradle.mustache index c40c9c3eb92..dd848e0f5ec 100644 --- a/libraries/rest-assured/build.gradle.mustache +++ b/libraries/rest-assured/build.gradle.mustache @@ -101,7 +101,7 @@ ext { {{#jackson}} jackson_version = "2.9.10" jackson_databind_version = "2.9.10" - jackson_databind_nullable_version = 0.2.0 + jackson_databind_nullable_version = 0.2.1 {{/jackson}} {{#gson}} gson_version = "2.8.5" diff --git a/libraries/rest-assured/pom.mustache b/libraries/rest-assured/pom.mustache index 330fd660725..f4eb427c766 100644 --- a/libraries/rest-assured/pom.mustache +++ b/libraries/rest-assured/pom.mustache @@ -325,7 +325,7 @@ {{#jackson}} 2.9.10 2.9.10 - 0.2.0 + 0.2.1 {{#threetenbp}} 2.9.10 {{/threetenbp}} diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index bf9f5408c2a..6579b7c46c9 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -121,7 +121,7 @@ ext { swagger_annotations_version = "1.5.22" jackson_version = "2.9.10" jackson_databind_version = "2.9.10.1" - jackson_databind_nullable_version = "0.2.0" + jackson_databind_nullable_version = "0.2.1" threetenbp_version = "2.9.10" resteasy_version = "3.1.3.Final" {{^java8}} diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index 16a1a3fe1fa..30a4ba06e6f 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -296,7 +296,7 @@ 3.1.3.Final 2.9.10 2.9.10.1 - 0.2.0 + 0.2.1 2.9.10 {{^java8}} 2.9.9 diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index 1c631f1a557..2e2485139fa 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -122,7 +122,7 @@ ext { swagger_annotations_version = "1.5.22" jackson_version = "2.9.10" jackson_databind_version = "2.9.10.1" - jackson_databind_nullable_version = "0.2.0" + jackson_databind_nullable_version = "0.2.1" spring_web_version = "4.3.9.RELEASE" jodatime_version = "2.9.9" junit_version = "4.12" diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache index eb3ddfb12f9..e55bc8e7fe5 100644 --- a/libraries/resttemplate/pom.mustache +++ b/libraries/resttemplate/pom.mustache @@ -311,7 +311,7 @@ 4.3.9.RELEASE 2.9.10 2.9.10.1 - 0.2.0 + 0.2.1 {{#joda}} 2.9.9 {{/joda}} diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index ddeb061cd02..362c8a504a6 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -133,7 +133,7 @@ ext { {{#play26}} jackson_version = "2.9.10" jackson_databind_version = "2.9.10.1" - jackson_databind_nullable_version = "0.2.0" + jackson_databind_nullable_version = "0.2.1" play_version = "2.6.7" {{/play26}} {{/usePlayWS}} diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index 428e4203763..f0415112104 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -388,7 +388,7 @@ 2.9.10 2.6.7 {{/play26}} - 0.2.0 + 0.2.1 {{/usePlayWS}} 2.5.0 {{#useRxJava}} diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache index cdbb87d1800..51125fa48e0 100644 --- a/libraries/vertx/pom.mustache +++ b/libraries/vertx/pom.mustache @@ -291,7 +291,7 @@ 1.5.22 2.9.10 2.9.10.1 - 0.2.0 + 0.2.1 4.12 diff --git a/libraries/webclient/pom.mustache b/libraries/webclient/pom.mustache index f32f6ee5f45..f07bbf5e942 100644 --- a/libraries/webclient/pom.mustache +++ b/libraries/webclient/pom.mustache @@ -145,7 +145,7 @@ 5.0.8.RELEASE 2.9.10 2.9.10.1 - 0.2.0 + 0.2.1 4.12 3.1.8.RELEASE 0.7.8.RELEASE From 4c8fcf58ae1ee073b1a4fad44bded2768e0b421c Mon Sep 17 00:00:00 2001 From: Ties de Kock Date: Sat, 21 Dec 2019 03:15:29 +0100 Subject: [PATCH 180/370] [java] Jersey2 and resttemplate do not correctly send defaultCookies (#4821) * Java/Jersey2 sends defaultCookies * Send cookie value instead of [value] (resttemplate) * Improve the javadoc string --- libraries/jersey2/ApiClient.mustache | 7 +++++++ libraries/resttemplate/ApiClient.mustache | 14 ++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 0aa3683cf35..b12740b0f64 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -715,6 +715,13 @@ public class ApiClient { } } + for (Entry entry : defaultCookieMap.entrySet()) { + String value = entry.getValue(); + if (value != null) { + invocationBuilder = invocationBuilder.cookie(entry.getKey(), value); + } + } + for (Entry entry : defaultHeaderMap.entrySet()) { String key = entry.getKey(); if (!headerParams.containsKey(key)) { diff --git a/libraries/resttemplate/ApiClient.mustache b/libraries/resttemplate/ApiClient.mustache index 2a327daca24..b160b7cca23 100644 --- a/libraries/resttemplate/ApiClient.mustache +++ b/libraries/resttemplate/ApiClient.mustache @@ -659,14 +659,20 @@ public class ApiClient { } } + /** + * Build cookie header. Keeps a single value per cookie (as per + * RFC6265 section 5.3). + * + * @param cookies map all cookies + * @return header string for cookies. + */ private String buildCookieHeader(MultiValueMap cookies) { final StringBuilder cookieValue = new StringBuilder(); String delimiter = ""; for (final Map.Entry> entry : cookies.entrySet()) { - for (String value : entry.getValue()) { - cookieValue.append(String.format("%s%s=%s", delimiter, entry.getKey(), entry.getValue())); - delimiter = "; "; - } + final String value = entry.getValue().get(entry.getValue().size() - 1); + cookieValue.append(String.format("%s%s=%s", delimiter, entry.getKey(), value)); + delimiter = "; "; } return cookieValue.toString(); } From 980f9f674c2e6ce29e018c84d9a65428e635c08e Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Thu, 26 Dec 2019 00:12:58 -0800 Subject: [PATCH 181/370] [Java] Fix serialized name of discriminator in JSON.mustache (#4672) * Use propertyBaseName instead of propertyName for discriminator * Revert "Use propertyBaseName instead of propertyName for discriminator" This reverts commit 389c5471ba0a71a8ba558c2859e64f08a5186f00. * Use propertyBaseName instead of propertyName for discriminator --- JSON.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JSON.mustache b/JSON.mustache index b7f458c9d12..b951c3c555d 100644 --- a/JSON.mustache +++ b/JSON.mustache @@ -75,7 +75,7 @@ public class JSON { {{/mappedModels}} classByDiscriminatorValue.put("{{classname}}".toUpperCase(Locale.ROOT), {{classname}}.class); return getClassByDiscriminator(classByDiscriminatorValue, - getDiscriminatorValue(readElement, "{{{propertyName}}}")); + getDiscriminatorValue(readElement, "{{{propertyBaseName}}}")); } }) {{/discriminator}} From ec8894564c9fb12c48665fb55419e830588d67ae Mon Sep 17 00:00:00 2001 From: William Cheng Date: Sun, 29 Dec 2019 14:55:08 +0800 Subject: [PATCH 182/370] fix java feign parameter request name (#4883) --- libraries/feign/api.mustache | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/feign/api.mustache b/libraries/feign/api.mustache index b446223ba53..238079ca27c 100644 --- a/libraries/feign/api.mustache +++ b/libraries/feign/api.mustache @@ -42,7 +42,7 @@ public interface {{classname}} extends ApiClient.Api { "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{#hasMore}}, {{/hasMore}}{{/headerParams}} }) - {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{paramName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isBodyParam}}{{^legacyDates}}@Param("{{baseName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{baseName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); {{#hasQueryParams}} /** @@ -80,7 +80,7 @@ public interface {{classname}} extends ApiClient.Api { "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{#hasMore}}, {{/hasMore}}{{/headerParams}} }) - {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isQueryParam}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{paramName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}, {{/isQueryParam}}{{/allParams}}@QueryMap(encoded=true) Map queryParams); + {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isQueryParam}}{{^isBodyParam}}{{^legacyDates}}@Param("{{baseName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{baseName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}, {{/isQueryParam}}{{/allParams}}@QueryMap(encoded=true) Map queryParams); /** * A convenience class for generating query parameters for the From 2785038df22d78e6f655d28957cddc77b2fd53be Mon Sep 17 00:00:00 2001 From: sullis Date: Wed, 1 Jan 2020 21:20:29 -0800 Subject: [PATCH 183/370] upgrade to JUnit 4.13 (#4899) --- build.gradle.mustache | 2 +- libraries/feign/build.gradle.mustache | 2 +- libraries/feign/build.sbt.mustache | 2 +- libraries/feign/pom.mustache | 2 +- libraries/google-api-client/build.gradle.mustache | 2 +- libraries/google-api-client/build.sbt.mustache | 2 +- libraries/google-api-client/pom.mustache | 2 +- libraries/jersey2/build.gradle.mustache | 2 +- libraries/jersey2/build.sbt.mustache | 2 +- libraries/jersey2/pom.mustache | 2 +- libraries/microprofile/pom.mustache | 2 +- libraries/native/build.gradle.mustache | 2 +- libraries/native/pom.mustache | 2 +- libraries/okhttp-gson/build.gradle.mustache | 2 +- libraries/okhttp-gson/build.sbt.mustache | 2 +- libraries/okhttp-gson/pom.mustache | 2 +- libraries/rest-assured/build.gradle.mustache | 2 +- libraries/rest-assured/build.sbt.mustache | 2 +- libraries/rest-assured/pom.mustache | 2 +- libraries/resteasy/build.gradle.mustache | 2 +- libraries/resteasy/build.sbt.mustache | 2 +- libraries/resteasy/pom.mustache | 2 +- libraries/resttemplate/build.gradle.mustache | 2 +- libraries/resttemplate/pom.mustache | 2 +- libraries/retrofit/build.gradle.mustache | 2 +- libraries/retrofit/build.sbt.mustache | 2 +- libraries/retrofit/pom.mustache | 2 +- libraries/retrofit2/build.gradle.mustache | 2 +- libraries/retrofit2/build.sbt.mustache | 2 +- libraries/retrofit2/pom.mustache | 2 +- libraries/vertx/build.gradle.mustache | 2 +- libraries/vertx/pom.mustache | 2 +- libraries/webclient/pom.mustache | 2 +- pom.mustache | 2 +- 34 files changed, 34 insertions(+), 34 deletions(-) diff --git a/build.gradle.mustache b/build.gradle.mustache index 1aa650293b1..0d370b8c3fb 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -141,7 +141,7 @@ ext { jackson_databind_nullable_version = "0.2.1" jersey_version = "1.19.4" jodatime_version = "2.9.9" - junit_version = "4.12" + junit_version = "4.13" } dependencies { diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index fcdbf1c4f2b..caa0ca58998 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -128,7 +128,7 @@ ext { {{/threetenbp}} feign_version = "{{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" feign_form_version = "2.1.0" - junit_version = "4.12" + junit_version = "4.13" oltu_version = "1.0.1" } diff --git a/libraries/feign/build.sbt.mustache b/libraries/feign/build.sbt.mustache index 61273efb773..4194803a089 100644 --- a/libraries/feign/build.sbt.mustache +++ b/libraries/feign/build.sbt.mustache @@ -21,7 +21,7 @@ lazy val root = (project in file(".")). "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", "com.brsanthu" % "migbase64" % "2.2" % "compile", - "junit" % "junit" % "4.12" % "test", + "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) ) diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index fd0315830ed..a13a4a263ee 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -320,7 +320,7 @@ {{#threetenbp}} 2.9.10 {{/threetenbp}} - 4.12 + 4.13 1.0.0 1.0.1 diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache index aa26930fd96..9808528459c 100644 --- a/libraries/google-api-client/build.gradle.mustache +++ b/libraries/google-api-client/build.gradle.mustache @@ -126,7 +126,7 @@ ext { google_api_client_version = "1.23.0" jersey_common_version = "2.25.1" jodatime_version = "2.9.9" - junit_version = "4.12" + junit_version = "4.13" {{#threetenbp}} jackson_threeten_version = "2.9.10" {{/threetenbp}} diff --git a/libraries/google-api-client/build.sbt.mustache b/libraries/google-api-client/build.sbt.mustache index 2af4dd8dfdb..87b444d9387 100644 --- a/libraries/google-api-client/build.sbt.mustache +++ b/libraries/google-api-client/build.sbt.mustache @@ -27,7 +27,7 @@ lazy val root = (project in file(".")). {{#threetenbp}} "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", {{/threetenbp}} - "junit" % "junit" % "4.12" % "test", + "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) ) diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index 4e17016acb6..259f9806af4 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -316,6 +316,6 @@ 2.9.10 {{/threetenbp}} 1.0.0 - 4.12 + 4.13 diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index 56d0e55fcb5..fdd258f1d25 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -130,7 +130,7 @@ ext { {{^supportJava6}} jersey_version = "2.27" {{/supportJava6}} - junit_version = "4.12" + junit_version = "4.13" {{#threetenbp}} threetenbp_version = "2.9.10" {{/threetenbp}} diff --git a/libraries/jersey2/build.sbt.mustache b/libraries/jersey2/build.sbt.mustache index 61f8e283787..84fc8b722b8 100644 --- a/libraries/jersey2/build.sbt.mustache +++ b/libraries/jersey2/build.sbt.mustache @@ -32,7 +32,7 @@ lazy val root = (project in file(".")). "org.apache.commons" % "commons-lang3" % "3.6", "commons-io" % "commons-io" % "2.5", {{/supportJava6}} - "junit" % "junit" % "4.12" % "test", + "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) ) diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 21f566f2c43..e2eb2bdbd04 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -367,6 +367,6 @@ 2.9.10 {{/threetenbp}} 1.0.0 - 4.12 + 4.13 diff --git a/libraries/microprofile/pom.mustache b/libraries/microprofile/pom.mustache index 95ffef03353..ca7d6b7a830 100644 --- a/libraries/microprofile/pom.mustache +++ b/libraries/microprofile/pom.mustache @@ -160,7 +160,7 @@ ${java.version} 1.5.18 9.2.9.v20150224 - 4.12 + 4.13 1.1.7 2.5 {{#useBeanValidation}} diff --git a/libraries/native/build.gradle.mustache b/libraries/native/build.gradle.mustache index f81df201eb2..c797b1ba9b7 100644 --- a/libraries/native/build.gradle.mustache +++ b/libraries/native/build.gradle.mustache @@ -52,7 +52,7 @@ artifacts { ext { swagger_annotations_version = "1.5.22" jackson_version = "2.9.9" - junit_version = "4.12" + junit_version = "4.13" } dependencies { diff --git a/libraries/native/pom.mustache b/libraries/native/pom.mustache index 75f54dab22f..7e6ebb2f950 100644 --- a/libraries/native/pom.mustache +++ b/libraries/native/pom.mustache @@ -216,6 +216,6 @@ 11 2.9.9 0.2.1 - 4.12 + 4.13 diff --git a/libraries/okhttp-gson/build.gradle.mustache b/libraries/okhttp-gson/build.gradle.mustache index fbf57ba7796..a149c682201 100644 --- a/libraries/okhttp-gson/build.gradle.mustache +++ b/libraries/okhttp-gson/build.gradle.mustache @@ -142,7 +142,7 @@ dependencies { {{#threetenbp}} compile 'org.threeten:threetenbp:1.4.0' {{/threetenbp}} - testCompile 'junit:junit:4.12' + testCompile 'junit:junit:4.13' } javadoc { diff --git a/libraries/okhttp-gson/build.sbt.mustache b/libraries/okhttp-gson/build.sbt.mustache index 4d768393264..43907462202 100644 --- a/libraries/okhttp-gson/build.sbt.mustache +++ b/libraries/okhttp-gson/build.sbt.mustache @@ -25,7 +25,7 @@ lazy val root = (project in file(".")). {{/threetenbp}} "io.gsonfire" % "gson-fire" % "1.8.3" % "compile", "javax.annotation" % "jsr250-api" % "1.0" % "compile", - "junit" % "junit" % "4.12" % "test", + "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) ) diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index cbcdd78f974..e4c05f4151d 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -320,7 +320,7 @@ {{/threetenbp}} 1.0.0 1.0 - 4.12 + 4.13 UTF-8 diff --git a/libraries/rest-assured/build.gradle.mustache b/libraries/rest-assured/build.gradle.mustache index dd848e0f5ec..bd241986225 100644 --- a/libraries/rest-assured/build.gradle.mustache +++ b/libraries/rest-assured/build.gradle.mustache @@ -97,7 +97,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.21" rest_assured_version = "4.0.0" - junit_version = "4.12" + junit_version = "4.13" {{#jackson}} jackson_version = "2.9.10" jackson_databind_version = "2.9.10" diff --git a/libraries/rest-assured/build.sbt.mustache b/libraries/rest-assured/build.sbt.mustache index d8214467ae2..71f2eaeeba2 100644 --- a/libraries/rest-assured/build.sbt.mustache +++ b/libraries/rest-assured/build.sbt.mustache @@ -27,7 +27,7 @@ lazy val root = (project in file(".")). "org.threeten" % "threetenbp" % "1.4.0" % "compile", {{/threetenbp}} "com.squareup.okio" % "okio" % "1.13.0" % "compile", - "junit" % "junit" % "4.12" % "test", + "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) ) diff --git a/libraries/rest-assured/pom.mustache b/libraries/rest-assured/pom.mustache index f4eb427c766..bec9af57bb7 100644 --- a/libraries/rest-assured/pom.mustache +++ b/libraries/rest-assured/pom.mustache @@ -331,6 +331,6 @@ {{/threetenbp}} {{/jackson}} 1.13.0 - 4.12 + 4.13 diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index 6579b7c46c9..86fb51119fc 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -131,7 +131,7 @@ ext { commons_io_version=2.5 commons_lang3_version=3.5 {{/supportJava6}} - junit_version = "4.12" + junit_version = "4.13" } dependencies { diff --git a/libraries/resteasy/build.sbt.mustache b/libraries/resteasy/build.sbt.mustache index 95ab58d1f9d..2554ec2f10e 100644 --- a/libraries/resteasy/build.sbt.mustache +++ b/libraries/resteasy/build.sbt.mustache @@ -29,7 +29,7 @@ lazy val root = (project in file(".")). "org.apache.commons" % "commons-lang3" % "3.5" % "compile", "commons-io" % "commons-io" % "2.5" % "compile", {{/supportJava6}} - "junit" % "junit" % "4.12" % "test", + "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) ) diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index 30a4ba06e6f..48d1fa3a286 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -306,6 +306,6 @@ 3.6 {{/supportJava6}} 1.0.0 - 4.12 + 4.13 diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index 2e2485139fa..74c7fdea5fa 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -125,7 +125,7 @@ ext { jackson_databind_nullable_version = "0.2.1" spring_web_version = "4.3.9.RELEASE" jodatime_version = "2.9.9" - junit_version = "4.12" + junit_version = "4.13" {{#threetenbp}} jackson_threeten_version = "2.9.10" {{/threetenbp}} diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache index e55bc8e7fe5..04920dd554b 100644 --- a/libraries/resttemplate/pom.mustache +++ b/libraries/resttemplate/pom.mustache @@ -319,6 +319,6 @@ 2.9.10 {{/threetenbp}} 1.0.0 - 4.12 + 4.13 diff --git a/libraries/retrofit/build.gradle.mustache b/libraries/retrofit/build.gradle.mustache index a3c7c226f06..af83cc1ef05 100644 --- a/libraries/retrofit/build.gradle.mustache +++ b/libraries/retrofit/build.gradle.mustache @@ -111,7 +111,7 @@ ext { oltu_version = "1.0.1" retrofit_version = "1.9.0" swagger_annotations_version = "1.5.21" - junit_version = "4.12" + junit_version = "4.13" jodatime_version = "2.9.3" {{#threetenbp}} threetenbp_version = "1.4.0" diff --git a/libraries/retrofit/build.sbt.mustache b/libraries/retrofit/build.sbt.mustache index 6afa18db865..360f53d1ae8 100644 --- a/libraries/retrofit/build.sbt.mustache +++ b/libraries/retrofit/build.sbt.mustache @@ -17,7 +17,7 @@ lazy val root = (project in file(".")). {{#threetenbp}} "org.threeten" % "threetenbp" % "1.4.0" % "compile", {{/threetenbp}} - "junit" % "junit" % "4.12" % "test", + "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) ) diff --git a/libraries/retrofit/pom.mustache b/libraries/retrofit/pom.mustache index 73d9b4d565a..5a40a07979c 100644 --- a/libraries/retrofit/pom.mustache +++ b/libraries/retrofit/pom.mustache @@ -280,6 +280,6 @@ {{/threetenbp}} 1.0.1 1.0.0 - 4.12 + 4.13 diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index 362c8a504a6..55025dd0e04 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -138,7 +138,7 @@ ext { {{/play26}} {{/usePlayWS}} swagger_annotations_version = "1.5.22" - junit_version = "4.12" + junit_version = "4.13" {{#useRxJava}} rx_java_version = "1.3.0" {{/useRxJava}} diff --git a/libraries/retrofit2/build.sbt.mustache b/libraries/retrofit2/build.sbt.mustache index ecae66c6a85..0d7954c4e04 100644 --- a/libraries/retrofit2/build.sbt.mustache +++ b/libraries/retrofit2/build.sbt.mustache @@ -53,7 +53,7 @@ lazy val root = (project in file(".")). "org.threeten" % "threetenbp" % "1.4.0" % "compile", {{/threetenbp}} "io.gsonfire" % "gson-fire" % "1.8.0" % "compile", - "junit" % "junit" % "4.12" % "test", + "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.11" % "test" ) ) diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index f0415112104..78046cbf1c6 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -404,6 +404,6 @@ 1.4.0 {{/threetenbp}} 1.0.1 - 4.12 + 4.13 diff --git a/libraries/vertx/build.gradle.mustache b/libraries/vertx/build.gradle.mustache index 862aee9f785..3ac8134e0fa 100644 --- a/libraries/vertx/build.gradle.mustache +++ b/libraries/vertx/build.gradle.mustache @@ -31,7 +31,7 @@ ext { jackson_version = "2.9.10" jackson_databind_version = "2.9.10.1" vertx_version = "3.4.2" - junit_version = "4.12" + junit_version = "4.13" } dependencies { diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache index 51125fa48e0..21b5fdbc6fc 100644 --- a/libraries/vertx/pom.mustache +++ b/libraries/vertx/pom.mustache @@ -292,6 +292,6 @@ 2.9.10 2.9.10.1 0.2.1 - 4.12 + 4.13 diff --git a/libraries/webclient/pom.mustache b/libraries/webclient/pom.mustache index f07bbf5e942..be8e0560029 100644 --- a/libraries/webclient/pom.mustache +++ b/libraries/webclient/pom.mustache @@ -146,7 +146,7 @@ 2.9.10 2.9.10.1 0.2.1 - 4.12 + 4.13 3.1.8.RELEASE 0.7.8.RELEASE {{#joda}} diff --git a/pom.mustache b/pom.mustache index 7dde4b12d9e..b17b2357bad 100644 --- a/pom.mustache +++ b/pom.mustache @@ -356,6 +356,6 @@ {{/supportJava6}} {{^threetenbp}}2.7.5{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} 1.0.0 - 4.12 + 4.13 From c4ad58ca7db165002caba8a6985370717f106713 Mon Sep 17 00:00:00 2001 From: Bruno Coelho <4brunu@users.noreply.github.com> Date: Thu, 2 Jan 2020 05:46:49 +0000 Subject: [PATCH 184/370] [kotlin][client] make Request date converter toJson as default (#4884) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix for Issue #2205 Because when we have tags on OpenAPI Specification, there can be more than 1 Feign Beans being generated and the title field is share by all the clients. This makes the code to stop working in runtime. Here is a PR which uses the classVarName instead, which follows the standards and should be enough to solve this issue. For more info please refer to: https://github.com/OpenAPITools/openapi-generator/issues/2205 * fix java feign parameter request name (#4883) * update sprign cloud feign sample * [JAVA][SPRING][2195] added missing getter for enum value (#2346) * [2195] added missing getter for enum value * updated samples * re-generate spring samples * Removed @JsonValue from toString and regenerated samples * re-generate spring samples Co-authored-by: Esteban Gehring * update samples * [kotlin][client] make Request date converter toJson as default * [kotlin][client] update windows scripts * [kotlin][client] update docs * [kotlin][client] update scripts * [kotlin][client] update scripts Co-authored-by: Filipe Manuel Couto Pinheiro Co-authored-by: William Cheng Co-authored-by: Lukáš Vasek Co-authored-by: Esteban Gehring --- libraries/feign/api.mustache | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/feign/api.mustache b/libraries/feign/api.mustache index b446223ba53..238079ca27c 100644 --- a/libraries/feign/api.mustache +++ b/libraries/feign/api.mustache @@ -42,7 +42,7 @@ public interface {{classname}} extends ApiClient.Api { "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{#hasMore}}, {{/hasMore}}{{/headerParams}} }) - {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{paramName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isBodyParam}}{{^legacyDates}}@Param("{{baseName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{baseName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); {{#hasQueryParams}} /** @@ -80,7 +80,7 @@ public interface {{classname}} extends ApiClient.Api { "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{#hasMore}}, {{/hasMore}}{{/headerParams}} }) - {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isQueryParam}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{paramName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}, {{/isQueryParam}}{{/allParams}}@QueryMap(encoded=true) Map queryParams); + {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isQueryParam}}{{^isBodyParam}}{{^legacyDates}}@Param("{{baseName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{baseName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}, {{/isQueryParam}}{{/allParams}}@QueryMap(encoded=true) Map queryParams); /** * A convenience class for generating query parameters for the From 39133938891d4f0cfabd5cb8966fbf4f0ac2e703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Fri, 3 Jan 2020 04:03:12 +0100 Subject: [PATCH 185/370] [java][client] jackson update (#4907) * [java][client] update jackson-databind-version to 2.10.1 * [java][client] update jackson-version to 2.10.1 * Update samples * [google-api-client] add missing generic parameter to fix compile error * Update samples --- build.gradle.mustache | 4 ++-- libraries/feign/build.gradle.mustache | 4 ++-- libraries/feign/build.sbt.mustache | 6 +++--- libraries/feign/pom.mustache | 4 ++-- libraries/google-api-client/api.mustache | 4 ++-- libraries/google-api-client/build.gradle.mustache | 4 ++-- libraries/google-api-client/build.sbt.mustache | 6 +++--- libraries/google-api-client/pom.mustache | 4 ++-- libraries/jersey2/build.gradle.mustache | 4 ++-- libraries/jersey2/build.sbt.mustache | 6 +++--- libraries/jersey2/pom.mustache | 4 ++-- libraries/rest-assured/build.gradle.mustache | 2 +- libraries/rest-assured/pom.mustache | 2 +- libraries/resteasy/build.gradle.mustache | 4 ++-- libraries/resteasy/build.sbt.mustache | 6 +++--- libraries/resteasy/pom.mustache | 4 ++-- libraries/resttemplate/build.gradle.mustache | 4 ++-- libraries/resttemplate/pom.mustache | 4 ++-- libraries/retrofit2/build.gradle.mustache | 6 +++--- libraries/retrofit2/build.sbt.mustache | 10 +++++----- libraries/retrofit2/pom.mustache | 6 +++--- libraries/vertx/build.gradle.mustache | 4 ++-- libraries/vertx/pom.mustache | 4 ++-- libraries/webclient/pom.mustache | 4 ++-- 24 files changed, 55 insertions(+), 55 deletions(-) diff --git a/build.gradle.mustache b/build.gradle.mustache index 0d370b8c3fb..b761d147c5d 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -136,8 +136,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.9.10" - jackson_databind_version = "2.9.10.1" + jackson_version = "2.10.1" + jackson_databind_version = "2.10.1" jackson_databind_nullable_version = "0.2.1" jersey_version = "1.19.4" jodatime_version = "2.9.9" diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index caa0ca58998..24e668fdf32 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -120,8 +120,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.9.10" - jackson_databind_version = "2.9.10.1" + jackson_version = "2.10.1" + jackson_databind_version = "2.10.1" jackson_databind_nullable_version = "0.2.1" {{#threetenbp}} jackson_threetenbp_version = "2.9.10" diff --git a/libraries/feign/build.sbt.mustache b/libraries/feign/build.sbt.mustache index 4194803a089..907b7bd4d27 100644 --- a/libraries/feign/build.sbt.mustache +++ b/libraries/feign/build.sbt.mustache @@ -14,9 +14,9 @@ lazy val root = (project in file(".")). "io.github.openfeign" % "feign-jackson" % "{{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", "io.github.openfeign" % "feign-slf4j" % "{{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", "io.github.openfeign.form" % "feign-form" % "2.1.0" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.9.10" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.10" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.1" % "compile", "com.fasterxml.jackson.datatype" % "jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}" % "2.9.10" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index a13a4a263ee..e73e45de1b3 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -314,9 +314,9 @@ 1.5.21 {{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}} 2.1.0 - 2.9.10 + 2.10.1 0.2.1 - 2.9.10.1 + 2.10.1 {{#threetenbp}} 2.9.10 {{/threetenbp}} diff --git a/libraries/google-api-client/api.mustache b/libraries/google-api-client/api.mustache index 7c5669aa2a2..2c13f4eb011 100644 --- a/libraries/google-api-client/api.mustache +++ b/libraries/google-api-client/api.mustache @@ -58,7 +58,7 @@ public class {{classname}} { **/ public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws IOException { {{#returnType}}HttpResponse response = {{/returnType}}{{operationId}}ForHttpResponse({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} - TypeReference typeRef = new TypeReference<{{{returnType}}}>() {}; + TypeReference<{{{returnType}}}> typeRef = new TypeReference<{{{returnType}}}>() {}; return apiClient.getObjectMapper().readValue(response.getContent(), typeRef);{{/returnType}} } @@ -77,7 +77,7 @@ public class {{classname}} { **/ public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#bodyParam}}{{^required}}{{{dataType}}} {{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}Map params) throws IOException { {{#returnType}}HttpResponse response = {{/returnType}}{{operationId}}ForHttpResponse({{#bodyParam}}{{^required}}{{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}params);{{#returnType}} - TypeReference typeRef = new TypeReference<{{{returnType}}}>() {}; + TypeReference<{{{returnType}}}> typeRef = new TypeReference<{{{returnType}}}>() {}; return apiClient.getObjectMapper().readValue(response.getContent(), typeRef);{{/returnType}} } diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache index 9808528459c..346ed6625b9 100644 --- a/libraries/google-api-client/build.gradle.mustache +++ b/libraries/google-api-client/build.gradle.mustache @@ -120,8 +120,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.9.10" - jackson_databind_version = "2.9.10.1" + jackson_version = "2.10.1" + jackson_databind_version = "2.10.1" jackson_databind_nullable_version = "0.2.1" google_api_client_version = "1.23.0" jersey_common_version = "2.25.1" diff --git a/libraries/google-api-client/build.sbt.mustache b/libraries/google-api-client/build.sbt.mustache index 87b444d9387..7d958dfadfb 100644 --- a/libraries/google-api-client/build.sbt.mustache +++ b/libraries/google-api-client/build.sbt.mustache @@ -12,9 +12,9 @@ lazy val root = (project in file(".")). "io.swagger" % "swagger-annotations" % "1.5.22", "com.google.api-client" % "google-api-client" % "1.23.0", "org.glassfish.jersey.core" % "jersey-common" % "2.25.1", - "com.fasterxml.jackson.core" % "jackson-core" % "2.9.10" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.10" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.1" % "compile", {{#withXml}} "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.9.10" % "compile", {{/withXml}} diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index 259f9806af4..5e3c04fe93b 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -306,8 +306,8 @@ 1.5.22 1.30.2 2.25.1 - 2.9.10 - 2.9.10.1 + 2.10.1 + 2.10.1 0.2.1 {{#joda}} 2.9.9 diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index fdd258f1d25..16cc03eeeba 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -119,8 +119,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.9.10" - jackson_databind_version = "2.9.10.1" + jackson_version = "2.10.1" + jackson_databind_version = "2.10.1" jackson_databind_nullable_version = "0.2.1" {{#supportJava6}} jersey_version = "2.6" diff --git a/libraries/jersey2/build.sbt.mustache b/libraries/jersey2/build.sbt.mustache index 84fc8b722b8..7e2dc832a2c 100644 --- a/libraries/jersey2/build.sbt.mustache +++ b/libraries/jersey2/build.sbt.mustache @@ -13,9 +13,9 @@ lazy val root = (project in file(".")). "org.glassfish.jersey.core" % "jersey-client" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, "org.glassfish.jersey.media" % "jersey-media-multipart" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, "org.glassfish.jersey.media" % "jersey-media-json-jackson" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, - "com.fasterxml.jackson.core" % "jackson-core" % "2.9.10" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.10" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.1" % "compile", {{#joda}} "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.10" % "compile", {{/joda}} diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index e2eb2bdbd04..e9fc8ba3942 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -360,8 +360,8 @@ 2.5 3.6 {{/supportJava6}} - 2.9.10 - 2.9.10.1 + 2.10.1 + 2.10.1 0.2.1 {{#threetenbp}} 2.9.10 diff --git a/libraries/rest-assured/build.gradle.mustache b/libraries/rest-assured/build.gradle.mustache index bd241986225..f6487eefc58 100644 --- a/libraries/rest-assured/build.gradle.mustache +++ b/libraries/rest-assured/build.gradle.mustache @@ -99,7 +99,7 @@ ext { rest_assured_version = "4.0.0" junit_version = "4.13" {{#jackson}} - jackson_version = "2.9.10" + jackson_version = "2.10.1" jackson_databind_version = "2.9.10" jackson_databind_nullable_version = 0.2.1 {{/jackson}} diff --git a/libraries/rest-assured/pom.mustache b/libraries/rest-assured/pom.mustache index bec9af57bb7..9c49fb07774 100644 --- a/libraries/rest-assured/pom.mustache +++ b/libraries/rest-assured/pom.mustache @@ -323,7 +323,7 @@ 1.4.0 {{/threetenbp}} {{#jackson}} - 2.9.10 + 2.10.1 2.9.10 0.2.1 {{#threetenbp}} diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index 86fb51119fc..08ab4a3cce9 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -119,8 +119,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.9.10" - jackson_databind_version = "2.9.10.1" + jackson_version = "2.10.1" + jackson_databind_version = "2.10.1" jackson_databind_nullable_version = "0.2.1" threetenbp_version = "2.9.10" resteasy_version = "3.1.3.Final" diff --git a/libraries/resteasy/build.sbt.mustache b/libraries/resteasy/build.sbt.mustache index 2554ec2f10e..936c4141f8f 100644 --- a/libraries/resteasy/build.sbt.mustache +++ b/libraries/resteasy/build.sbt.mustache @@ -13,9 +13,9 @@ lazy val root = (project in file(".")). "org.jboss.resteasy" % "resteasy-client" % "3.1.3.Final" % "compile", "org.jboss.resteasy" % "resteasy-multipart-provider" % "3.1.3.Final" % "compile", "org.jboss.resteasy" % "resteasy-jackson2-provider" % "3.1.3.Final" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.9.10" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.10" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.1" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", {{#java8}} "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.10" % "compile", diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index 48d1fa3a286..e3e127020e4 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -294,8 +294,8 @@ UTF-8 1.5.22 3.1.3.Final - 2.9.10 - 2.9.10.1 + 2.10.1 + 2.10.1 0.2.1 2.9.10 {{^java8}} diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index 74c7fdea5fa..a957f76822e 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -120,8 +120,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.9.10" - jackson_databind_version = "2.9.10.1" + jackson_version = "2.10.1" + jackson_databind_version = "2.10.1" jackson_databind_nullable_version = "0.2.1" spring_web_version = "4.3.9.RELEASE" jodatime_version = "2.9.9" diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache index 04920dd554b..1f5e82d501f 100644 --- a/libraries/resttemplate/pom.mustache +++ b/libraries/resttemplate/pom.mustache @@ -309,8 +309,8 @@ UTF-8 1.5.22 4.3.9.RELEASE - 2.9.10 - 2.9.10.1 + 2.10.1 + 2.10.1 0.2.1 {{#joda}} 2.9.9 diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index 55025dd0e04..7d8a096e83c 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -127,12 +127,12 @@ ext { play_version = "2.4.11" {{/play24}} {{#play25}} - jackson_version = "2.9.10" + jackson_version = "2.10.1" play_version = "2.5.14" {{/play25}} {{#play26}} - jackson_version = "2.9.10" - jackson_databind_version = "2.9.10.1" + jackson_version = "2.10.1" + jackson_databind_version = "2.10.1" jackson_databind_nullable_version = "0.2.1" play_version = "2.6.7" {{/play26}} diff --git a/libraries/retrofit2/build.sbt.mustache b/libraries/retrofit2/build.sbt.mustache index 0d7954c4e04..be45635e47f 100644 --- a/libraries/retrofit2/build.sbt.mustache +++ b/libraries/retrofit2/build.sbt.mustache @@ -23,15 +23,15 @@ lazy val root = (project in file(".")). {{/play24}} {{#play25}} "com.typesafe.play" % "play-java-ws_2.11" % "2.5.15" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.9.10" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.10" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.1" % "compile", {{/play25}} {{#play26}} "com.typesafe.play" % "play-ahc-ws_2.12" % "2.6.7" % "compile", "javax.validation" % "validation-api" % "1.1.0.Final" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.9.10" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.10" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10" % "compile", {{/play26}} "com.squareup.retrofit2" % "converter-jackson" % "2.3.0" % "compile", diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index 78046cbf1c6..9613f948416 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -375,17 +375,17 @@ 1.8.3 1.5.22 {{#usePlayWS}} - 2.9.10.1 + 2.10.1 {{#play24}} 2.6.6 2.4.11 {{/play24}} {{#play25}} - 2.9.10 + 2.10.1 2.5.15 {{/play25}} {{#play26}} - 2.9.10 + 2.10.1 2.6.7 {{/play26}} 0.2.1 diff --git a/libraries/vertx/build.gradle.mustache b/libraries/vertx/build.gradle.mustache index 3ac8134e0fa..456356c925f 100644 --- a/libraries/vertx/build.gradle.mustache +++ b/libraries/vertx/build.gradle.mustache @@ -28,8 +28,8 @@ task execute(type:JavaExec) { ext { swagger_annotations_version = "1.5.21" - jackson_version = "2.9.10" - jackson_databind_version = "2.9.10.1" + jackson_version = "2.10.1" + jackson_databind_version = "2.10.1" vertx_version = "3.4.2" junit_version = "4.13" } diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache index 21b5fdbc6fc..3ed8b93b490 100644 --- a/libraries/vertx/pom.mustache +++ b/libraries/vertx/pom.mustache @@ -289,8 +289,8 @@ UTF-8 3.4.2 1.5.22 - 2.9.10 - 2.9.10.1 + 2.10.1 + 2.10.1 0.2.1 4.13 diff --git a/libraries/webclient/pom.mustache b/libraries/webclient/pom.mustache index be8e0560029..7b57232bc5a 100644 --- a/libraries/webclient/pom.mustache +++ b/libraries/webclient/pom.mustache @@ -143,8 +143,8 @@ UTF-8 1.5.22 5.0.8.RELEASE - 2.9.10 - 2.9.10.1 + 2.10.1 + 2.10.1 0.2.1 4.13 3.1.8.RELEASE From 01ea1edbc1410a2dd0f7a5a43d7005de424bbe4c Mon Sep 17 00:00:00 2001 From: Hippolyte HENRY Date: Sat, 18 Jan 2020 09:12:20 +0100 Subject: [PATCH 186/370] [Java][jersey2] Use builder pattern for requests (#4666) * Use builder pattern for requests * petstore * Add @throws annotation * regenerate jersey2 test files * Also group bodyParam in builder class * petstore java6 * regenerate java8 * ensure up to date --- libraries/jersey2/api.mustache | 117 +++++++++++++++++++++++----- libraries/jersey2/api_doc.mustache | 111 ++++++++++++++++++++++++++ libraries/jersey2/api_test.mustache | 51 ++++++++++++ 3 files changed, 258 insertions(+), 21 deletions(-) create mode 100644 libraries/jersey2/api_doc.mustache create mode 100644 libraries/jersey2/api_test.mustache diff --git a/libraries/jersey2/api.mustache b/libraries/jersey2/api.mustache index f3e27a079c2..3950d7a2af3 100644 --- a/libraries/jersey2/api.mustache +++ b/libraries/jersey2/api.mustache @@ -38,8 +38,8 @@ public class {{classname}} { public void setApiClient(ApiClient apiClient) { this.apiClient = apiClient; } - {{#operation}} + {{^vendorExtensions.x-group-parameters}} /** * {{summary}} * {{notes}} @@ -53,10 +53,10 @@ public class {{classname}} { {{#responses.0}} * @http.response.details - - {{#responses}} - - {{/responses}} + + {{#responses}} + + {{/responses}}
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
{{/responses.0}} {{#isDeprecated}} @@ -71,13 +71,11 @@ public class {{classname}} { @Deprecated {{/isDeprecated}} public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { - {{#returnType}} - return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}).getData(); - {{/returnType}}{{^returnType}} - {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); - {{/returnType}} + {{#returnType}}return {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#returnType}}.getData(){{/returnType}}; } + {{/vendorExtensions.x-group-parameters}} + {{^vendorExtensions.x-group-parameters}} /** * {{summary}} * {{notes}} @@ -89,10 +87,10 @@ public class {{classname}} { {{#responses.0}} * @http.response.details - - {{#responses}} - - {{/responses}} + + {{#responses}} + + {{/responses}}
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
{{/responses.0}} {{#isDeprecated}} @@ -106,7 +104,7 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set @@ -152,13 +150,90 @@ public class {{classname}} { String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; - {{#returnType}} - GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {}; - return apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType); - {{/returnType}}{{^returnType}} - return apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, null); - {{/returnType}} + {{#returnType}}GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {};{{/returnType}} + return apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, {{#returnType}}localVarReturnType{{/returnType}}{{^returnType}}null{{/returnType}}); + } + {{#vendorExtensions.x-group-parameters}} + + public class API{{operationId}}Request { + {{#allParams}} + private {{#isRequired}}final {{/isRequired}}{{{dataType}}} {{localVariablePrefix}}{{paramName}}; + {{/allParams}} + + private API{{operationId}}Request({{#pathParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}) { + {{#pathParams}} + this.{{localVariablePrefix}}{{paramName}} = {{paramName}}; + {{/pathParams}} + } + {{#allParams}}{{^isPathParam}} + + /** + * Set {{paramName}} + * @param {{paramName}} {{description}} ({{^required}}optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}{{/required}}{{#required}}required{{/required}}) + * @return API{{operationId}}Request + */ + public API{{operationId}}Request {{paramName}}({{{dataType}}} {{paramName}}) { + this.{{localVariablePrefix}}{{paramName}} = {{paramName}}; + return this; + } + {{/isPathParam}}{{/allParams}} + + /** + * Execute {{operationId}} request + {{#returnType}}* @return {{.}}{{/returnType}} + * @throws ApiException if fails to make API call + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} + {{#isDeprecated}}* @deprecated{{/isDeprecated}} + */ + {{#isDeprecated}}@Deprecated{{/isDeprecated}} + public {{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}void{{/returnType}} execute() throws ApiException { + {{#returnType}}return {{/returnType}}this.executeWithHttpInfo().getData(); + } + + /** + * Execute {{operationId}} request with HTTP info returned + * @return ApiResponse<{{#returnType}}{{.}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + * @throws ApiException if fails to make API call + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} + {{#isDeprecated}}* @deprecated{{/isDeprecated}} + */ + {{#isDeprecated}}@Deprecated{{/isDeprecated}} + public ApiResponse<{{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> executeWithHttpInfo() throws ApiException { + return {{operationId}}WithHttpInfo({{#allParams}}{{localVariablePrefix}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + } + } + + /** + * {{summary}} + * {{notes}}{{#pathParams}} + * @param {{paramName}} {{description}} (required){{/pathParams}} + * @return {{operationId}}Request + * @throws ApiException if fails to make API call + {{#isDeprecated}}* @deprecated{{/isDeprecated}} + {{#externalDocs}}* {{description}} + * @see {{summary}} Documentation{{/externalDocs}} + */ + {{#isDeprecated}}@Deprecated{{/isDeprecated}} + public API{{operationId}}Request {{operationId}}({{#pathParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}) throws ApiException { + return new API{{operationId}}Request({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}); } + {{/vendorExtensions.x-group-parameters}} {{/operation}} } {{/operations}} diff --git a/libraries/jersey2/api_doc.mustache b/libraries/jersey2/api_doc.mustache new file mode 100644 index 00000000000..7e62976258b --- /dev/null +++ b/libraries/jersey2/api_doc.mustache @@ -0,0 +1,111 @@ +# {{classname}}{{#description}} + +{{description}}{{/description}} + +All URIs are relative to *{{basePath}}* + +Method | HTTP request | Description +------------- | ------------- | ------------- +{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}} + +{{#operations}} +{{#operation}} + +## {{operationId}} + +{{^vendorExtensions.x-group-parameters}}> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{/vendorExtensions.x-group-parameters}} +{{#vendorExtensions.x-group-parameters}}> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}){{#allParams}}{{^isPathParam}}.{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}}.execute();{{/vendorExtensions.x-group-parameters}} + +{{summary}}{{#notes}} + +{{{unescapedNotes}}}{{/notes}} + +### Example + +```java +// Import classes: +import {{{invokerPackage}}}.ApiClient; +import {{{invokerPackage}}}.ApiException; +import {{{invokerPackage}}}.Configuration;{{#hasAuthMethods}} +import {{{invokerPackage}}}.auth.*;{{/hasAuthMethods}} +import {{{invokerPackage}}}.models.*; +import {{{package}}}.{{{classname}}}; + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("{{{basePath}}}"); + {{#hasAuthMethods}} + {{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + // Configure HTTP basic authorization: {{{name}}} + HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setUsername("YOUR USERNAME"); + {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasicBasic}}{{#isBasicBearer}} + // Configure HTTP bearer authorization: {{{name}}} + HttpBearerAuth {{{name}}} = (HttpBearerAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setBearerToken("BEARER TOKEN");{{/isBasicBearer}}{{/isBasic}}{{#isApiKey}} + // Configure API key authorization: {{{name}}} + ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setApiKey("YOUR API KEY"); + // Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null) + //{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} + // Configure OAuth2 access token for authorization: {{{name}}} + OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}} + {{/authMethods}} + {{/hasAuthMethods}} + + {{{classname}}} apiInstance = new {{{classname}}}(defaultClient); + {{#allParams}} + {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} + {{/allParams}} + try { {{^vendorExtensions.x-group-parameters}} + {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{/vendorExtensions.x-group-parameters}} + {{#vendorExtensions.x-group-parameters}}{{#returnType}}{{{returnType}}} result = {{/returnType}}api.{{operationId}}({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}){{#allParams}}{{^isPathParam}} + .{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}} + .execute();{{/vendorExtensions.x-group-parameters}} + {{#returnType}}System.out.println(result);{{/returnType}} + } catch (ApiException e) { + System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } +} +``` + +### Parameters + +{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} +Name | Type | Description | Notes +------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} +{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{^isContainer}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} +{{/allParams}} + +### Return type + +{{#returnType}}{{#returnTypeIsPrimitive}}**{{returnType}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{returnType}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}null (empty response body){{/returnType}} + +### Authorization + +{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{name}}](../README.md#{{name}}){{^-last}}, {{/-last}}{{/authMethods}} + +### HTTP request headers + +- **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} +- **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} + +{{#responses.0}} +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +{{#responses}} +| **{{code}}** | {{message}} | {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}} | +{{/responses}} +{{/responses.0}} + +{{/operation}} +{{/operations}} diff --git a/libraries/jersey2/api_test.mustache b/libraries/jersey2/api_test.mustache new file mode 100644 index 00000000000..21e0f97d639 --- /dev/null +++ b/libraries/jersey2/api_test.mustache @@ -0,0 +1,51 @@ +{{>licenseInfo}} + +package {{package}}; + +import {{invokerPackage}}.ApiException; +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Test; +import org.junit.Ignore; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +@Ignore +public class {{classname}}Test { + + private final {{classname}} api = new {{classname}}(); + + {{#operations}}{{#operation}} + /** + * {{summary}} + * + * {{notes}} + * + * @throws ApiException + * if the Api call fails + */ + @Test + public void {{operationId}}Test() throws ApiException { + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + {{^vendorExtensions.x-group-parameters}} + {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{/vendorExtensions.x-group-parameters}} + {{#vendorExtensions.x-group-parameters}} + {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}){{#allParams}}{{^isPathParam}} + .{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}} + .execute(); + {{/vendorExtensions.x-group-parameters}} + // TODO: test validations + } + {{/operation}}{{/operations}} +} From 5036a5d34c51b16ca81372784ff2a2a916f136a9 Mon Sep 17 00:00:00 2001 From: Nicholas Muesch Date: Sat, 18 Jan 2020 04:25:18 -0500 Subject: [PATCH 187/370] Escape query params before invoking api (#5023) * Escape query params before invoking api * Update petstore file * Update remaining petstore examples --- libraries/jersey2/ApiClient.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index b12740b0f64..0f83a20450f 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -694,7 +694,7 @@ public class ApiClient { if (queryParams != null) { for (Pair queryParam : queryParams) { if (queryParam.getValue() != null) { - target = target.queryParam(queryParam.getName(), queryParam.getValue()); + target = target.queryParam(queryParam.getName(), escapeString(queryParam.getValue())); } } } From 3b74bfa4bbcccacaf7092f5ef9066ea3206646d5 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Sat, 18 Jan 2020 19:11:51 +0800 Subject: [PATCH 188/370] better code format in java jersey doc (#5031) --- libraries/jersey2/api_doc.mustache | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/libraries/jersey2/api_doc.mustache b/libraries/jersey2/api_doc.mustache index 7e62976258b..f162d1cc974 100644 --- a/libraries/jersey2/api_doc.mustache +++ b/libraries/jersey2/api_doc.mustache @@ -14,8 +14,12 @@ Method | HTTP request | Description ## {{operationId}} -{{^vendorExtensions.x-group-parameters}}> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{/vendorExtensions.x-group-parameters}} -{{#vendorExtensions.x-group-parameters}}> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}){{#allParams}}{{^isPathParam}}.{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}}.execute();{{/vendorExtensions.x-group-parameters}} +{{^vendorExtensions.x-group-parameters}} +> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) +{{/vendorExtensions.x-group-parameters}} +{{#vendorExtensions.x-group-parameters}} +> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}){{#allParams}}{{^isPathParam}}.{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}}.execute(); +{{/vendorExtensions.x-group-parameters}} {{summary}}{{#notes}} @@ -60,12 +64,18 @@ public class Example { {{#allParams}} {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} {{/allParams}} - try { {{^vendorExtensions.x-group-parameters}} - {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{/vendorExtensions.x-group-parameters}} - {{#vendorExtensions.x-group-parameters}}{{#returnType}}{{{returnType}}} result = {{/returnType}}api.{{operationId}}({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}){{#allParams}}{{^isPathParam}} + try { + {{^vendorExtensions.x-group-parameters}} + {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{/vendorExtensions.x-group-parameters}} + {{#vendorExtensions.x-group-parameters}} + {{#returnType}}{{{returnType}}} result = {{/returnType}}api.{{operationId}}({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}){{#allParams}}{{^isPathParam}} .{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}} - .execute();{{/vendorExtensions.x-group-parameters}} - {{#returnType}}System.out.println(result);{{/returnType}} + .execute(); + {{/vendorExtensions.x-group-parameters}} + {{#returnType}} + System.out.println(result); + {{/returnType}} } catch (ApiException e) { System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); System.err.println("Status code: " + e.getCode()); From 17a6df53d04f698a558650dcc19f753656d77d03 Mon Sep 17 00:00:00 2001 From: Jim Schubert Date: Sat, 18 Jan 2020 18:53:05 -0500 Subject: [PATCH 189/370] =?UTF-8?q?Evaluating=20https=20issues=20in=20Circ?= =?UTF-8?q?leCI=20(on=20top=20of=20CiscoM31-maven-h=E2=80=A6=20(#5034)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * replace http with https. Replace http://central.maven.org with https://repo1.maven.org * replace http://www.apache.org/licenses/LICENSE-2.0 with https://www.apache.org/licenses/LICENSE-2.0 * Force HTTPS for mavenCentral gradle DSL Co-authored-by: Sebastien Rosset --- build.gradle.mustache | 4 ++-- libraries/feign/build.gradle.mustache | 2 +- libraries/google-api-client/build.gradle.mustache | 2 +- libraries/jersey2/build.gradle.mustache | 2 +- libraries/microprofile/licenseInfo.mustache | 2 +- libraries/native/build.gradle.mustache | 4 ++-- libraries/okhttp-gson/build.gradle.mustache | 2 +- libraries/rest-assured/build.gradle.mustache | 2 +- libraries/resteasy/build.gradle.mustache | 2 +- libraries/resttemplate/build.gradle.mustache | 2 +- libraries/retrofit/build.gradle.mustache | 2 +- libraries/retrofit2/build.gradle.mustache | 2 +- libraries/vertx/build.gradle.mustache | 2 +- 13 files changed, 15 insertions(+), 15 deletions(-) diff --git a/build.gradle.mustache b/build.gradle.mustache index b761d147c5d..abfb8653bec 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -6,7 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - mavenCentral() + maven { url = "https://repo1.maven.org/maven2" } jcenter() } dependencies { @@ -16,7 +16,7 @@ buildscript { } repositories { - mavenCentral() + maven { url = "https://repo1.maven.org/maven2" } jcenter() } diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index 24e668fdf32..cd78d9e03d3 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -6,7 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - mavenCentral() + maven { url = "https://repo1.maven.org/maven2" } jcenter() } dependencies { diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache index 346ed6625b9..e190e36cdaa 100644 --- a/libraries/google-api-client/build.gradle.mustache +++ b/libraries/google-api-client/build.gradle.mustache @@ -6,7 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - mavenCentral() + maven { url = "https://repo1.maven.org/maven2" } jcenter() } dependencies { diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index 16cc03eeeba..5a162a7d710 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -6,7 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - mavenCentral() + maven { url = "https://repo1.maven.org/maven2" } jcenter() } dependencies { diff --git a/libraries/microprofile/licenseInfo.mustache b/libraries/microprofile/licenseInfo.mustache index 02acad802ec..d148ab0a419 100644 --- a/libraries/microprofile/licenseInfo.mustache +++ b/libraries/microprofile/licenseInfo.mustache @@ -13,7 +13,7 @@ * 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 + * https://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, diff --git a/libraries/native/build.gradle.mustache b/libraries/native/build.gradle.mustache index c797b1ba9b7..a92d040f623 100644 --- a/libraries/native/build.gradle.mustache +++ b/libraries/native/build.gradle.mustache @@ -6,13 +6,13 @@ version = '{{artifactVersion}}' buildscript { repositories { - mavenCentral() + maven { url = "https://repo1.maven.org/maven2" } jcenter() } } repositories { - mavenCentral() + maven { url = "https://repo1.maven.org/maven2" } jcenter() } diff --git a/libraries/okhttp-gson/build.gradle.mustache b/libraries/okhttp-gson/build.gradle.mustache index a149c682201..67f7a7cda4a 100644 --- a/libraries/okhttp-gson/build.gradle.mustache +++ b/libraries/okhttp-gson/build.gradle.mustache @@ -9,7 +9,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - mavenCentral() + maven { url = "https://repo1.maven.org/maven2" } jcenter() } dependencies { diff --git a/libraries/rest-assured/build.gradle.mustache b/libraries/rest-assured/build.gradle.mustache index f6487eefc58..0caef5e4aa7 100644 --- a/libraries/rest-assured/build.gradle.mustache +++ b/libraries/rest-assured/build.gradle.mustache @@ -6,7 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - mavenCentral() + maven { url = "https://repo1.maven.org/maven2" } jcenter() } dependencies { diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index 08ab4a3cce9..5f716aad842 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -6,7 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - mavenCentral() + maven { url = "https://repo1.maven.org/maven2" } jcenter() } dependencies { diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index a957f76822e..610d25d1473 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -6,7 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - mavenCentral() + maven { url = "https://repo1.maven.org/maven2" } jcenter() } dependencies { diff --git a/libraries/retrofit/build.gradle.mustache b/libraries/retrofit/build.gradle.mustache index af83cc1ef05..7431d90eba3 100644 --- a/libraries/retrofit/build.gradle.mustache +++ b/libraries/retrofit/build.gradle.mustache @@ -6,7 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - mavenCentral() + maven { url = "https://repo1.maven.org/maven2" } jcenter() } dependencies { diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index 7d8a096e83c..813886e4b56 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -6,7 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - mavenCentral() + maven { url = "https://repo1.maven.org/maven2" } jcenter() } dependencies { diff --git a/libraries/vertx/build.gradle.mustache b/libraries/vertx/build.gradle.mustache index 456356c925f..e135bc2212a 100644 --- a/libraries/vertx/build.gradle.mustache +++ b/libraries/vertx/build.gradle.mustache @@ -5,7 +5,7 @@ group = '{{groupId}}' version = '{{artifactVersion}}' repositories { - mavenCentral() + maven { url = "https://repo1.maven.org/maven2" } jcenter() } From 76ef3c005f8262f7aee2017b8cfca7cdfd85cc76 Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Sun, 19 Jan 2020 11:57:38 -0800 Subject: [PATCH 190/370] [gradle] consistent use of maven url in gradle files (#5045) * wrap maven url with uri function * consistent use of maven url in gradle files --- build.gradle.mustache | 4 ++-- libraries/feign/build.gradle.mustache | 2 +- libraries/google-api-client/build.gradle.mustache | 2 +- libraries/jersey2/build.gradle.mustache | 2 +- libraries/native/build.gradle.mustache | 4 ++-- libraries/okhttp-gson/build.gradle.mustache | 2 +- libraries/rest-assured/build.gradle.mustache | 2 +- libraries/resteasy/build.gradle.mustache | 2 +- libraries/resttemplate/build.gradle.mustache | 2 +- libraries/retrofit/build.gradle.mustache | 2 +- libraries/retrofit2/build.gradle.mustache | 2 +- libraries/vertx/build.gradle.mustache | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) diff --git a/build.gradle.mustache b/build.gradle.mustache index abfb8653bec..69707eadc16 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -6,7 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - maven { url = "https://repo1.maven.org/maven2" } + maven { url "https://repo1.maven.org/maven2" } jcenter() } dependencies { @@ -16,7 +16,7 @@ buildscript { } repositories { - maven { url = "https://repo1.maven.org/maven2" } + maven { url "https://repo1.maven.org/maven2" } jcenter() } diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index cd78d9e03d3..69170a03177 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -6,7 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - maven { url = "https://repo1.maven.org/maven2" } + maven { url "https://repo1.maven.org/maven2" } jcenter() } dependencies { diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache index e190e36cdaa..0089f90de78 100644 --- a/libraries/google-api-client/build.gradle.mustache +++ b/libraries/google-api-client/build.gradle.mustache @@ -6,7 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - maven { url = "https://repo1.maven.org/maven2" } + maven { url "https://repo1.maven.org/maven2" } jcenter() } dependencies { diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index 5a162a7d710..30aa47428cb 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -6,7 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - maven { url = "https://repo1.maven.org/maven2" } + maven { url "https://repo1.maven.org/maven2" } jcenter() } dependencies { diff --git a/libraries/native/build.gradle.mustache b/libraries/native/build.gradle.mustache index a92d040f623..cea6681a95e 100644 --- a/libraries/native/build.gradle.mustache +++ b/libraries/native/build.gradle.mustache @@ -6,13 +6,13 @@ version = '{{artifactVersion}}' buildscript { repositories { - maven { url = "https://repo1.maven.org/maven2" } + maven { url "https://repo1.maven.org/maven2" } jcenter() } } repositories { - maven { url = "https://repo1.maven.org/maven2" } + maven { url "https://repo1.maven.org/maven2" } jcenter() } diff --git a/libraries/okhttp-gson/build.gradle.mustache b/libraries/okhttp-gson/build.gradle.mustache index 67f7a7cda4a..304b00a445a 100644 --- a/libraries/okhttp-gson/build.gradle.mustache +++ b/libraries/okhttp-gson/build.gradle.mustache @@ -9,7 +9,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - maven { url = "https://repo1.maven.org/maven2" } + maven { url "https://repo1.maven.org/maven2" } jcenter() } dependencies { diff --git a/libraries/rest-assured/build.gradle.mustache b/libraries/rest-assured/build.gradle.mustache index 0caef5e4aa7..b04e53f1e96 100644 --- a/libraries/rest-assured/build.gradle.mustache +++ b/libraries/rest-assured/build.gradle.mustache @@ -6,7 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - maven { url = "https://repo1.maven.org/maven2" } + maven { url "https://repo1.maven.org/maven2" } jcenter() } dependencies { diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index 5f716aad842..59a0970f358 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -6,7 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - maven { url = "https://repo1.maven.org/maven2" } + maven { url "https://repo1.maven.org/maven2" } jcenter() } dependencies { diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index 610d25d1473..33d09ae8305 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -6,7 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - maven { url = "https://repo1.maven.org/maven2" } + maven { url "https://repo1.maven.org/maven2" } jcenter() } dependencies { diff --git a/libraries/retrofit/build.gradle.mustache b/libraries/retrofit/build.gradle.mustache index 7431d90eba3..fab2f0d9fe2 100644 --- a/libraries/retrofit/build.gradle.mustache +++ b/libraries/retrofit/build.gradle.mustache @@ -6,7 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - maven { url = "https://repo1.maven.org/maven2" } + maven { url "https://repo1.maven.org/maven2" } jcenter() } dependencies { diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index 813886e4b56..ea96f094165 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -6,7 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - maven { url = "https://repo1.maven.org/maven2" } + maven { url "https://repo1.maven.org/maven2" } jcenter() } dependencies { diff --git a/libraries/vertx/build.gradle.mustache b/libraries/vertx/build.gradle.mustache index e135bc2212a..53bc7b9a8e5 100644 --- a/libraries/vertx/build.gradle.mustache +++ b/libraries/vertx/build.gradle.mustache @@ -5,7 +5,7 @@ group = '{{groupId}}' version = '{{artifactVersion}}' repositories { - maven { url = "https://repo1.maven.org/maven2" } + maven { url "https://repo1.maven.org/maven2" } jcenter() } From 746baa2b88f47a4771a125e78c533acdcf22286c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Jan 2020 17:00:52 +0800 Subject: [PATCH 191/370] Bump spring-webflux from 5.0.8.RELEASE to 5.1.0.RELEASE in /samples/client/petstore/java/webclient (#5071) * Bump spring-webflux in /samples/client/petstore/java/webclient Bumps [spring-webflux](https://github.com/spring-projects/spring-framework) from 5.0.8.RELEASE to 5.1.0.RELEASE. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v5.0.8.RELEASE...v5.1.0.RELEASE) Signed-off-by: dependabot[bot] * Bump spring-webflux version from 5.0.8 to 5.0.16 ref https://pivotal.io/security/cve-2020-5398 Co-authored-by: Akihito Nakano --- libraries/webclient/pom.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/webclient/pom.mustache b/libraries/webclient/pom.mustache index 7b57232bc5a..39cd7729c35 100644 --- a/libraries/webclient/pom.mustache +++ b/libraries/webclient/pom.mustache @@ -142,7 +142,7 @@ UTF-8 1.5.22 - 5.0.8.RELEASE + 5.0.16.RELEASE 2.10.1 2.10.1 0.2.1 From 9134f8471b0a0fe86bec58947c3233cd35807b99 Mon Sep 17 00:00:00 2001 From: Slavek Kabrda Date: Mon, 27 Jan 2020 14:23:20 +0100 Subject: [PATCH 192/370] [java][client] oneOf support for jackson clients (#5120) --- model.mustache | 2 +- model_test.mustache | 2 ++ oneof_interface.mustache | 6 ++++++ pojo.mustache | 2 +- pojo_doc.mustache | 19 ++++++++++++++++++- typeInfoAnnotation.mustache | 2 +- 6 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 oneof_interface.mustache diff --git a/model.mustache b/model.mustache index 2194bbfdb39..8763e3bd08b 100644 --- a/model.mustache +++ b/model.mustache @@ -42,6 +42,6 @@ import org.hibernate.validator.constraints.*; {{#models}} {{#model}} -{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{>pojo}}{{/isEnum}} +{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{#vendorExtensions.isOneOfInterface}}{{>oneof_interface}}{{/vendorExtensions.isOneOfInterface}}{{^vendorExtensions.isOneOfInterface}}{{>pojo}}{{/vendorExtensions.isOneOfInterface}}{{/isEnum}} {{/model}} {{/models}} diff --git a/model_test.mustache b/model_test.mustache index e72796cdb93..0258f350074 100644 --- a/model_test.mustache +++ b/model_test.mustache @@ -21,6 +21,7 @@ import java.util.Map; public class {{classname}}Test { {{#models}} {{#model}} + {{^vendorExtensions.isOneOfInterface}} {{^isEnum}} private final {{classname}} model = new {{classname}}(); @@ -43,6 +44,7 @@ public class {{classname}}Test { } {{/allVars}} + {{/vendorExtensions.isOneOfInterface}} {{/model}} {{/models}} } diff --git a/oneof_interface.mustache b/oneof_interface.mustache new file mode 100644 index 00000000000..c17cf0b31ca --- /dev/null +++ b/oneof_interface.mustache @@ -0,0 +1,6 @@ +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>typeInfoAnnotation}}{{>xmlAnnotation}} +public interface {{classname}} {{#vendorExtensions.implements}}{{#-first}}extends {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.implements}} { + {{#discriminator}} + public {{propertyType}} {{propertyGetter}}(); + {{/discriminator}} +} diff --git a/pojo.mustache b/pojo.mustache index 796f9a7ec14..3386b1b969a 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -10,7 +10,7 @@ }) {{/jackson}} {{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} -public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcelableModel}}implements Parcelable {{#serializableModel}}, Serializable {{/serializableModel}}{{/parcelableModel}}{{^parcelableModel}}{{#serializableModel}}implements Serializable {{/serializableModel}}{{/parcelableModel}}{ +public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorExtensions.implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.implements}}{ {{#serializableModel}} private static final long serialVersionUID = 1L; diff --git a/pojo_doc.mustache b/pojo_doc.mustache index 313e61ba7e6..e63db5e2720 100644 --- a/pojo_doc.mustache +++ b/pojo_doc.mustache @@ -1,7 +1,8 @@ -# {{classname}} +# {{#vendorExtensions.isOneOfInterface}}Interface {{/vendorExtensions.isOneOfInterface}}{{classname}} {{#description}}{{&description}} {{/description}} +{{^vendorExtensions.isOneOfInterface}} ## Properties Name | Type | Description | Notes @@ -17,3 +18,19 @@ Name | Value ---- | -----{{#allowableValues}}{{#enumVars}} {{name}} | {{value}}{{/enumVars}}{{/allowableValues}} {{/isEnum}}{{/vars}} +{{#vendorExtensions.implements.0}} + +## Implemented Interfaces + +{{#vendorExtensions.implements}} +* {{{.}}} +{{/vendorExtensions.implements}} +{{/vendorExtensions.implements.0}} +{{/vendorExtensions.isOneOfInterface}} +{{#vendorExtensions.isOneOfInterface}} +## Implementing Classes + +{{#oneOf}} +* {{{.}}} +{{/oneOf}} +{{/vendorExtensions.isOneOfInterface}} \ No newline at end of file diff --git a/typeInfoAnnotation.mustache b/typeInfoAnnotation.mustache index a8ab10768e6..81c2ba05f90 100644 --- a/typeInfoAnnotation.mustache +++ b/typeInfoAnnotation.mustache @@ -1,6 +1,6 @@ {{#jackson}} -@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "{{{discriminator.propertyBaseName}}}", visible = true) +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "{{{discriminator.propertyBaseName}}}", visible = true) @JsonSubTypes({ {{#discriminator.mappedModels}} @JsonSubTypes.Type(value = {{modelName}}.class, name = "{{^vendorExtensions.x-discriminator-value}}{{mappingName}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}"), From b37494153196e3b68368e871302a1716b344bad8 Mon Sep 17 00:00:00 2001 From: LoveIsGrief Date: Wed, 29 Jan 2020 10:18:57 +0100 Subject: [PATCH 193/370] Switch to predominant use of appDescriptionWithNewLines in README.mustache (#5109) Descriptions tend to get lengthy and can include multiple lines. New lines are important to markdown formatting/syntax and can't just be ignored. Resolves https://github.com/OpenAPITools/openapi-generator/issues/3704 --- README.mustache | 2 +- libraries/microprofile/README.mustache | 6 +++--- libraries/native/README.mustache | 2 +- libraries/okhttp-gson/README.mustache | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.mustache b/README.mustache index f1bb9f234cd..917f873d5dc 100644 --- a/README.mustache +++ b/README.mustache @@ -8,7 +8,7 @@ - Build date: {{generatedDate}} {{/hideGenerationTimestamp}} -{{#appDescription}}{{{appDescription}}}{{/appDescription}} +{{#appDescriptionWithNewLines}}{{{appDescriptionWithNewLines}}}{{/appDescriptionWithNewLines}} {{#infoUrl}} For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) diff --git a/libraries/microprofile/README.mustache b/libraries/microprofile/README.mustache index 576e70fe8ba..8d126ada313 100644 --- a/libraries/microprofile/README.mustache +++ b/libraries/microprofile/README.mustache @@ -1,9 +1,9 @@ # {{appName}} - MicroProfile Rest Client -{{#appDescription}} -{{{appDescription}}} +{{#appDescriptionWithNewLines}} +{{{appDescriptionWithNewLines}}} -{{/appDescription}} +{{/appDescriptionWithNewLines}} ## Overview This API client was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. [MicroProfile Rest Client](https://github.com/eclipse/microprofile-rest-client) is a type-safe way of calling diff --git a/libraries/native/README.mustache b/libraries/native/README.mustache index 44356cca82c..f574b47b485 100644 --- a/libraries/native/README.mustache +++ b/libraries/native/README.mustache @@ -8,7 +8,7 @@ - Build date: {{generatedDate}} {{/hideGenerationTimestamp}} -{{#appDescription}}{{{appDescription}}}{{/appDescription}} +{{#appDescriptionWithNewLines}}{{{appDescriptionWithNewLines}}}{{/appDescriptionWithNewLines}} {{#infoUrl}} For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) diff --git a/libraries/okhttp-gson/README.mustache b/libraries/okhttp-gson/README.mustache index e459ad31713..e9be868f52c 100644 --- a/libraries/okhttp-gson/README.mustache +++ b/libraries/okhttp-gson/README.mustache @@ -6,7 +6,7 @@ - Build date: {{generatedDate}} {{/hideGenerationTimestamp}} -{{#appDescription}}{{{appDescription}}}{{/appDescription}} +{{#appDescriptionWithNewLines}}{{{appDescriptionWithNewLines}}}{{/appDescriptionWithNewLines}} {{#infoUrl}} For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) From 4ba4b901029854d783a46c9cc8b999bb1369763f Mon Sep 17 00:00:00 2001 From: Ben Cox <1038350+ind1go@users.noreply.github.com> Date: Mon, 3 Feb 2020 09:11:59 +0000 Subject: [PATCH 194/370] [java-jersey2] Fix empty body when form parameters supplied (#5169) --- libraries/jersey2/ApiClient.mustache | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 0f83a20450f..95fb8093bc3 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -573,7 +573,7 @@ public class ApiClient { entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE); } else { // We let jersey handle the serialization - entity = Entity.entity(obj, contentType); + entity = Entity.entity(obj == null ? Entity.text("") : obj, contentType); } return entity; } @@ -732,7 +732,7 @@ public class ApiClient { } } - Entity entity = (body == null) ? Entity.json("") : serialize(body, formParams, contentType); + Entity entity = serialize(body, formParams, contentType); Response response = null; From 36b678b03ba5ba91a261f322a3ea6254f90d44b3 Mon Sep 17 00:00:00 2001 From: gaetPax <47664574+gaetPax@users.noreply.github.com> Date: Wed, 5 Feb 2020 16:10:16 +0100 Subject: [PATCH 195/370] [Java] update feign form dependency version (#5179) * [Java-Feign-issue 5173] - update feign form dependency version * [Java-Feign-issue 5173] - updated feign versions in sample project * [Java-Feign-issue 5173] - fix OAuth in Feign10 sample * [Java-Feign-issue 5173] - updated OAuth Feign template * update feign samples Co-authored-by: William Cheng --- libraries/feign/auth/OAuth.mustache | 6 +++--- libraries/feign/build.gradle.mustache | 4 ++-- libraries/feign/build.sbt.mustache | 8 ++++---- libraries/feign/pom.mustache | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/libraries/feign/auth/OAuth.mustache b/libraries/feign/auth/OAuth.mustache index 25b1f193ba9..feefdb93981 100644 --- a/libraries/feign/auth/OAuth.mustache +++ b/libraries/feign/auth/OAuth.mustache @@ -83,20 +83,20 @@ public class OAuth implements RequestInterceptor { } // If first time, get the token if (expirationTimeMillis == null || System.currentTimeMillis() >= expirationTimeMillis) { - updateAccessToken(); + updateAccessToken(template); } if (getAccessToken() != null) { template.header("Authorization", "Bearer " + getAccessToken()); } } - public synchronized void updateAccessToken() { + public synchronized void updateAccessToken(RequestTemplate template) { OAuthJSONAccessTokenResponse accessTokenResponse; try { accessTokenResponse = oauthClient.accessToken(tokenRequestBuilder.buildBodyMessage()); } catch (Exception e) { {{#useFeign10}} - throw new RetryableException(0, e.getMessage(), HttpMethod.POST, e, null); + throw new RetryableException(0, e.getMessage(), HttpMethod.POST, e, null, template.request()); {{/useFeign10}} {{^useFeign10}} throw new RetryableException(e.getMessage(), e,null); diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index 69170a03177..8693ae09e3c 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -126,8 +126,8 @@ ext { {{#threetenbp}} jackson_threetenbp_version = "2.9.10" {{/threetenbp}} - feign_version = "{{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" - feign_form_version = "2.1.0" + feign_version = "{{#useFeign10}}10.7.4{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" + feign_form_version = "{{#useFeign10}}3.8.0{{/useFeign10}}{{^useFeign10}}2.1.0{{/useFeign10}}" junit_version = "4.13" oltu_version = "1.0.1" } diff --git a/libraries/feign/build.sbt.mustache b/libraries/feign/build.sbt.mustache index 907b7bd4d27..f7004c17868 100644 --- a/libraries/feign/build.sbt.mustache +++ b/libraries/feign/build.sbt.mustache @@ -10,10 +10,10 @@ lazy val root = (project in file(".")). resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( "io.swagger" % "swagger-annotations" % "1.5.22" % "compile", - "io.github.openfeign" % "feign-core" % "{{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", - "io.github.openfeign" % "feign-jackson" % "{{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", - "io.github.openfeign" % "feign-slf4j" % "{{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", - "io.github.openfeign.form" % "feign-form" % "2.1.0" % "compile", + "io.github.openfeign" % "feign-core" % "{{#useFeign10}}10.7.4{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", + "io.github.openfeign" % "feign-jackson" % "{{#useFeign10}}10.7.4{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", + "io.github.openfeign" % "feign-slf4j" % "{{#useFeign10}}10.7.4{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", + "io.github.openfeign.form" % "feign-form" % "{{#useFeign10}}3.8.0{{/useFeign10}}{{^useFeign10}}2.1.0{{/useFeign10}}" % "compile", "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.1" % "compile", diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index e73e45de1b3..3746cf17c96 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -312,8 +312,8 @@ ${java.version} ${java.version} 1.5.21 - {{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}} - 2.1.0 + {{#useFeign10}}10.7.4{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}} + {{#useFeign10}}3.8.0{{/useFeign10}}{{^useFeign10}}2.1.0{{/useFeign10}} 2.10.1 0.2.1 2.10.1 From 2c7f5786a02b1226513814a81017ddec9e935df6 Mon Sep 17 00:00:00 2001 From: Slavek Kabrda Date: Mon, 10 Feb 2020 22:26:32 +0100 Subject: [PATCH 196/370] [go-experimental] Add oneOf support (#5150) * [go-experimental] Add oneOf support * Fix docs for the oneOf models * isOneOfInterface => x-is-one-of-interface * Add proper warnings when inline models are used in oneOf choices * Add a convenience method to oneOf implementing structs to cast them as the oneOf interface * Update modules/openapi-generator/src/main/resources/go-experimental/model.mustache Co-Authored-By: Jiri Kuncar * Fix retrieving data from additionalDataMap * Add basic tests Co-authored-by: Jiri Kuncar --- model.mustache | 2 +- model_test.mustache | 4 ++-- pojo_doc.mustache | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/model.mustache b/model.mustache index 8763e3bd08b..d4d1447a1d4 100644 --- a/model.mustache +++ b/model.mustache @@ -42,6 +42,6 @@ import org.hibernate.validator.constraints.*; {{#models}} {{#model}} -{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{#vendorExtensions.isOneOfInterface}}{{>oneof_interface}}{{/vendorExtensions.isOneOfInterface}}{{^vendorExtensions.isOneOfInterface}}{{>pojo}}{{/vendorExtensions.isOneOfInterface}}{{/isEnum}} +{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{#vendorExtensions.x-is-one-of-interface}}{{>oneof_interface}}{{/vendorExtensions.x-is-one-of-interface}}{{^vendorExtensions.x-is-one-of-interface}}{{>pojo}}{{/vendorExtensions.x-is-one-of-interface}}{{/isEnum}} {{/model}} {{/models}} diff --git a/model_test.mustache b/model_test.mustache index 0258f350074..07468db5657 100644 --- a/model_test.mustache +++ b/model_test.mustache @@ -21,7 +21,7 @@ import java.util.Map; public class {{classname}}Test { {{#models}} {{#model}} - {{^vendorExtensions.isOneOfInterface}} + {{^vendorExtensions.x-is-one-of-interface}} {{^isEnum}} private final {{classname}} model = new {{classname}}(); @@ -44,7 +44,7 @@ public class {{classname}}Test { } {{/allVars}} - {{/vendorExtensions.isOneOfInterface}} + {{/vendorExtensions.x-is-one-of-interface}} {{/model}} {{/models}} } diff --git a/pojo_doc.mustache b/pojo_doc.mustache index e63db5e2720..4c15d09eadb 100644 --- a/pojo_doc.mustache +++ b/pojo_doc.mustache @@ -1,8 +1,8 @@ -# {{#vendorExtensions.isOneOfInterface}}Interface {{/vendorExtensions.isOneOfInterface}}{{classname}} +# {{#vendorExtensions.x-is-one-of-interface}}Interface {{/vendorExtensions.x-is-one-of-interface}}{{classname}} {{#description}}{{&description}} {{/description}} -{{^vendorExtensions.isOneOfInterface}} +{{^vendorExtensions.x-is-one-of-interface}} ## Properties Name | Type | Description | Notes @@ -26,11 +26,11 @@ Name | Value * {{{.}}} {{/vendorExtensions.implements}} {{/vendorExtensions.implements.0}} -{{/vendorExtensions.isOneOfInterface}} -{{#vendorExtensions.isOneOfInterface}} +{{/vendorExtensions.x-is-one-of-interface}} +{{#vendorExtensions.x-is-one-of-interface}} ## Implementing Classes {{#oneOf}} * {{{.}}} {{/oneOf}} -{{/vendorExtensions.isOneOfInterface}} \ No newline at end of file +{{/vendorExtensions.x-is-one-of-interface}} \ No newline at end of file From 742e74cd75b0b36e17b814ea584e52a1b3823f7c Mon Sep 17 00:00:00 2001 From: Timo Rohrberg Date: Thu, 13 Feb 2020 14:55:10 +0100 Subject: [PATCH 197/370] [Java][okhttp-gson] Use builder api of OkHttpClient to avoid UnsupportedOperationEx (#5177) * 3432 Use builder api of OkHttpClient to avoid UnsupportedOperationEx The reason for the UnsupportedOperationException was an invalid access to the interceptors list of OkHttpClient. That list is unmodifiable as stated by the JavaDoc. Instead accessing the list directly, the interceptors should always be passed when building the client by the builder api. * 3432 Use builder api of OkHttpClient to avoid UnsupportedOperationEx The reason for the UnsupportedOperationException was an invalid access to the interceptors list of OkHttpClient. That list is unmodifiable as stated by the JavaDoc. Instead accessing the list directly, the interceptors should always be passed when building the client by the builder api. * 3432 Follow-up fix to make samples compile again * 3432 Updated sample implementation for okHttp-Gson-ParcelableModel --- libraries/okhttp-gson/ApiClient.mustache | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index 3856ddf8c19..1d3511364ca 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -90,6 +90,7 @@ public class ApiClient { */ public ApiClient() { init(); + initHttpClient(); // Setup authentications (key: authentication name, value: authentication).{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} @@ -129,7 +130,7 @@ public class ApiClient { "{{name}}", retryingOAuth ); - httpClient.interceptors().add(retryingOAuth); + initHttpClient(Collections.singletonList(retryingOAuth)); {{/hasOAuthMethods}} // Prevent the authentications from being modified. @@ -139,16 +140,25 @@ public class ApiClient { {{/-first}} {{/oauthMethods}} {{/hasOAuthMethods}} - private void init() { + private void initHttpClient() { + initHttpClient(Collections.emptyList()); + } + + private void initHttpClient(List interceptors) { OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.addNetworkInterceptor(getProgressInterceptor()); - httpClient = builder.build(); - + for (Interceptor interceptor: interceptors) { + builder.addInterceptor(interceptor); + } {{#useGzipFeature}} - // Enable gzip request compression - httpClient.interceptors().add(new GzipRequestInterceptor()); + // Enable gzip request compression + builder.addInterceptor(new GzipRequestInterceptor()); {{/useGzipFeature}} + httpClient = builder.build(); + } + + private void init() { verifyingSsl = true; json = new JSON(); From 2a107c8a5e0ea688306f355f8b2ee3d3e5e53dba Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 14 Feb 2020 13:58:44 +0800 Subject: [PATCH 198/370] [Java] mark Feign 10.x (instead of 9.x) as the default (#5310) * set feign 10x as default, mark 9x as deprecated * update doc --- libraries/okhttp-gson/ApiClient.mustache | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index 1d3511364ca..1f0e606d873 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -151,8 +151,8 @@ public class ApiClient { builder.addInterceptor(interceptor); } {{#useGzipFeature}} - // Enable gzip request compression - builder.addInterceptor(new GzipRequestInterceptor()); + // Enable gzip request compression + builder.addInterceptor(new GzipRequestInterceptor()); {{/useGzipFeature}} httpClient = builder.build(); From 4c9b3a5984b4eee3a572c1e27a97224e53d5a15b Mon Sep 17 00:00:00 2001 From: Jim Schubert Date: Sat, 15 Feb 2020 16:26:32 -0500 Subject: [PATCH 199/370] [templates] Update templates vendor ext standards (#5295) * [templates] Update to vendor extension standard keys * Fix missed value in Java template, also implements=>x-implements. Evaluate Haskell Client changes * Fix missing accept/content-type update for vendor extension format --- libraries/microprofile/pojo.mustache | 6 +-- oneof_interface.mustache | 2 +- pojo.mustache | 64 ++++++++++++++-------------- pojo_doc.mustache | 8 ++-- 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/libraries/microprofile/pojo.mustache b/libraries/microprofile/pojo.mustache index a7d3ddb77c1..4ded8e94e2e 100644 --- a/libraries/microprofile/pojo.mustache +++ b/libraries/microprofile/pojo.mustache @@ -57,9 +57,9 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}}{{#serializ * @return {{name}} **/ @JsonbProperty("{{baseName}}") -{{#vendorExtensions.extraAnnotation}} - {{{vendorExtensions.extraAnnotation}}} -{{/vendorExtensions.extraAnnotation}} +{{#vendorExtensions.x-extra-annotation}} + {{{vendorExtensions.x-extra-annotation}}} +{{/vendorExtensions.x-extra-annotation}} {{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} {{#isEnum}}{{^isListContainer}}{{^isMapContainer}}public {{dataType}} {{getter}}() { if ({{name}} == null) { return null; diff --git a/oneof_interface.mustache b/oneof_interface.mustache index c17cf0b31ca..02deb483d5f 100644 --- a/oneof_interface.mustache +++ b/oneof_interface.mustache @@ -1,5 +1,5 @@ {{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>typeInfoAnnotation}}{{>xmlAnnotation}} -public interface {{classname}} {{#vendorExtensions.implements}}{{#-first}}extends {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.implements}} { +public interface {{classname}} {{#vendorExtensions.x-implements}}{{#-first}}extends {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.x-implements}} { {{#discriminator}} public {{propertyType}} {{propertyGetter}}(); {{/discriminator}} diff --git a/pojo.mustache b/pojo.mustache index 3386b1b969a..c438cd43eb7 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -10,7 +10,7 @@ }) {{/jackson}} {{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} -public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorExtensions.implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.implements}}{ +public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{ {{#serializableModel}} private static final long serialVersionUID = 1L; @@ -56,22 +56,22 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{#gson}} @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}}) {{/gson}} - {{#vendorExtensions.isJacksonOptionalNullable}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} {{#isContainer}} private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined(); {{/isContainer}} {{^isContainer}} private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; {{/isContainer}} - {{/vendorExtensions.isJacksonOptionalNullable}} - {{^vendorExtensions.isJacksonOptionalNullable}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} {{#isContainer}} private {{{datatypeWithEnum}}} {{name}}{{#required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/required}}{{^required}} = null{{/required}}; {{/isContainer}} {{^isContainer}} private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; {{/isContainer}} - {{/vendorExtensions.isJacksonOptionalNullable}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} {{/vars}} {{#parcelableModel}} @@ -99,14 +99,14 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{^isReadOnly}} public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { - {{#vendorExtensions.isJacksonOptionalNullable}}this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});{{/vendorExtensions.isJacksonOptionalNullable}} - {{^vendorExtensions.isJacksonOptionalNullable}}this.{{name}} = {{name}};{{/vendorExtensions.isJacksonOptionalNullable}} + {{#vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});{{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = {{name}};{{/vendorExtensions.x-is-jackson-optional-nullable}} return this; } {{#isListContainer}} public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { - {{#vendorExtensions.isJacksonOptionalNullable}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} if (this.{{name}} == null || !this.{{name}}.isPresent()) { this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); } @@ -116,8 +116,8 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE // this can never happen, as we make sure above that the value is present } return this; - {{/vendorExtensions.isJacksonOptionalNullable}} - {{^vendorExtensions.isJacksonOptionalNullable}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} {{^required}} if (this.{{name}} == null) { this.{{name}} = {{{defaultValue}}}; @@ -125,13 +125,13 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{/required}} this.{{name}}.add({{name}}Item); return this; - {{/vendorExtensions.isJacksonOptionalNullable}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} } {{/isListContainer}} {{#isMapContainer}} public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { - {{#vendorExtensions.isJacksonOptionalNullable}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} if (this.{{name}} == null || !this.{{name}}.isPresent()) { this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); } @@ -141,8 +141,8 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE // this can never happen, as we make sure above that the value is present } return this; - {{/vendorExtensions.isJacksonOptionalNullable}} - {{^vendorExtensions.isJacksonOptionalNullable}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} {{^required}} if (this.{{name}} == null) { this.{{name}} = {{{defaultValue}}}; @@ -150,7 +150,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{/required}} this.{{name}}.put(key, {{name}}Item); return this; - {{/vendorExtensions.isJacksonOptionalNullable}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} } {{/isMapContainer}} @@ -179,49 +179,49 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE @javax.annotation.Nullable {{/required}} {{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} @ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") -{{#vendorExtensions.extraAnnotation}} - {{{vendorExtensions.extraAnnotation}}} -{{/vendorExtensions.extraAnnotation}} -{{#vendorExtensions.isJacksonOptionalNullable}} +{{#vendorExtensions.x-extra-annotation}} + {{{vendorExtensions.x-extra-annotation}}} +{{/vendorExtensions.x-extra-annotation}} +{{#vendorExtensions.x-is-jackson-optional-nullable}} {{!unannotated, Jackson would pick this up automatically and add it *in addition* to the _JsonNullable getter field}} @JsonIgnore -{{/vendorExtensions.isJacksonOptionalNullable}} -{{^vendorExtensions.isJacksonOptionalNullable}}{{#jackson}}{{> jackson_annotations}}{{/jackson}}{{/vendorExtensions.isJacksonOptionalNullable}} +{{/vendorExtensions.x-is-jackson-optional-nullable}} +{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#jackson}}{{> jackson_annotations}}{{/jackson}}{{/vendorExtensions.x-is-jackson-optional-nullable}} public {{{datatypeWithEnum}}} {{getter}}() { - {{#vendorExtensions.isJacksonOptionalNullable}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} {{#isReadOnly}}{{! A readonly attribute doesn't have setter => jackson will set null directly if explicitly returned by API, so make sure we have an empty JsonNullable}} if ({{name}} == null) { {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; } {{/isReadOnly}} return {{name}}.orElse(null); - {{/vendorExtensions.isJacksonOptionalNullable}} - {{^vendorExtensions.isJacksonOptionalNullable}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} return {{name}}; - {{/vendorExtensions.isJacksonOptionalNullable}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} } - {{#vendorExtensions.isJacksonOptionalNullable}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} {{> jackson_annotations}} public JsonNullable<{{{datatypeWithEnum}}}> {{getter}}_JsonNullable() { return {{name}}; } - {{/vendorExtensions.isJacksonOptionalNullable}}{{#vendorExtensions.isJacksonOptionalNullable}} + {{/vendorExtensions.x-is-jackson-optional-nullable}}{{#vendorExtensions.x-is-jackson-optional-nullable}} @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) {{#isReadOnly}}private{{/isReadOnly}}{{^isReadOnly}}public{{/isReadOnly}} void {{setter}}_JsonNullable(JsonNullable<{{{datatypeWithEnum}}}> {{name}}) { {{! For getters/setters that have name differing from attribute name, we must include setter (albeit private) for jackson to be able to set the attribute}} this.{{name}} = {{name}}; } - {{/vendorExtensions.isJacksonOptionalNullable}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} {{^isReadOnly}} public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { - {{#vendorExtensions.isJacksonOptionalNullable}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); - {{/vendorExtensions.isJacksonOptionalNullable}} - {{^vendorExtensions.isJacksonOptionalNullable}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} this.{{name}} = {{name}}; - {{/vendorExtensions.isJacksonOptionalNullable}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} } {{/isReadOnly}} diff --git a/pojo_doc.mustache b/pojo_doc.mustache index 4c15d09eadb..d9381323c87 100644 --- a/pojo_doc.mustache +++ b/pojo_doc.mustache @@ -18,14 +18,14 @@ Name | Value ---- | -----{{#allowableValues}}{{#enumVars}} {{name}} | {{value}}{{/enumVars}}{{/allowableValues}} {{/isEnum}}{{/vars}} -{{#vendorExtensions.implements.0}} +{{#vendorExtensions.x-implements.0}} ## Implemented Interfaces -{{#vendorExtensions.implements}} +{{#vendorExtensions.x-implements}} * {{{.}}} -{{/vendorExtensions.implements}} -{{/vendorExtensions.implements.0}} +{{/vendorExtensions.x-implements}} +{{/vendorExtensions.x-implements.0}} {{/vendorExtensions.x-is-one-of-interface}} {{#vendorExtensions.x-is-one-of-interface}} ## Implementing Classes From 290880429ff1da504701d4249ce6b6950620319d Mon Sep 17 00:00:00 2001 From: Jiri Kuncar Date: Wed, 19 Feb 2020 15:27:45 +0100 Subject: [PATCH 200/370] [java] Support templated servers (#4998) * [java] Support templated servers * Deprecate old signature of invokeAPI method * throw ArrayIndexOutOfBoundsException * Update modules/openapi-generator/src/main/resources/Java/ServerConfiguration.mustache * [java] Regenerate samples Co-authored-by: Jim Schubert --- ApiClient.mustache | 72 +++++++++++++- ServerConfiguration.mustache | 58 ++++++++++++ ServerVariable.mustache | 23 +++++ libraries/jersey2/ApiClient.mustache | 137 ++++++++++++++++++++++++++- libraries/jersey2/api.mustache | 2 +- 5 files changed, 286 insertions(+), 6 deletions(-) create mode 100644 ServerConfiguration.mustache create mode 100644 ServerVariable.mustache diff --git a/ApiClient.mustache b/ApiClient.mustache index 1ae6c36f68a..8b71c1551e3 100644 --- a/ApiClient.mustache +++ b/ApiClient.mustache @@ -38,7 +38,9 @@ import java.util.Collections; import java.util.Map; import java.util.Map.Entry; import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Arrays; import java.util.ArrayList; import java.util.Date; import java.util.TimeZone; @@ -63,6 +65,33 @@ public class ApiClient { private Map defaultHeaderMap = new HashMap(); private Map defaultCookieMap = new HashMap(); private String basePath = "{{{basePath}}}"; + protected List servers = new ArrayList({{#servers}}{{#-first}}Arrays.asList( +{{/-first}} new ServerConfiguration( + "{{{url}}}", + "{{{description}}}{{^description}}No description provided{{/description}}", + new HashMap(){{#variables}}{{#-first}} {{ +{{/-first}} put("{{{name}}}", new ServerVariable( + "{{{description}}}{{^description}}No description provided{{/description}}", + "{{{defaultValue}}}", + new HashSet( + {{#enumValues}} + {{#-first}} + Arrays.asList( + {{/-first}} + "{{{.}}}"{{^-last}},{{/-last}} + {{#-last}} + ) + {{/-last}} + {{/enumValues}} + ) + )); + {{#-last}} + }}{{/-last}}{{/variables}} + ){{^-last}},{{/-last}} + {{#-last}} + ){{/-last}}{{/servers}}); + protected Integer serverIndex = 0; + protected Map serverVariables = null; private boolean debugging = false; private int connectionTimeout = 0; @@ -177,6 +206,33 @@ public class ApiClient { return this; } + public List getServers() { + return servers; + } + + public ApiClient setServers(List servers) { + this.servers = servers; + return this; + } + + public Integer getServerIndex() { + return serverIndex; + } + + public ApiClient setServerIndex(Integer serverIndex) { + this.serverIndex = serverIndex; + return this; + } + + public Map getServerVariables() { + return serverVariables; + } + + public ApiClient setServerVariables(Map serverVariables) { + this.serverVariables = serverVariables; + return this; + } + /** * Gets the status code of the previous request * @return Status code @@ -252,7 +308,7 @@ public class ApiClient { } throw new RuntimeException("No API key authentication configured!"); } - + /** * Helper method to set API key prefix for the first API key authentication. * @param apiKeyPrefix API key prefix @@ -626,8 +682,20 @@ public class ApiClient { * @return The full URL */ private String buildUrl(String path, List queryParams, List collectionQueryParams) { + String baseURL; + if (serverIndex != null) { + if (serverIndex < 0 || serverIndex >= servers.size()) { + throw new ArrayIndexOutOfBoundsException(String.format( + "Invalid index %d when selecting the host settings. Must be less than %d", serverIndex, servers.size() + )); + } + baseURL = servers.get(serverIndex).URL(serverVariables); + } else { + baseURL = basePath; + } + final StringBuilder url = new StringBuilder(); - url.append(basePath).append(path); + url.append(baseURL).append(path); if (queryParams != null && !queryParams.isEmpty()) { // support (constant) query string in `path`, e.g. "/posts?draft=1" diff --git a/ServerConfiguration.mustache b/ServerConfiguration.mustache new file mode 100644 index 00000000000..f976c542b19 --- /dev/null +++ b/ServerConfiguration.mustache @@ -0,0 +1,58 @@ +package {{invokerPackage}}; + +import java.util.Map; + +/** + * Representing a Server configuration. + */ +public class ServerConfiguration { + public String URL; + public String description; + public Map variables; + + /** + * @param URL A URL to the target host. + * @param description A describtion of the host designated by the URL. + * @param variables A map between a variable name and its value. The value is used for substitution in the server's URL template. + */ + public ServerConfiguration(String URL, String description, Map variables) { + this.URL = URL; + this.description = description; + this.variables = variables; + } + + /** + * Format URL template using given variables. + * + * @param variables A map between a variable name and its value. + * @return Formatted URL. + */ + public String URL(Map variables) { + String url = this.URL; + + // go through variables and replace placeholders + for (Map.Entry variable: this.variables.entrySet()) { + String name = variable.getKey(); + ServerVariable serverVariable = variable.getValue(); + String value = serverVariable.defaultValue; + + if (variables != null && variables.containsKey(name)) { + value = variables.get(name); + if (serverVariable.enumValues.size() > 0 && !serverVariable.enumValues.contains(value)) { + throw new RuntimeException("The variable " + name + " in the server URL has invalid value " + value + "."); + } + } + url = url.replaceAll("\\{" + name + "\\}", value); + } + return url; + } + + /** + * Format URL template using default server variables. + * + * @return Formatted URL. + */ + public String URL() { + return URL(null); + } +} diff --git a/ServerVariable.mustache b/ServerVariable.mustache new file mode 100644 index 00000000000..1978b1eb95e --- /dev/null +++ b/ServerVariable.mustache @@ -0,0 +1,23 @@ +package {{invokerPackage}}; + +import java.util.HashSet; + +/** + * Representing a Server Variable for server URL template substitution. + */ +public class ServerVariable { + public String description; + public String defaultValue; + public HashSet enumValues = null; + + /** + * @param description A description for the server variable. + * @param defaultValue The default value to use for substitution. + * @param enumValues An enumeration of string values to be used if the substitution options are from a limited set. + */ + public ServerVariable(String description, String defaultValue, HashSet enumValues) { + this.description = description; + this.defaultValue = defaultValue; + this.enumValues = enumValues; + } +} diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 95fb8093bc3..15632392a3f 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -37,7 +37,9 @@ import java.util.Collections; import java.util.Map; import java.util.Map.Entry; import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Arrays; import java.util.ArrayList; import java.util.Date; import java.util.TimeZone; @@ -55,6 +57,7 @@ import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; import {{invokerPackage}}.auth.HttpBearerAuth; import {{invokerPackage}}.auth.ApiKeyAuth; + {{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} @@ -64,6 +67,74 @@ public class ApiClient { protected Map defaultHeaderMap = new HashMap(); protected Map defaultCookieMap = new HashMap(); protected String basePath = "{{{basePath}}}"; + protected List servers = new ArrayList({{#servers}}{{#-first}}Arrays.asList( +{{/-first}} new ServerConfiguration( + "{{{url}}}", + "{{{description}}}{{^description}}No description provided{{/description}}", + new HashMap(){{#variables}}{{#-first}} {{ +{{/-first}} put("{{{name}}}", new ServerVariable( + "{{{description}}}{{^description}}No description provided{{/description}}", + "{{{defaultValue}}}", + new HashSet( + {{#enumValues}} + {{#-first}} + Arrays.asList( + {{/-first}} + "{{{.}}}"{{^-last}},{{/-last}} + {{#-last}} + ) + {{/-last}} + {{/enumValues}} + ) + )); + {{#-last}} + }}{{/-last}}{{/variables}} + ){{^-last}},{{/-last}} + {{#-last}} + ){{/-last}}{{/servers}}); + protected Integer serverIndex = 0; + protected Map serverVariables = null; + protected Map> operationServers = new HashMap>() {{ + {{#apiInfo}} + {{#apis}} + {{#operations}} + {{#operation}} + {{#servers}} + {{#-first}} + put("{{{classname}}}.{{{operationId}}}", new ArrayList(Arrays.asList( + {{/-first}} + new ServerConfiguration( + "{{{url}}}", + "{{{description}}}{{^description}}No description provided{{/description}}", + new HashMap(){{#variables}}{{#-first}} {{ +{{/-first}} put("{{{name}}}", new ServerVariable( + "{{{description}}}{{^description}}No description provided{{/description}}", + "{{{defaultValue}}}", + new HashSet( + {{#enumValues}} + {{#-first}} + Arrays.asList( + {{/-first}} + "{{{.}}}"{{^-last}},{{/-last}} + {{#-last}} + ) + {{/-last}} + {{/enumValues}} + ) + )); + {{#-last}} + }}{{/-last}}{{/variables}} + ){{^-last}},{{/-last}} + {{#-last}} + )));{{/-last}} + {{/servers}} + {{/operation}} + {{/operations}} + {{/apis}} + {{/apiInfo}} + }}; + protected Map operationServerIndex = new HashMap(); + protected Map> operationServerVariables = new HashMap>(); protected boolean debugging = false; protected int connectionTimeout = 0; private int readTimeout = 0; @@ -121,6 +192,33 @@ public class ApiClient { return this; } + public List getServers() { + return servers; + } + + public ApiClient setServers(List servers) { + this.servers = servers; + return this; + } + + public Integer getServerIndex() { + return serverIndex; + } + + public ApiClient setServerIndex(Integer serverIndex) { + this.serverIndex = serverIndex; + return this; + } + + public Map getServerVariables() { + return serverVariables; + } + + public ApiClient setServerVariables(Map serverVariables) { + this.serverVariables = serverVariables; + return this; + } + /** * Get authentications (key: authentication name, value: authentication). * @return Map of authentication object @@ -670,6 +768,7 @@ public class ApiClient { * Invoke API by sending HTTP request with the given options. * * @param Type + * @param operation The qualified name of the operation * @param path The sub-path of the HTTP URL * @param method The request method, one of "GET", "POST", "PUT", "HEAD" and "DELETE" * @param queryParams The query parameters @@ -684,12 +783,36 @@ public class ApiClient { * @return The response body in type of string * @throws ApiException API exception */ - public ApiResponse invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { + public ApiResponse invokeAPI(String operation, String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); - // Not using `.target(this.basePath).path(path)` below, + // Not using `.target(targetURL).path(path)` below, // to support (constant) query string in `path`, e.g. "/posts?draft=1" - WebTarget target = httpClient.target(this.basePath + path); + String targetURL; + if (serverIndex != null) { + Integer index; + List serverConfigurations; + Map variables; + + if (operationServers.containsKey(operation)) { + index = operationServerIndex.getOrDefault(operation, serverIndex); + variables = operationServerVariables.getOrDefault(operation, serverVariables); + serverConfigurations = operationServers.get(operation); + } else { + index = serverIndex; + variables = serverVariables; + serverConfigurations = servers; + } + if (index < 0 || index >= serverConfigurations.size()) { + throw new ArrayIndexOutOfBoundsException(String.format( + "Invalid index %d when selecting the host settings. Must be less than %d", index, serverConfigurations.size() + )); + } + targetURL = serverConfigurations.get(index).URL(variables) + path; + } else { + targetURL = this.basePath + path; + } + WebTarget target = httpClient.target(targetURL); if (queryParams != null) { for (Pair queryParam : queryParams) { @@ -793,6 +916,14 @@ public class ApiClient { } } + /** + * @deprecated Add qualified name of the operation as a first parameter. + */ + @Deprecated + public ApiResponse invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { + return invokeAPI(null, path, method, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType); + } + /** * Build the Client used to make HTTP requests. * @param debugging Debug setting diff --git a/libraries/jersey2/api.mustache b/libraries/jersey2/api.mustache index 3950d7a2af3..4a2e61afe8e 100644 --- a/libraries/jersey2/api.mustache +++ b/libraries/jersey2/api.mustache @@ -151,7 +151,7 @@ public class {{classname}} { String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; {{#returnType}}GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {};{{/returnType}} - return apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, {{#returnType}}localVarReturnType{{/returnType}}{{^returnType}}null{{/returnType}}); + return apiClient.invokeAPI("{{classname}}.{{operationId}}", localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, {{#returnType}}localVarReturnType{{/returnType}}{{^returnType}}null{{/returnType}}); } {{#vendorExtensions.x-group-parameters}} From 916835522fa770e2dd7a728665f4388e41faa516 Mon Sep 17 00:00:00 2001 From: Igor Savin Date: Wed, 19 Feb 2020 17:28:21 +0100 Subject: [PATCH 201/370] Update maven-javadoc-plugin for Java 11 support (#5361) * Resolves `An error has occurred in Javadoc report generation: [ERROR] Exit code: 1 - javadoc: error - The code being documented uses modules but the packages defined in https://docs.oracle.com/javase/8/docs/api/ are in the unnamed module` error that happens when using Java 11 * Resolves `An error has occurred in Javadoc report generation: [ERROR] Exit code: 1 - javadoc: error - The code being documented uses modules but the packages defined in https://docs.oracle.com/javase/8/docs/api/ are in the unnamed module` error that happens when using Java 11 * Fix duplicate configuration entries * Fix okhttp poms * Remove letter that shouldn't be there --- libraries/feign/pom.mustache | 5 ++++- libraries/google-api-client/pom.mustache | 5 ++++- libraries/jersey2/pom.mustache | 3 ++- libraries/okhttp-gson/pom.mustache | 3 ++- libraries/rest-assured/pom.mustache | 5 ++++- libraries/resteasy/pom.mustache | 5 ++++- libraries/resttemplate/pom.mustache | 5 ++++- libraries/retrofit/pom.mustache | 5 ++++- libraries/retrofit2/pom.mustache | 5 ++++- libraries/vertx/pom.mustache | 5 ++++- pom.mustache | 5 ++++- 11 files changed, 40 insertions(+), 11 deletions(-) diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index 3746cf17c96..9ff42c84cb4 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -142,7 +142,10 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.4 + 3.1.1 + + none + attach-javadocs diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index 5e3c04fe93b..4f45670c322 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -163,7 +163,10 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.4 + 3.1.1 + + none + attach-javadocs diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index e9fc8ba3942..23dccf1d88c 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -163,7 +163,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.4 + 3.1.1 attach-javadocs @@ -173,6 +173,7 @@ + none http.response.details diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index e4c05f4151d..6f04c25e1c9 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -142,7 +142,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.4 + 3.1.1 attach-javadocs @@ -152,6 +152,7 @@ + none http.response.details diff --git a/libraries/rest-assured/pom.mustache b/libraries/rest-assured/pom.mustache index 9c49fb07774..da538caa9b0 100644 --- a/libraries/rest-assured/pom.mustache +++ b/libraries/rest-assured/pom.mustache @@ -150,7 +150,10 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.4 + 3.1.1 + + none + attach-javadocs diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index e3e127020e4..880eadd80b0 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -161,7 +161,10 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.4 + 3.1.1 + + none + attach-javadocs diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache index 1f5e82d501f..b02cb86dc86 100644 --- a/libraries/resttemplate/pom.mustache +++ b/libraries/resttemplate/pom.mustache @@ -163,7 +163,10 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.4 + 3.1.1 + + none + attach-javadocs diff --git a/libraries/retrofit/pom.mustache b/libraries/retrofit/pom.mustache index 5a40a07979c..7c689ae4b6c 100644 --- a/libraries/retrofit/pom.mustache +++ b/libraries/retrofit/pom.mustache @@ -163,7 +163,10 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.4 + 3.1.1 + + none + attach-javadocs diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index 9613f948416..dd087eff058 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -142,7 +142,10 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.4 + 3.1.1 + + none + attach-javadocs diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache index 3ed8b93b490..325c2b81c7b 100644 --- a/libraries/vertx/pom.mustache +++ b/libraries/vertx/pom.mustache @@ -151,7 +151,10 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.4 + 3.1.1 + + none + attach-javadocs diff --git a/pom.mustache b/pom.mustache index b17b2357bad..351f5c478fe 100644 --- a/pom.mustache +++ b/pom.mustache @@ -163,7 +163,10 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.4 + 3.1.1 + + none + attach-javadocs From d1dd68510d4f9a79a40f3c6f28093ba4a50342b2 Mon Sep 17 00:00:00 2001 From: dwlabcube <46682038+dwlabcube@users.noreply.github.com> Date: Tue, 25 Feb 2020 11:10:40 +0100 Subject: [PATCH 202/370] Removal of Encoding in the Query-Params in order to prevent double Encoding. (#5255) This way letting WebClient do its Job in encoding the URL. --- libraries/webclient/ApiClient.mustache | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index e21f3847641..5c996d94c5d 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -555,23 +555,11 @@ public class ApiClient { updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(path); - if (queryParams != null) { - //encode the query parameters in case they contain unsafe characters - for (List values : queryParams.values()) { - if (values != null) { - for (int i = 0; i < values.size(); i++) { - try { - values.set(i, URLEncoder.encode(values.get(i), "utf8")); - } catch (UnsupportedEncodingException e) { - - } - } - } - } + if (queryParams != null) { builder.queryParams(queryParams); } - final WebClient.RequestBodySpec requestBuilder = webClient.method(method).uri(builder.encode().toUriString(), pathParams); + final WebClient.RequestBodySpec requestBuilder = webClient.method(method).uri(builder.build(false).toUriString(), pathParams); if(accept != null) { requestBuilder.accept(accept.toArray(new MediaType[accept.size()])); } From dca3021849c3b04b0513fa329ae9e2f0bd0d3016 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Thu, 27 Feb 2020 12:05:03 +0800 Subject: [PATCH 203/370] [Java][WebClient] better code format (#5433) * better code format for java webclient * prefix local varaible with localVar --- libraries/webclient/ApiClient.mustache | 2 +- libraries/webclient/api.mustache | 73 +++++++++++++++++--------- 2 files changed, 48 insertions(+), 27 deletions(-) diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index 5c996d94c5d..72b80bac81a 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -555,7 +555,7 @@ public class ApiClient { updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(path); - if (queryParams != null) { + if (queryParams != null) { builder.queryParams(queryParams); } diff --git a/libraries/webclient/api.mustache b/libraries/webclient/api.mustache index 9138d7d2e7a..b852e87ec4e 100644 --- a/libraries/webclient/api.mustache +++ b/libraries/webclient/api.mustache @@ -4,11 +4,13 @@ import {{invokerPackage}}.ApiClient; {{#imports}}import {{import}}; {{/imports}} +{{^fullJavaUtil}} -{{^fullJavaUtil}}import java.util.HashMap; +import java.util.HashMap; import java.util.List; import java.util.Locale; -import java.util.Map;{{/fullJavaUtil}} +import java.util.Map; +{{/fullJavaUtil}} import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.LinkedMultiValueMap; @@ -62,49 +64,68 @@ public class {{classname}} { */ public {{#returnType}}{{#isListContainer}}Flux<{{{returnBaseType}}}>{{/isListContainer}}{{^isListContainer}}Mono<{{{returnType}}}>{{/isListContainer}} {{/returnType}}{{^returnType}}Mono {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { Object postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; - {{#allParams}}{{#required}} + {{#allParams}} + {{#required}} // verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); } - {{/required}}{{/allParams}} + {{/required}} + {{/allParams}} // create path and map variables - final Map pathParams = new HashMap();{{#hasPathParams}}{{#pathParams}} - pathParams.put("{{baseName}}", {{#collectionFormat}}apiClient.collectionPathParameterToString(ApiClient.CollectionFormat.valueOf("csv".toUpperCase()), {{/collectionFormat}}{{{paramName}}}{{#collectionFormat}}){{/collectionFormat}});{{/pathParams}}{{/hasPathParams}} + final Map pathParams = new HashMap(); + {{#hasPathParams}} + {{#pathParams}} + pathParams.put("{{baseName}}", {{#collectionFormat}}apiClient.collectionPathParameterToString(ApiClient.CollectionFormat.valueOf("csv".toUpperCase()), {{/collectionFormat}}{{{paramName}}}{{#collectionFormat}}){{/collectionFormat}}); + {{/pathParams}} + {{/hasPathParams}} final MultiValueMap queryParams = new LinkedMultiValueMap(); final HttpHeaders headerParams = new HttpHeaders(); final MultiValueMap cookieParams = new LinkedMultiValueMap(); - final MultiValueMap formParams = new LinkedMultiValueMap();{{#hasQueryParams}} + final MultiValueMap formParams = new LinkedMultiValueMap(); + {{#hasQueryParams}} - {{#queryParams}}queryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{#hasMore}} - {{/hasMore}}{{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}} + {{#queryParams}} + queryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}})); + {{/queryParams}} + {{/hasQueryParams}} + {{#hasHeaderParams}} - {{#headerParams}}if ({{paramName}} != null) + {{#headerParams}} + if ({{paramName}} != null) headerParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{#hasMore}} - {{/hasMore}}{{/headerParams}}{{/hasHeaderParams}}{{#hasCookieParams}} - - {{#cookieParams}}cookieParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{#hasMore}} - {{/hasMore}}{{/cookieParams}}{{/hasCookieParams}}{{#hasFormParams}} - - {{#formParams}}if ({{paramName}} != null) - formParams.add{{#collectionFormat}}All{{/collectionFormat}}("{{baseName}}", {{#isFile}}new FileSystemResource({{paramName}}){{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} - {{/hasMore}}{{/formParams}}{{/hasFormParams}} - - final String[] accepts = { {{#hasProduces}} + {{/hasMore}} + {{/headerParams}} + {{/hasHeaderParams}} + {{#hasCookieParams}} + + {{#cookieParams}} + cookieParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}})); + {{/cookieParams}} + {{/hasCookieParams}} + {{#hasFormParams}} + + {{#formParams}} + if ({{paramName}} != null) + formParams.add{{#collectionFormat}}All{{/collectionFormat}}("{{baseName}}", {{#isFile}}new FileSystemResource({{paramName}}){{/isFile}}{{^isFile}}{{paramName}}{{/isFile}}); + {{/formParams}} + {{/hasFormParams}} + + final String[] localVarAccepts = { {{#hasProduces}} {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} {{/hasProduces}}}; - final List accept = apiClient.selectHeaderAccept(accepts); - final String[] contentTypes = { {{#hasConsumes}} + final List localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); + final String[] localVarContentTypes = { {{#hasConsumes}} {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} {{/hasConsumes}}}; - final MediaType contentType = apiClient.selectHeaderContentType(contentTypes); + final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); - String[] authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; - {{#returnType}}ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}> returnType = new ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference returnType = new ParameterizedTypeReference() {};{{/returnType}} - return apiClient.{{#isListContainer}}invokeFluxAPI{{/isListContainer}}{{^isListContainer}}invokeAPI{{/isListContainer}}("{{{path}}}", HttpMethod.{{httpMethod}}, pathParams, queryParams, postBody, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType); + {{#returnType}}ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}> localVarReturnType = new ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference localVarReturnType = new ParameterizedTypeReference() {};{{/returnType}} + return apiClient.{{#isListContainer}}invokeFluxAPI{{/isListContainer}}{{^isListContainer}}invokeAPI{{/isListContainer}}("{{{path}}}", HttpMethod.{{httpMethod}}, pathParams, queryParams, postBody, headerParams, cookieParams, formParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType); } {{/operation}} } From 7ab97fd9cc7bd18133f782ded2f21d970d5839da Mon Sep 17 00:00:00 2001 From: Jiri Kuncar Date: Sun, 1 Mar 2020 09:33:18 +0100 Subject: [PATCH 204/370] [java] Support aliasing of API keys (#4966) * [java] Support aliasing of API keys * Rebuild Java Jersey2 sample client * x-lookup to x-auth-id-alias * Regenerated --- libraries/jersey2/ApiClient.mustache | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 15632392a3f..0111a24c4da 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -144,6 +144,7 @@ public class ApiClient { protected String tempFolderPath = null; protected Map authentications; + protected Map authenticationLookup; protected DateFormat dateFormat; @@ -164,6 +165,10 @@ public class ApiClient { authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} // Prevent the authentications from being modified. authentications = Collections.unmodifiableMap(authentications); + + // Setup authentication lookup (key: authentication alias, value: authentication name) + authenticationLookup = new HashMap();{{#authMethods}}{{#vendorExtensions.x-auth-id-alias}} + authenticationLookup.put("{{name}}", "{{.}}");{{/vendorExtensions.x-auth-id-alias}}{{/authMethods}} } /** @@ -279,6 +284,25 @@ public class ApiClient { throw new RuntimeException("No API key authentication configured!"); } + /** + * Helper method to configure authentications which respects aliases of API keys. + * + * @param secrets Hash map from authentication name to its secret. + */ + public void configureApiKeys(HashMap secrets) { + for (Map.Entry authEntry : authentications.entrySet()) { + Authentication auth = authEntry.getValue(); + if (auth instanceof ApiKeyAuth) { + String name = authEntry.getKey(); + // respect x-auth-id-alias property + name = authenticationLookup.getOrDefault(name, name); + if (secrets.containsKey(name)) { + ((ApiKeyAuth) auth).setApiKey(secrets.get(name)); + } + } + } + } + /** * Helper method to set API key prefix for the first API key authentication. * @param apiKeyPrefix API key prefix From 7276f1ca9d673d4889c9997959c5b343ec10575a Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 6 Mar 2020 14:49:58 +0800 Subject: [PATCH 205/370] update jackson dependency to newer version (#5527) --- build.gradle.mustache | 9 ++++++--- build.sbt.mustache | 1 + libraries/feign/build.gradle.mustache | 4 ++-- libraries/feign/build.sbt.mustache | 6 +++--- libraries/feign/pom.mustache | 4 ++-- libraries/google-api-client/pom.mustache | 4 ++-- libraries/jersey2/build.gradle.mustache | 4 ++-- libraries/jersey2/build.sbt.mustache | 6 +++--- libraries/jersey2/pom.mustache | 4 ++-- libraries/resteasy/build.gradle.mustache | 4 ++-- libraries/resteasy/build.sbt.mustache | 6 +++--- libraries/resteasy/pom.mustache | 4 ++-- libraries/resttemplate/build.gradle.mustache | 4 ++-- libraries/resttemplate/pom.mustache | 4 ++-- libraries/retrofit2/build.gradle.mustache | 4 ++-- libraries/retrofit2/build.sbt.mustache | 12 ++++++------ libraries/retrofit2/pom.mustache | 6 +++--- libraries/vertx/build.gradle.mustache | 4 ++-- libraries/vertx/pom.mustache | 4 ++-- libraries/webclient/pom.mustache | 4 ++-- pom.mustache | 7 +++++-- 21 files changed, 56 insertions(+), 49 deletions(-) diff --git a/build.gradle.mustache b/build.gradle.mustache index 69707eadc16..c1bf968dbac 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -136,9 +136,12 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.10.1" - jackson_databind_version = "2.10.1" + jackson_version = "2.10.3" + jackson_databind_version = "2.10.3" jackson_databind_nullable_version = "0.2.1" + {{#threetenbp}} + jackson_threetenbp_version = "2.9.10" + {{/threetenbp}} jersey_version = "1.19.4" jodatime_version = "2.9.9" junit_version = "4.13" @@ -161,7 +164,7 @@ dependencies { compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_version" + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threetenbp_version" {{/threetenbp}} {{^java8}} compile "com.brsanthu:migbase64:2.2" diff --git a/build.sbt.mustache b/build.sbt.mustache index e69de29bb2d..464090415c4 100644 --- a/build.sbt.mustache +++ b/build.sbt.mustache @@ -0,0 +1 @@ +# TODO diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index 8693ae09e3c..2a6c4c79fbc 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -120,8 +120,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.10.1" - jackson_databind_version = "2.10.1" + jackson_version = "2.10.3" + jackson_databind_version = "2.10.3" jackson_databind_nullable_version = "0.2.1" {{#threetenbp}} jackson_threetenbp_version = "2.9.10" diff --git a/libraries/feign/build.sbt.mustache b/libraries/feign/build.sbt.mustache index f7004c17868..8fa1d345b26 100644 --- a/libraries/feign/build.sbt.mustache +++ b/libraries/feign/build.sbt.mustache @@ -14,9 +14,9 @@ lazy val root = (project in file(".")). "io.github.openfeign" % "feign-jackson" % "{{#useFeign10}}10.7.4{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", "io.github.openfeign" % "feign-slf4j" % "{{#useFeign10}}10.7.4{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", "io.github.openfeign.form" % "feign-form" % "{{#useFeign10}}3.8.0{{/useFeign10}}{{^useFeign10}}2.1.0{{/useFeign10}}" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", "com.fasterxml.jackson.datatype" % "jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}" % "2.9.10" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index 9ff42c84cb4..86f6f397781 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -317,9 +317,9 @@ 1.5.21 {{#useFeign10}}10.7.4{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}} {{#useFeign10}}3.8.0{{/useFeign10}}{{^useFeign10}}2.1.0{{/useFeign10}} - 2.10.1 + 2.10.3 0.2.1 - 2.10.1 + 2.10.3 {{#threetenbp}} 2.9.10 {{/threetenbp}} diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index 4f45670c322..4d6a8c5e161 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -309,8 +309,8 @@ 1.5.22 1.30.2 2.25.1 - 2.10.1 - 2.10.1 + 2.10.3 + 2.10.3 0.2.1 {{#joda}} 2.9.9 diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index 30aa47428cb..cdb451adb34 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -119,8 +119,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.10.1" - jackson_databind_version = "2.10.1" + jackson_version = "2.10.3" + jackson_databind_version = "2.10.3" jackson_databind_nullable_version = "0.2.1" {{#supportJava6}} jersey_version = "2.6" diff --git a/libraries/jersey2/build.sbt.mustache b/libraries/jersey2/build.sbt.mustache index 7e2dc832a2c..abb91ecdc99 100644 --- a/libraries/jersey2/build.sbt.mustache +++ b/libraries/jersey2/build.sbt.mustache @@ -13,9 +13,9 @@ lazy val root = (project in file(".")). "org.glassfish.jersey.core" % "jersey-client" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, "org.glassfish.jersey.media" % "jersey-media-multipart" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, "org.glassfish.jersey.media" % "jersey-media-json-jackson" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", {{#joda}} "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.10" % "compile", {{/joda}} diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 23dccf1d88c..9bd8925f001 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -361,8 +361,8 @@ 2.5 3.6 {{/supportJava6}} - 2.10.1 - 2.10.1 + 2.10.3 + 2.10.3 0.2.1 {{#threetenbp}} 2.9.10 diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index 59a0970f358..89c6fb24ee4 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -119,8 +119,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.10.1" - jackson_databind_version = "2.10.1" + jackson_version = "2.10.3" + jackson_databind_version = "2.10.3" jackson_databind_nullable_version = "0.2.1" threetenbp_version = "2.9.10" resteasy_version = "3.1.3.Final" diff --git a/libraries/resteasy/build.sbt.mustache b/libraries/resteasy/build.sbt.mustache index 936c4141f8f..351c072616f 100644 --- a/libraries/resteasy/build.sbt.mustache +++ b/libraries/resteasy/build.sbt.mustache @@ -13,9 +13,9 @@ lazy val root = (project in file(".")). "org.jboss.resteasy" % "resteasy-client" % "3.1.3.Final" % "compile", "org.jboss.resteasy" % "resteasy-multipart-provider" % "3.1.3.Final" % "compile", "org.jboss.resteasy" % "resteasy-jackson2-provider" % "3.1.3.Final" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", {{#java8}} "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.10" % "compile", diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index 880eadd80b0..714f4299b74 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -297,8 +297,8 @@ UTF-8 1.5.22 3.1.3.Final - 2.10.1 - 2.10.1 + 2.10.3 + 2.10.3 0.2.1 2.9.10 {{^java8}} diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index 33d09ae8305..c61825adbb9 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -120,8 +120,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.10.1" - jackson_databind_version = "2.10.1" + jackson_version = "2.10.3" + jackson_databind_version = "2.10.3" jackson_databind_nullable_version = "0.2.1" spring_web_version = "4.3.9.RELEASE" jodatime_version = "2.9.9" diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache index b02cb86dc86..c9f02fffca4 100644 --- a/libraries/resttemplate/pom.mustache +++ b/libraries/resttemplate/pom.mustache @@ -312,8 +312,8 @@ UTF-8 1.5.22 4.3.9.RELEASE - 2.10.1 - 2.10.1 + 2.10.3 + 2.10.3 0.2.1 {{#joda}} 2.9.9 diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index ea96f094165..82f7974062b 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -131,8 +131,8 @@ ext { play_version = "2.5.14" {{/play25}} {{#play26}} - jackson_version = "2.10.1" - jackson_databind_version = "2.10.1" + jackson_version = "2.10.3" + jackson_databind_version = "2.10.3" jackson_databind_nullable_version = "0.2.1" play_version = "2.6.7" {{/play26}} diff --git a/libraries/retrofit2/build.sbt.mustache b/libraries/retrofit2/build.sbt.mustache index be45635e47f..f7b7ce464d5 100644 --- a/libraries/retrofit2/build.sbt.mustache +++ b/libraries/retrofit2/build.sbt.mustache @@ -23,16 +23,16 @@ lazy val root = (project in file(".")). {{/play24}} {{#play25}} "com.typesafe.play" % "play-java-ws_2.11" % "2.5.15" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", {{/play25}} {{#play26}} "com.typesafe.play" % "play-ahc-ws_2.12" % "2.6.7" % "compile", "javax.validation" % "validation-api" % "1.1.0.Final" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10.3" % "compile", {{/play26}} "com.squareup.retrofit2" % "converter-jackson" % "2.3.0" % "compile", {{/usePlayWS}} diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index dd087eff058..06f19bcb034 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -378,17 +378,17 @@ 1.8.3 1.5.22 {{#usePlayWS}} - 2.10.1 + 2.10.3 {{#play24}} 2.6.6 2.4.11 {{/play24}} {{#play25}} - 2.10.1 + 2.10.3 2.5.15 {{/play25}} {{#play26}} - 2.10.1 + 2.10.3 2.6.7 {{/play26}} 0.2.1 diff --git a/libraries/vertx/build.gradle.mustache b/libraries/vertx/build.gradle.mustache index 53bc7b9a8e5..02760c59149 100644 --- a/libraries/vertx/build.gradle.mustache +++ b/libraries/vertx/build.gradle.mustache @@ -28,8 +28,8 @@ task execute(type:JavaExec) { ext { swagger_annotations_version = "1.5.21" - jackson_version = "2.10.1" - jackson_databind_version = "2.10.1" + jackson_version = "2.10.3" + jackson_databind_version = "2.10.3" vertx_version = "3.4.2" junit_version = "4.13" } diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache index 325c2b81c7b..b3539c9fd77 100644 --- a/libraries/vertx/pom.mustache +++ b/libraries/vertx/pom.mustache @@ -292,8 +292,8 @@ UTF-8 3.4.2 1.5.22 - 2.10.1 - 2.10.1 + 2.10.3 + 2.10.3 0.2.1 4.13 diff --git a/libraries/webclient/pom.mustache b/libraries/webclient/pom.mustache index 39cd7729c35..138270ea3f9 100644 --- a/libraries/webclient/pom.mustache +++ b/libraries/webclient/pom.mustache @@ -143,8 +143,8 @@ UTF-8 1.5.22 5.0.16.RELEASE - 2.10.1 - 2.10.1 + 2.10.3 + 2.10.3 0.2.1 4.13 3.1.8.RELEASE diff --git a/pom.mustache b/pom.mustache index 351f5c478fe..dd95ac7554e 100644 --- a/pom.mustache +++ b/pom.mustache @@ -292,7 +292,7 @@ com.github.joschi.jackson jackson-datatype-threetenbp - ${jackson-version} + ${jackson-threetenbp-version} {{/threetenbp}} {{^java8}} @@ -357,7 +357,10 @@ 2.5 3.6 {{/supportJava6}} - {{^threetenbp}}2.7.5{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} + 2.10.3 + {{#threetenbp}} + 2.9.10 + {{/threetenbp}} 1.0.0 4.13 From 7a7ebb2a588cc3eda1988c414872414557f8098e Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Tue, 10 Mar 2020 10:18:08 -0700 Subject: [PATCH 206/370] [Java] Fix exception when OAuth2 token URL is a relative URL (#5535) * Add support for case when OAuth2 token URL is a relative URL * Add support for case when OAuth2 token URL is a relative URL * run scripts under bin --- libraries/okhttp-gson/ApiClient.mustache | 23 ++++++++++++++++++- .../okhttp-gson/auth/RetryingOAuth.mustache | 7 ++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index 1f0e606d873..1c068bcc58d 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -30,6 +30,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.lang.reflect.Type; +import java.net.URI; import java.net.URLConnection; import java.net.URLEncoder; import java.security.GeneralSecurityException; @@ -122,10 +123,30 @@ public class ApiClient { * Constructor for ApiClient to support access token retry on 401/403 configured with client ID, secret, and additional parameters */ public ApiClient(String clientId, String clientSecret, Map parameters) { + this(null, clientId, clientSecret, parameters); + } + + /* + * Constructor for ApiClient to support access token retry on 401/403 configured with base path, client ID, secret, and additional parameters + */ + public ApiClient(String basePath, String clientId, String clientSecret, Map parameters) { init(); + if (basePath != null) { + this.basePath = basePath; + } {{#hasOAuthMethods}} - RetryingOAuth retryingOAuth = new RetryingOAuth("{{tokenUrl}}", clientId, OAuthFlow.{{flow}}, clientSecret, parameters); + String tokenUrl = "{{tokenUrl}}"; + if (!"".equals(tokenUrl) && !URI.create(tokenUrl).isAbsolute()) { + URI uri = URI.create(getBasePath()); + tokenUrl = uri.getScheme() + ":" + + (uri.getAuthority() != null ? "//" + uri.getAuthority() : "") + + tokenUrl; + if (!URI.create(tokenUrl).isAbsolute()) { + throw new IllegalArgumentException("OAuth2 token URL must be an absolute URL"); + } + } + RetryingOAuth retryingOAuth = new RetryingOAuth(tokenUrl, clientId, OAuthFlow.{{flow}}, clientSecret, parameters); authentications.put( "{{name}}", retryingOAuth diff --git a/libraries/okhttp-gson/auth/RetryingOAuth.mustache b/libraries/okhttp-gson/auth/RetryingOAuth.mustache index 94f1d6afcf9..3ddacedb70e 100644 --- a/libraries/okhttp-gson/auth/RetryingOAuth.mustache +++ b/libraries/okhttp-gson/auth/RetryingOAuth.mustache @@ -36,6 +36,13 @@ public class RetryingOAuth extends OAuth implements Interceptor { this(new OkHttpClient(), tokenRequestBuilder); } + /** + @param tokenUrl The token URL to be used for this OAuth2 flow. + Applicable to the following OAuth2 flows: "password", "clientCredentials" and "authorizationCode". + The value must be an absolute URL. + @param clientId The OAuth2 client ID for the "clientCredentials" flow. + @param clientSecret The OAuth2 client secret for the "clientCredentials" flow. + */ public RetryingOAuth( String tokenUrl, String clientId, From 96fbd54136199c22c93f125a60404d2d9febf77d Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Tue, 10 Mar 2020 10:22:56 -0700 Subject: [PATCH 207/370] [Java] fix runtime exception when there are multiple auth methods (#5530) * fix runtime exception when there are multiple auth methods * Refactor a bit so that it does not cause conflict with relative url token branch --- libraries/okhttp-gson/ApiClient.mustache | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index 1c068bcc58d..3969c08d391 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -153,6 +153,10 @@ public class ApiClient { ); initHttpClient(Collections.singletonList(retryingOAuth)); {{/hasOAuthMethods}} + // Setup authentications (key: authentication name, value: authentication).{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{/authMethods}} // Prevent the authentications from being modified. authentications = Collections.unmodifiableMap(authentications); From f85758f3eefe8039ffb19d2e7bba2a6aa052fc00 Mon Sep 17 00:00:00 2001 From: Clemens Angermann Date: Tue, 17 Mar 2020 09:59:36 +0100 Subject: [PATCH 208/370] Adding Response Interceptor (#5500) * added Response interceptor for native clients * added Response interceptor for native clients --- libraries/native/ApiClient.mustache | 29 ++++++++++++++++++++++++++++- libraries/native/api.mustache | 7 ++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/libraries/native/ApiClient.mustache b/libraries/native/ApiClient.mustache index 6bcad4a2f3f..fb83d919b93 100644 --- a/libraries/native/ApiClient.mustache +++ b/libraries/native/ApiClient.mustache @@ -8,10 +8,12 @@ import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.openapitools.jackson.nullable.JsonNullableModule; +import java.io.InputStream; import java.net.URI; import java.net.URLEncoder; import java.net.http.HttpClient; import java.net.http.HttpRequest; +import java.net.http.HttpResponse; import java.nio.charset.Charset; import java.time.Duration; import java.util.Collection; @@ -46,6 +48,7 @@ public class ApiClient { private int port; private String basePath; private Consumer interceptor; + private Consumer> responseInterceptor; private Duration readTimeout; private static String valueToString(Object value) { @@ -161,6 +164,7 @@ public class ApiClient { basePath = baseURI.getRawPath(); interceptor = null; readTimeout = null; + responseInterceptor = null; } /** @@ -292,6 +296,29 @@ public class ApiClient { return interceptor; } + /** + * Set a custom response interceptor. + * + *

This is useful for logging, monitoring or extraction of header variables

+ * + * @param interceptor A function invoked before creating each request. A value + * of null resets the interceptor to a no-op. + * @return This object. + */ + public ApiClient setResponseInterceptor(Consumer> interceptor) { + this.responseInterceptor = interceptor; + return this; + } + + /** + * Get the custom response interceptor. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer> getResponseInterceptor() { + return responseInterceptor; + } + /** * Set the read timeout for the http client. * @@ -307,7 +334,7 @@ public class ApiClient { this.readTimeout = readTimeout; return this; } - + /** * Get the read timeout that was set. * diff --git a/libraries/native/api.mustache b/libraries/native/api.mustache index 8c545a015f4..4c4848ca480 100644 --- a/libraries/native/api.mustache +++ b/libraries/native/api.mustache @@ -36,7 +36,8 @@ public class {{classname}} { private final String memberVarBaseUri; private final Consumer memberVarInterceptor; private final Duration memberVarReadTimeout; - + private final Consumer> memberVarResponseInterceptor; + public {{classname}}() { this(new ApiClient()); } @@ -47,6 +48,7 @@ public class {{classname}} { memberVarBaseUri = apiClient.getBaseUri(); memberVarInterceptor = apiClient.getRequestInterceptor(); memberVarReadTimeout = apiClient.getReadTimeout(); + memberVarResponseInterceptor = apiClient.getResponseInterceptor(); } {{#operation}} @@ -138,6 +140,9 @@ public class {{classname}} { HttpResponse localVarResponse = memberVarHttpClient.send( localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } if (localVarResponse.statusCode()/ 100 != 2) { throw new ApiException(localVarResponse.statusCode(), "{{operationId}} call received non-success response", From af07c0b3547b1a74d7d19bb505c0853888ff2a3d Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Thu, 26 Mar 2020 01:47:51 -0700 Subject: [PATCH 209/370] [Java] Update version of maven-surefire-plugin (#5509) * use more recent version of maven-surefire-plugin * use more recent version of maven-surefire-plugin * higher debug level for troubleshooting ci issue * temporarily increase debug log to help troubleshoot * Use local instance of pet store service for unit test purpose * Add more logging to troubleshoot unit test failures * Add more logging to troubleshoot unit test failures * Add more logging to troubleshoot unit test failures * Add more logging to troubleshoot unit test failures * Add more logging to troubleshoot unit test failures * use random ID for Java unit test instead of fixed id * add code comments and specify URL for java unit test * reenable quiet argument * fix java unit test issues * fix java unit test issues * Revert "fix java unit test issues" This reverts commit e8508416ff0f2aeb568e3f916b013dc967390f74. * fix java unit test issues --- libraries/okhttp-gson/pom.mustache | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index 6f04c25e1c9..c11b4ab127d 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -63,7 +63,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.12 + 3.0.0-M4 @@ -73,7 +73,7 @@ -Xms512m -Xmx1500m methods - pertest + 10 From f60e472264e880f392e45d9270d3b0b88d2be2c8 Mon Sep 17 00:00:00 2001 From: Nicholas Muesch Date: Tue, 7 Apr 2020 04:07:08 -0400 Subject: [PATCH 210/370] Add openapi.yaml file to Java clients (#5765) * Add openapi.yaml file to Java client * Move supporting template file to Java root * Update petstore clients --- openapi.mustache | 1 + 1 file changed, 1 insertion(+) create mode 100644 openapi.mustache diff --git a/openapi.mustache b/openapi.mustache new file mode 100644 index 00000000000..34fbb53f331 --- /dev/null +++ b/openapi.mustache @@ -0,0 +1 @@ +{{{openapi-yaml}}} From 2ca79c861ac4ec7bed736a0bea31359067bc2f8d Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Fri, 10 Apr 2020 09:40:27 -0700 Subject: [PATCH 211/370] [Java-client] Add maven-compiler-plugin in pom.xml and enable linter checks by default (#5866) * Add maven-compiler-plugin plugin in Java pom.xml and enable linter checks by default * Add maven-compiler-plugin plugin in Java pom.xml and enable linter checks by default --- JSON.mustache | 2 +- libraries/okhttp-gson/pom.mustache | 13 +++++++++++++ pom.mustache | 14 ++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/JSON.mustache b/JSON.mustache index b951c3c555d..723ea79f16e 100644 --- a/JSON.mustache +++ b/JSON.mustache @@ -69,7 +69,7 @@ public class JSON { .registerTypeSelector({{classname}}.class, new TypeSelector() { @Override public Class getClassForElement(JsonElement readElement) { - Map classByDiscriminatorValue = new HashMap(); + Map classByDiscriminatorValue = new HashMap(); {{#mappedModels}} classByDiscriminatorValue.put("{{mappingName}}".toUpperCase(Locale.ROOT), {{modelName}}.class); {{/mappedModels}} diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index c11b4ab127d..788d416e048 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -40,6 +40,19 @@ + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + true + 128m + 512m + + -Xlint:all + + + org.apache.maven.plugins maven-enforcer-plugin diff --git a/pom.mustache b/pom.mustache index dd95ac7554e..28dfab1f257 100644 --- a/pom.mustache +++ b/pom.mustache @@ -40,6 +40,20 @@ + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + true + 128m + 512m + + -Xlint:all + + + + org.apache.maven.plugins maven-enforcer-plugin From bb6ba968e3e032251c1ea44b03771a6091724cf1 Mon Sep 17 00:00:00 2001 From: Jochen Schalanda Date: Sun, 12 Apr 2020 17:36:18 +0200 Subject: [PATCH 212/370] Update generated build files for REST Assured (#5873) * REST Assured 4.3.0 * Jackson 2.10.3 * Gson 2.8.6, GSON-Fire 1.8.4 * Okio 1.17.5 * Joda-Time 2.10.5 * ThreeTenBP 1.4.3 * Added missing dependencies for Bean Validation * Added missing dependencies for `@Generated` annotation * Refresh REST Assured sample project --- libraries/rest-assured/build.gradle.mustache | 22 ++++-- libraries/rest-assured/build.sbt.mustache | 24 +++--- libraries/rest-assured/pom.mustache | 83 ++++++++++++++------ 3 files changed, 86 insertions(+), 43 deletions(-) diff --git a/libraries/rest-assured/build.gradle.mustache b/libraries/rest-assured/build.gradle.mustache index b04e53f1e96..640ad1cd18c 100644 --- a/libraries/rest-assured/build.gradle.mustache +++ b/libraries/rest-assured/build.gradle.mustache @@ -96,24 +96,24 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.21" - rest_assured_version = "4.0.0" + rest_assured_version = "4.3.0" junit_version = "4.13" {{#jackson}} - jackson_version = "2.10.1" - jackson_databind_version = "2.9.10" + jackson_version = "2.10.3" + jackson_databind_version = "2.10.3" jackson_databind_nullable_version = 0.2.1 {{/jackson}} {{#gson}} - gson_version = "2.8.5" - gson_fire_version = "1.8.3" + gson_version = "2.8.6" + gson_fire_version = "1.8.4" {{/gson}} {{#joda}} - jodatime_version = "2.9.9" + jodatime_version = "2.10.5" {{/joda}} {{#threetenbp}} - threetenbp_version = "1.4.0" + threetenbp_version = "1.4.3" {{/threetenbp}} - okio_version = "1.13.0" + okio_version = "1.17.5" } dependencies { @@ -138,5 +138,11 @@ dependencies { compile "org.threeten:threetenbp:$threetenbp_version" {{/threetenbp}} compile "com.squareup.okio:okio:$okio_version" +{{#useBeanValidation}} + compile "javax.validation:validation-api:2.0.1.Final" +{{/useBeanValidation}} +{{#performBeanValidation}} + compile "org.hibernate:hibernate-validator:6.0.19.Final" +{{/performBeanValidation}} testCompile "junit:junit:$junit_version" } diff --git a/libraries/rest-assured/build.sbt.mustache b/libraries/rest-assured/build.sbt.mustache index 71f2eaeeba2..77f8af4f436 100644 --- a/libraries/rest-assured/build.sbt.mustache +++ b/libraries/rest-assured/build.sbt.mustache @@ -10,23 +10,29 @@ lazy val root = (project in file(".")). resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( "io.swagger" % "swagger-annotations" % "1.5.21", - "io.rest-assured" % "scala-support" % "4.0.0", + "io.rest-assured" % "scala-support" % "4.3.0", {{#jackson}} - "com.fasterxml.jackson.core" % "jackson-core" % "2.9.9" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.9" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", {{/jackson}} {{#gson}} - "com.google.code.gson" % "gson" % "2.8.5", - "io.gsonfire" % "gson-fire" % "1.8.3" % "compile", + "com.google.code.gson" % "gson" % "2.8.6", + "io.gsonfire" % "gson-fire" % "1.8.4" % "compile", {{/gson}} {{#joda}} - "joda-time" % "joda-time" % "2.9.9" % "compile", + "joda-time" % "joda-time" % "2.10.5" % "compile", {{/joda}} {{#threetenbp}} - "org.threeten" % "threetenbp" % "1.4.0" % "compile", + "org.threeten" % "threetenbp" % "1.4.3" % "compile", {{/threetenbp}} - "com.squareup.okio" % "okio" % "1.13.0" % "compile", + "com.squareup.okio" % "okio" % "1.17.5" % "compile", +{{#useBeanValidation}} + "javax.validation" % "validation-api" % "2.0.1.Final" % "compile", +{{/useBeanValidation}} +{{#performBeanValidation}} + "org.hibernate" % "hibernate-validator" "6.0.19.Final" % "compile", +{{/performBeanValidation}} "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) diff --git a/libraries/rest-assured/pom.mustache b/libraries/rest-assured/pom.mustache index da538caa9b0..2e68695d431 100644 --- a/libraries/rest-assured/pom.mustache +++ b/libraries/rest-assured/pom.mustache @@ -43,7 +43,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.0.0-M1 + 3.0.0-M3 enforce-maven @@ -53,7 +53,7 @@ - 2.2.0 + 3.0.5 @@ -63,7 +63,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.12 + 2.22.2 @@ -71,9 +71,8 @@ conf/log4j.properties - -Xms512m -Xmx1500m - methods - pertest + false + 1C @@ -111,6 +110,7 @@ org.codehaus.mojo build-helper-maven-plugin + 3.1.0 add_sources @@ -141,7 +141,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.6.1 + 3.8.1 1.8 1.8 @@ -150,7 +150,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.1.1 + 3.2.0 none @@ -166,7 +166,7 @@ org.apache.maven.plugins maven-source-plugin - 2.2.1 + 3.2.0 attach-sources @@ -187,7 +187,7 @@ org.apache.maven.plugins maven-gpg-plugin - 1.5 + 1.6 sign-artifacts @@ -203,6 +203,20 @@ + {{#jackson}} + + + + com.fasterxml.jackson + jackson-bom + ${jackson-version} + pom + import + + + + {{/jackson}} + io.swagger @@ -215,6 +229,14 @@ jsr305 3.0.2 + {{^hideGenerationTimestamp}} + + javax.annotation + javax.annotation-api + 1.3.2 + provided + + {{/hideGenerationTimestamp}} io.rest-assured rest-assured @@ -253,17 +275,14 @@ com.fasterxml.jackson.core jackson-core - ${jackson-version} com.fasterxml.jackson.core jackson-annotations - ${jackson-version} com.fasterxml.jackson.core jackson-databind - ${jackson-databind-version} org.openapitools @@ -274,21 +293,18 @@ com.fasterxml.jackson.dataformat jackson-dataformat-xml - ${jackson-version} {{/withXml}} {{#joda}} com.fasterxml.jackson.datatype jackson-datatype-joda - ${jackson-version} {{/joda}} {{#java8}} com.fasterxml.jackson.datatype jackson-datatype-jsr310 - ${jackson-version} {{/java8}} {{#threetenbp}} @@ -304,6 +320,23 @@ okio ${okio-version} + {{#useBeanValidation}} + + + javax.validation + validation-api + 2.0.1.Final + provided + + {{/useBeanValidation}} + {{#performBeanValidation}} + + + org.hibernate + hibernate-validator + 6.0.19.Final + + {{/performBeanValidation}} junit @@ -315,25 +348,23 @@ UTF-8 1.5.21 - 4.0.0 - 2.8.5 - 1.8.3 - 1.0.0 + 4.3.0 + 2.8.6 + 1.8.4 {{#joda}} - 2.9.9 + 2.10.5 {{/joda}} {{#threetenbp}} - 1.4.0 + 1.4.3 {{/threetenbp}} {{#jackson}} - 2.10.1 - 2.9.10 + 2.10.3 0.2.1 {{#threetenbp}} - 2.9.10 + 2.10.0 {{/threetenbp}} {{/jackson}} - 1.13.0 + 1.17.5 4.13 From 81920b1dc093ff01d17f1512fb2ed4df824aeb02 Mon Sep 17 00:00:00 2001 From: Chr1st0ph Date: Mon, 13 Apr 2020 03:59:35 +0200 Subject: [PATCH 213/370] [Java][Feign] Bug fix in @Param annotation (#5250) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * FIX-5249 fix @Param annotation for Feign-client code generation Use paramName instead of baseName in order to make mapping in @Headers section fit the param-value. * update samples * FIX-5249 fix @Param annotation for Feign-client code generation Use paramName instead of baseName in order to make mapping in @Headers section fit the param-value. Co-authored-by: Christoph Preißner Co-authored-by: William Cheng --- libraries/feign/api.mustache | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/feign/api.mustache b/libraries/feign/api.mustache index 238079ca27c..cff48fcd2e4 100644 --- a/libraries/feign/api.mustache +++ b/libraries/feign/api.mustache @@ -42,7 +42,7 @@ public interface {{classname}} extends ApiClient.Api { "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{#hasMore}}, {{/hasMore}}{{/headerParams}} }) - {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isBodyParam}}{{^legacyDates}}@Param("{{baseName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{baseName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{baseName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); {{#hasQueryParams}} /** @@ -80,7 +80,7 @@ public interface {{classname}} extends ApiClient.Api { "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{#hasMore}}, {{/hasMore}}{{/headerParams}} }) - {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isQueryParam}}{{^isBodyParam}}{{^legacyDates}}@Param("{{baseName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{baseName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}, {{/isQueryParam}}{{/allParams}}@QueryMap(encoded=true) Map queryParams); + {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isQueryParam}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{baseName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}, {{/isQueryParam}}{{/allParams}}@QueryMap(encoded=true) Map queryParams); /** * A convenience class for generating query parameters for the From 27d0b13f17bc7df585e27cd5b68b8de1937303dc Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Sun, 12 Apr 2020 22:56:20 -0700 Subject: [PATCH 214/370] [Java] Increase java compiler stack size to handle large files (#5901) * increase java compiler stack size to handle large files * increase java compiler stack size to handle large files --- libraries/okhttp-gson/pom.mustache | 1 + pom.mustache | 1 + 2 files changed, 2 insertions(+) diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index 788d416e048..db9e309ce6a 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -50,6 +50,7 @@ 512m -Xlint:all + -J-Xss4m diff --git a/pom.mustache b/pom.mustache index 28dfab1f257..e9cbf546b6d 100644 --- a/pom.mustache +++ b/pom.mustache @@ -50,6 +50,7 @@ 512m -Xlint:all + -J-Xss4m From 84e941602b6dfa904327127ccd3d57123e5e9c2f Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Mon, 13 Apr 2020 03:54:00 -0700 Subject: [PATCH 215/370] [Java] Discriminator lookup should not be case insensitive by default (#5894) * Add 'discriminatorCaseSensitive' property * Discriminator value lookup should not be case insensitive * fix typo * run scripts * execute ./bin/utils/export_docs_generators.sh * fix discriminator mapping, add code comments --- JSON.mustache | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/JSON.mustache b/JSON.mustache index 723ea79f16e..590ba386ea2 100644 --- a/JSON.mustache +++ b/JSON.mustache @@ -71,9 +71,9 @@ public class JSON { public Class getClassForElement(JsonElement readElement) { Map classByDiscriminatorValue = new HashMap(); {{#mappedModels}} - classByDiscriminatorValue.put("{{mappingName}}".toUpperCase(Locale.ROOT), {{modelName}}.class); + classByDiscriminatorValue.put("{{mappingName}}"{{^discriminatorCaseSensitive}}.toUpperCase(Locale.ROOT){{/discriminatorCaseSensitive}}, {{modelName}}.class); {{/mappedModels}} - classByDiscriminatorValue.put("{{classname}}".toUpperCase(Locale.ROOT), {{classname}}.class); + classByDiscriminatorValue.put("{{name}}"{{^discriminatorCaseSensitive}}.toUpperCase(Locale.ROOT){{/discriminatorCaseSensitive}}, {{classname}}.class); return getClassByDiscriminator(classByDiscriminatorValue, getDiscriminatorValue(readElement, "{{{propertyBaseName}}}")); } @@ -97,8 +97,15 @@ public class JSON { return element.getAsString(); } + /** + * Returns the Java class that implements the OpenAPI schema for the specified discriminator value. + * + * @param classByDiscriminatorValue The map of discriminator values to Java classes. + * @param discriminatorValue The value of the OpenAPI discriminator in the input data. + * @return The Java class that implements the OpenAPI schema + */ private static Class getClassByDiscriminator(Map classByDiscriminatorValue, String discriminatorValue) { - Class clazz = (Class) classByDiscriminatorValue.get(discriminatorValue.toUpperCase(Locale.ROOT)); + Class clazz = (Class) classByDiscriminatorValue.get(discriminatorValue{{^discriminatorCaseSensitive}}.toUpperCase(Locale.ROOT){{/discriminatorCaseSensitive}}); if (null == clazz) { throw new IllegalArgumentException("cannot determine model class of name: <" + discriminatorValue + ">"); } From 3cfd564ca327133ea44f6700aacc6b7a2b15ee0d Mon Sep 17 00:00:00 2001 From: Erikmolin Date: Tue, 14 Apr 2020 05:26:50 +0200 Subject: [PATCH 216/370] [Java] Fix inclusive max validation (#5908) Co-authored-by: erikmolin --- beanValidationCore.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beanValidationCore.mustache b/beanValidationCore.mustache index d107c037b9a..ae26b2739f1 100644 --- a/beanValidationCore.mustache +++ b/beanValidationCore.mustache @@ -17,4 +17,4 @@ isInteger set isLong set }}{{#isLong}}{{#minimum}} @Min({{minimum}}L){{/minimum}}{{#maximum}} @Max({{maximum}}L){{/maximum}}{{/isLong}}{{! Not Integer, not Long => we have a decimal value! -}}{{^isInteger}}{{^isLong}}{{#minimum}} @DecimalMin({{#exclusiveMinimum}}value={{/exclusiveMinimum}}"{{minimum}}"{{#exclusiveMinimum}},inclusive=false{{/exclusiveMinimum}}){{/minimum}}{{#maximum}} @DecimalMax({{#exclusiveMinimum}}value={{/exclusiveMinimum}}"{{maximum}}"{{#exclusiveMinimum}},inclusive=false{{/exclusiveMinimum}}){{/maximum}}{{/isLong}}{{/isInteger}} \ No newline at end of file +}}{{^isInteger}}{{^isLong}}{{#minimum}} @DecimalMin({{#exclusiveMinimum}}value={{/exclusiveMinimum}}"{{minimum}}"{{#exclusiveMinimum}},inclusive=false{{/exclusiveMinimum}}){{/minimum}}{{#maximum}} @DecimalMax({{#exclusiveMaximum}}value={{/exclusiveMaximum}}"{{maximum}}"{{#exclusiveMaximum}},inclusive=false{{/exclusiveMaximum}}){{/maximum}}{{/isLong}}{{/isInteger}} \ No newline at end of file From 3f84fb0e6a6f609cde4e5db6fc8855205d5f9c3a Mon Sep 17 00:00:00 2001 From: William Cheng Date: Tue, 14 Apr 2020 20:34:16 +0800 Subject: [PATCH 217/370] update dependency for java client (#5926) --- libraries/okhttp-gson/build.gradle.mustache | 16 ++++++++-------- libraries/okhttp-gson/build.sbt.mustache | 15 ++++++++------- libraries/okhttp-gson/pom.mustache | 17 ++++++++--------- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/libraries/okhttp-gson/build.gradle.mustache b/libraries/okhttp-gson/build.gradle.mustache index 304b00a445a..91913276775 100644 --- a/libraries/okhttp-gson/build.gradle.mustache +++ b/libraries/okhttp-gson/build.gradle.mustache @@ -68,7 +68,7 @@ if(hasProperty('target') && target == 'android') { } dependencies { - provided 'javax.annotation:jsr250-api:1.0' + provided 'javax.annotation:javax.annotation-api:1.3.2' } } @@ -126,21 +126,21 @@ if(hasProperty('target') && target == 'android') { } dependencies { - compile 'io.swagger:swagger-annotations:1.5.22' + compile 'io.swagger:swagger-annotations:1.5.24' compile "com.google.code.findbugs:jsr305:3.0.2" - compile 'com.squareup.okhttp3:okhttp:3.14.2' - compile 'com.squareup.okhttp3:logging-interceptor:3.14.2' - compile 'com.google.code.gson:gson:2.8.5' - compile 'io.gsonfire:gson-fire:1.8.3' + compile 'com.squareup.okhttp3:okhttp:3.14.7' + compile 'com.squareup.okhttp3:logging-interceptor:3.14.7' + compile 'com.google.code.gson:gson:2.8.6' + compile 'io.gsonfire:gson-fire:1.8.4' {{#hasOAuthMethods}} compile group: 'org.apache.oltu.oauth2', name: 'org.apache.oltu.oauth2.client', version: '1.0.1' {{/hasOAuthMethods}} - compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.9' + compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.10' {{#joda}} compile 'joda-time:joda-time:2.9.9' {{/joda}} {{#threetenbp}} - compile 'org.threeten:threetenbp:1.4.0' + compile 'org.threeten:threetenbp:1.4.3' {{/threetenbp}} testCompile 'junit:junit:4.13' } diff --git a/libraries/okhttp-gson/build.sbt.mustache b/libraries/okhttp-gson/build.sbt.mustache index 43907462202..7c137589e37 100644 --- a/libraries/okhttp-gson/build.sbt.mustache +++ b/libraries/okhttp-gson/build.sbt.mustache @@ -9,11 +9,11 @@ lazy val root = (project in file(".")). publishArtifact in (Compile, packageDoc) := false, resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( - "io.swagger" % "swagger-annotations" % "1.5.22", - "com.squareup.okhttp3" % "okhttp" % "3.14.2", - "com.squareup.okhttp3" % "logging-interceptor" % "3.14.2", - "com.google.code.gson" % "gson" % "2.8.5", - "org.apache.commons" % "commons-lang3" % "3.9", + "io.swagger" % "swagger-annotations" % "1.5.24", + "com.squareup.okhttp3" % "okhttp" % "3.14.7", + "com.squareup.okhttp3" % "logging-interceptor" % "3.14.7", + "com.google.code.gson" % "gson" % "2.8.6", + "org.apache.commons" % "commons-lang3" % "3.10", {{#hasOAuthMethods}} "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1", {{/hasOAuthMethods}} @@ -21,10 +21,11 @@ lazy val root = (project in file(".")). "joda-time" % "joda-time" % "2.9.9" % "compile", {{/joda}} {{#threetenbp}} - "org.threeten" % "threetenbp" % "1.4.0" % "compile", + "org.threeten" % "threetenbp" % "1.4.3" % "compile", {{/threetenbp}} "io.gsonfire" % "gson-fire" % "1.8.3" % "compile", - "javax.annotation" % "jsr250-api" % "1.0" % "compile", + "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", + "com.google.code.findbugs" % "jsr305" % "3.0.2" % "compile", "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index db9e309ce6a..b6d67f28350 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -307,7 +307,7 @@ {{/parcelableModel}} javax.annotation - jsr250-api + javax.annotation-api ${javax-annotation-version} @@ -322,19 +322,18 @@ {{#supportJava6}}1.6{{/supportJava6}}{{^supportJava6}}{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}{{/supportJava6}} ${java.version} ${java.version} - 1.8.3 - 1.5.22 - 3.14.2 - 2.8.5 - 3.9 + 1.8.4 + 1.5.24 + 3.14.7 + 2.8.6 + 3.10 {{#joda}} 2.9.9 {{/joda}} {{#threetenbp}} - 1.4.0 + 1.4.3 {{/threetenbp}} - 1.0.0 - 1.0 + 1.3.2 4.13 UTF-8
From 1487799e26287a5c7e3de819aa32145e71b83a93 Mon Sep 17 00:00:00 2001 From: Jochen Schalanda Date: Wed, 22 Apr 2020 05:19:17 +0200 Subject: [PATCH 218/370] [Java][Client] Fix Gradle and SBT builds for REST Assured generator (#5990) * Fix Gradle and SBT builds for Java REST Assured generator * Add missing jackson-databind-nullable dependency to SBT build * Update rest-assured sample * Add sample for Java client with REST Assured and Jackson * Add new REST Assured sample as Maven sub-module --- libraries/rest-assured/build.gradle.mustache | 19 ++++++++++++++-- libraries/rest-assured/build.sbt.mustache | 23 ++++++++++++++++---- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/libraries/rest-assured/build.gradle.mustache b/libraries/rest-assured/build.gradle.mustache index 640ad1cd18c..0868a2aa7c0 100644 --- a/libraries/rest-assured/build.gradle.mustache +++ b/libraries/rest-assured/build.gradle.mustache @@ -101,7 +101,10 @@ ext { {{#jackson}} jackson_version = "2.10.3" jackson_databind_version = "2.10.3" - jackson_databind_nullable_version = 0.2.1 + jackson_databind_nullable_version = "0.2.1" + {{#threetenbp}} + jackson_threetenbp_version = "2.10.0" + {{/threetenbp}} {{/jackson}} {{#gson}} gson_version = "2.8.6" @@ -119,13 +122,25 @@ ext { dependencies { compile "io.swagger:swagger-annotations:$swagger_annotations_version" compile "com.google.code.findbugs:jsr305:3.0.2" - compile "io.rest-assured:scala-support:$rest_assured_version" + compile "io.rest-assured:rest-assured:$rest_assured_version" {{#jackson}} compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{#withXml}} + compile "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jackson_version" + {{/withXml}} + {{#joda}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + {{/joda}} + {{#java8}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{/java8}} + {{#threetenbp}} + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threetenbp_version" + {{/threetenbp}} {{/jackson}} {{#gson}} compile "io.gsonfire:gson-fire:$gson_fire_version" diff --git a/libraries/rest-assured/build.sbt.mustache b/libraries/rest-assured/build.sbt.mustache index 77f8af4f436..955f515fc70 100644 --- a/libraries/rest-assured/build.sbt.mustache +++ b/libraries/rest-assured/build.sbt.mustache @@ -10,11 +10,26 @@ lazy val root = (project in file(".")). resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( "io.swagger" % "swagger-annotations" % "1.5.21", + "io.rest-assured" % "rest-assured" % "4.3.0", "io.rest-assured" % "scala-support" % "4.3.0", + "com.google.code.findbugs" % "jsr305" % "3.0.2", {{#jackson}} - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3", + "org.openapitools" % "jackson-databind-nullable" % "0.2.1", + {{#withXml}} + "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.10.3", + {{/withXml}} + {{#joda}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.10.3", + {{/joda}} + {{#java8}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.10.3", + {{/java8}} + {{#threetenbp}} + "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.10.0", + {{/threetenbp}} {{/jackson}} {{#gson}} "com.google.code.gson" % "gson" % "2.8.6", @@ -31,7 +46,7 @@ lazy val root = (project in file(".")). "javax.validation" % "validation-api" % "2.0.1.Final" % "compile", {{/useBeanValidation}} {{#performBeanValidation}} - "org.hibernate" % "hibernate-validator" "6.0.19.Final" % "compile", + "org.hibernate" % "hibernate-validator" % "6.0.19.Final" % "compile", {{/performBeanValidation}} "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" From fbdb395591862cae629d0f839f09aed52694ccec Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 22 Apr 2020 11:47:08 +0800 Subject: [PATCH 219/370] Sync master to 5.0.x (#5968) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Change the Model template (#5222) * Add a link to Xero blog post (#5426) * Removal of Encoding in the Query-Params in order to prevent double Encoding. (#5255) This way letting WebClient do its Job in encoding the URL. * update java webclient sample * [kotlin][client] Add Jackson as serialization library (#5236) * [kotlin][client] Add Jackson as serialization library * [kotlin][client] Add kotlin-client-jackson.sh to kotlin-client-all.sh * update kotlin client samples * update doc Co-authored-by: William Cheng * include kotlin jackson in CI tests (#5438) * [Ruby] Add error output (#5428) * Add error output to the log so that we can make sure why the error occurred * Fix forbidden method invocation using default charsets * Update usage.md (#5443) * fix NPE for enum (#5445) * [Java][WebClient] better code format (#5433) * better code format for java webclient * prefix local varaible with localVar * fix issue with online service (#5461) * Support for additionalProperties in the C generator "Client: C" solves #5395 (#5440) * Support for additionalProperties in the C generator. * Support for additionalProperties in the C generator. * [docs] Enable Algolia search (#5472) * Fix #5420 add headers from configuration object (#5422) * Fix #5420 add headers from configuration object * Add baseOptions undefined checking #5420 * Update the samples and replace array to object #5420 * Update sample * [typescript] Clean up modelPropertyNaming across generators (#5427) * [typescript] Clean up modelPropertyNaming across generators Fixes https://github.com/OpenAPITools/openapi-generator/issues/2976 Generators without runtime models conversion use "original" property naming by default. It's still possible to change it via cli options Generators with runtime conversion keep using "camelCase" * Refactoring: use enum instead of string for modelPropertyNaming * Restore the original camelCase for var names, decouple it from property names * Swap toParamName and toVarName logic (looks like I've mistaken them) * Regenerate docs * Remove a no longer used private method * Added support for msvc builds in cpp-qt5-client generator (#5468) * Added support for msvc builds Moved GCC-specific compile flags to non msvc builds, and added equivalent flags for msvc. * CMakeLists condition cleanup * [all] Move feature set setter (#5460) When I originally implemented the feature set code, I added the getter/setter on DefaultCodegen and CodegenConfig as well as on GeneratorMetadata. GeneratorMetadata also includes the library variation features. When I went to add library-specific features, I realized the discrepancy. This removes the public setter from DefaultCodegen/CodegenConfig, and adds a protected modifyFeatureSet which accepts a lambda and hides the builder logic away in the method. This will be a breaking change for anyone who's created a custom generator in 4.2.3, so the impact is very limited. * [Swift5] small improvements to Objc compatibility (#5410) * [swift] make some small improvements * [swift][client] revert model to use allVars * PostProcessModelProperty with allVars * PostProcessModelProperty with vars * [swift] improve objc interoperability * [swift] fix swift4 for CI to pass * [swift] improve objc interoperability * [swift] improve objc interoperability * Swift - try to fix build * [swift] remove pods from git * [scala] [template] scala sttp client (#5429) * scala-sttp-client template * invoker for sttp fixed and tests added * clean up pet api test from redunant comments * docs updated * fix artefact name, model comments and redunant generic * code optimization * cross scala versions 2.11 2.12 2.13 * date serializers extracted and joda enabled as default * basic and bearer authorization added, apikey in query supported * [Ruby] Fix obsolete configuration of Rubocop and Rubocop's warns (#5417) (#5474) * fix obsolute configuration in generated .rubocop.yml * fix style of `expect` with block in generated ruby client's test code * update sample of ruby client * [scala] strip model class name for all scala generators (#5439) * stripped parameter enabled for all scala based generators * scala samples updated * docs generators updated * fix scalatra. regenerated by openapi3 script. manually removed enum default value from scalatra example due bug in schema extraction * [Scala][sttp] various improvements (#5475) * various improvements to scala sttp * update ScalaSttpClientCodegen.java * add windows batch file * test scala sttp in jdk8 * fix tempalte directory * Use the dataType if the baseType is not set (#5372) * Use the dataType if the baseType is not set * add tests for passing enum as parameter * updated requirements file in samples * Update spec to explicitly name objects and prevent `inline_object` * use the correct scripts to generate samples (`bin/openapi3/python-flask*`) * [python] Adds python oneOf/anyOf models + tests (#5341) * Adds oneOf + anyOf schemas, models and tests to python-experimental * Adds setUpClass and tearDownClass * Removes newline in method_init_shared.mustache * Regenerated v3 spec sample for python-experimental * Fxes test for discard_unknown_keys * Moves new models into existing spec, regen python-exp and go-exp * Also fix python-exp windows file * fix CVE-2020-8130 (#5483) * [go] Add Ptr method to const enum values (#5257) * fix rubocop warns in Ruby client's custom spec (#5488) * [C-libcurl] The name in API parameter should not be escaped even though it includes a C key word. (#5487) * [go-experimental] Support aliasing of API keys (#4940) * [go-experimental] Support aliasing of API keys * Use {{.}} inside condition * Use name instead of keyParamName for lookup * x-lookup to x-auth-id-alias * [java] Support aliasing of API keys (#4966) * [java] Support aliasing of API keys * Rebuild Java Jersey2 sample client * x-lookup to x-auth-id-alias * Regenerated * [cli][gradle] Validate now uses parseOptions w/setResolve (#5471) * [cli] Validate now uses parseOptions w/setResolve The validate command now uses ParseOptions#setResolve(true) to match how we parse in CodegenConfigurator and online's Generate. Without this option, the OpenAPI 3 parser skips the "resolve" block, which made lead to validations in the command not matching validations during generation. * [gradle] Validate now uses parseOptions w/setResolve The Graldle validate command now uses ParseOptions#setResolve(true) to match how we parse in CodegenConfigurator and online's Generate. Without this option, the OpenAPI 3 parser skips the "resolve" block, which made lead to validations in the command not matching validations during generation. * [kotlin]Fix ktor doesn't generate nullable types (#5258) * If not required, need `? = null` * run ./bin/kotlin-server-petstore.sh * Added `?` when value is `required` and `isNullable` * Rerun ./bin/kotlin-server-petstore.sh. But No differences * [C++] Add an option to allow having lowercase variables in models, Pistache: allow using reservedWords in models (#5434) * [C++][Pistache] Use reserved words to replace incorrect names discard old decision to truncate reservedWords * [C++][Pistache] Update struct model to use name instead of baseName * [C++][Pistache] Update Petstore sample * [C++] Add option to have lowercase variables * [C++] Update generated docs * [BUG] [JAVA | Spring] Cookie in parameter is not correctly generated (#5393) * Cookie in parameter is not correctly generated * gh-5386: Fix cookie parameter in * gh-5386: Fix cookie parameter in * gh-5386: Update test file * gh-5386: Fix cookie parameter in * gh-5386: Fix cookie parameter in * gh-5386: Regenerate samples * gh-5386: Fix test * Added Spring CookieValue tests Co-authored-by: Gonzalo * Add missing `@Generated` annotation. (#5384) The annotation is present on other generated files when using jaxrs-spec, but it missing on model classes. * [scala] [template] scala model property style (#5486) * Model property naming style generic for scala * scala templates based on abstractScala regererated * docs generators updated * property format tests * add Agoda as the user (#5494) * Hide timestamp in Scala Play server samples (#5495) * hide timestamp in scala play server output * add chameleon82 to scala tech committee * Add a link to tech blog tech.medpeer.co.jp (#5498) * Add links to blog posts about OpenAPI Generator (#5508) * Typescript array alias array (#4981) * Add failing tests for typescript type declaration * Refactor array and map child type string fallback * Add unaliasSchema to typescript getTypeDeclaration * TypeScriptRxjs: Use Blob as file type declaration This was inadvertantly changed in https://github.com/OpenAPITools/openapi-generator/pull/5266 * [core] Sanitize/underscore/camelize cache expiry (#5484) The helper methods for sanitize/underscore/camelize were recently updated to cache values in static maps. This would lead to a memory leak in hosted environments as the maps had no cleanup/expiry. This moves those cached entries to Caffeine caches with expiry based on last access to allow the edge-case performance improvement gains on very large documents, without the memory leak in hosted or embedded environments. * Update README.md * Add a link to the conference paper (#5510) * Add a link to the conference paper * fix author list * [Slim4] Add Data Mocker middleware (#4978) * [Slim4] Store response schemas * [Slim4] Add Data Mocker middleware * [Slim4] Enhance Slim router * [Slim4] Enhance config * [Slim4] Fix data format key in object mocking * [Slim4] Add tests for Data Mocker middleware * [Slim4] Add Mock feature documentation * [Slim4] Refresh samples * [Java][Spring][Spring-Cloud] Fix #5144 - Use conditional package declaration to avoid unnecessary dependencies (#5145) * FIX: Use conditional package declaration to avoid unnecessary dependencies * DEV: Adjusted sample ClientConfiguration.java for async spring-cloud * fix(php): no need to serialize collections, Guzzle does that, fix #2292 (#3984) * fix(php): only serialize collections if !explode, Guzzle handles the rest, fix #2292 * fix(php): update petstore samples Co-authored-by: Mahdi Dibaiee * [php] replace $collectionFormat with $style (#5517) * php - remove $collectionFormat * update php openapi3 petstore sample * [BUG][scala][template] scala generate java.math.BigDecimal instead of scala type (#5514) * [BUG] scala generate java.math.BigDecimal instead of scala type * update docs/generators * [PHP] complete support for form style (#5519) * [BUG][PHP] Parameter property style not fully implemented (related to comment on PR #3984) * [AUTOGENERATED][PHP] Sample Files * update jackson dependency to newer version (#5527) * Fix Swift4 CI tests (#5540) * comment out swift 4 order tests * comment out store tests * Test Dart petstore client in CircleCI (#5544) * test dart2 in circle ci (jdk7) * fix tests * update package * fix dart installation * Add serialization of ModelComposed (#5551) * Fixes kwargs typos, removes E501s (#5552) * Update generic model to support nullable properties (#5568) * [DOC] Add link to integration test wiki in CONTRIBUTING.md (#5570) * Add link to integration test wiki * Add link to integration test wiki * [Kotlin][client] fix file upload (#5548) * [kotlin] fix file upload * [kotlin] fix file upload * [kotlin] fix file upload * [kotlin][client] fix jackson integration * [kotlin] fix file upload * [kotlin] fix file upload * update doc * [Java] Fix exception when OAuth2 token URL is a relative URL (#5535) * Add support for case when OAuth2 token URL is a relative URL * Add support for case when OAuth2 token URL is a relative URL * run scripts under bin * [Java] fix runtime exception when there are multiple auth methods (#5530) * fix runtime exception when there are multiple auth methods * Refactor a bit so that it does not cause conflict with relative url token branch * [markdown] Fix broken links when generating markdown (#5569) * [markdown] Fix broken links when generating markdown The `api.mustache` file generates links to the markdown model files. These links were previously brokeen. Additionally, the defaultPackage for markdown is "/Models", so this looked pretty in the heading for model files. So this prefix has been stripped from the header in `model.mustache`. * Re-generate Petstore samples for markdown * typescript-angular: fix zone-js version for angular 8 (#5585) * Add a link to the slide (#5590) * [Swift] fix URLSession file upload (#5546) * [swift5] - fix URLSession file upload * [swift5] - fix URLSession file upload * [swift5] fix file upload * [swift5] - fix URLSession file upload * [swift] add unit tests for file upload * [swift] update samples copyright * [swift] add option for API prefix (#5567) * [swift] add option for API prefix * [swift] update docs * [haskell-http-client] update stack; exclude problem time versions (#5589) * [go-experimental] Do not generate HTTP signature unit test for every generated SDK (#5588) * Do not generate HTTP signature unit test for every generated SDK * Add golang 1.14 to CI environment * fix unit test issues * remove script commands that were commented out * add support for ed25519 private keys * PR to solve 2 open issues on enums: #5091 and #4293 (#5477) * PR to solve 2 open issues on enums: Issue 5091 needs to generate enums also when the enum is directly in a param to a API call, instead than in a model. I did that by copying and adapting enum code from *model* to *api* Issue 4293 needs to decorate enums, for when enum names or enum values are repeated over the yaml definition. * PR to solve 2 open issues on enums: Issue 5091 needs to generate enums also when the enum is directly in a param to a API call, instead than in a model. I did that by copying and adapting enum code from *model* to *api* Issue 4293 needs to decorate enums, for when enum names or enum values are repeated over the yaml definition. * Enums decorated: with {{projectName}}_{{classVarName}}_{{enumName}}_ in the models, with {{projectName}}_{{classVarName}}_{{enumName}}_ in the operations. * Changes to the c client: - Removed white space. - Removed ToJSON and FromJSON function for the enums, since they are not used - Sanitized project name in the .java file. For example, this solves a problem with the issue #2338, where the yaml file had title: "Skycoin REST API." * Changes to the c client: - Removed white space. - Removed ToJSON and FromJSON function for the enums, since they are not used - Sanitized project name in the .java file. For example, this solves a problem with the issue #2338, where the yaml file had title: "Skycoin REST API." * Adds parseFlattenSpec (#5526) * Adds parseFlattenSpec, updates tests and helper functions * Adds parseSPec invocation inside parseFlattenSpec * Scala-Akka: Add missing body to PATCH requests (#5605) * NodeJS - Adds missing keyword (#5606) * [jaxrs-cxf-cdi] Support PATCH httpMethod (#5574) Update the required CXF version to 3.1.2 since PATCH support appeared with this version. Add the cxf PATCH annotation to the imports so that the generated code when defining a PATCH api compiles. * fix default value for abstract scala and scalatra server impl (#5578) * [Java] Generated API class has wrong dataType and does not compile Issue (#5331) * add unit test assertion * add check for composed schema * add support for x-allOf-name * change x-allOf-name to x-all-of-name * Add more troubleshooting information * Add more troubleshooting information * Add more troubleshooting information * Add more troubleshooting information * [swift5] stop hiding network error (#5603) * [swift5] stop hiding network error * [swift5] stop hiding network error * [scala][templates] java 8 dates support (#5291) * [scala][akka-http-client] java8 dates support * scala-akka readme doc updated * DateSerializers renamed * rename serializers * move date-library option to abstractScala * generators docs updated * enum defined for date libraries * Backport to scala-http-client * fix scala-akka-client date serializers * fix typo in docs * switch scala templates to java8 (jsr-310) date library by default * update scala samples with java8 date library * update scala generators docs with java8 default date library * fix scala-play-server generator cli options as only java8 dateLibrary supported * fix scalaz DateTimeCodecs template to support java8 * scalaz ci test againt java7 removed as it generate scala 2.11.8 client which is java8 based * update doc * Adding Response Interceptor (#5500) * added Response interceptor for native clients * added Response interceptor for native clients * [k6] Add blog post about using the k6 generator (#5608) * [Kotlin] Remove kotlin-reflect dependency when not needed (#5502) * Remove kotlin-reflect dependency when using CodeGen * Update Kotlin tests * Regenerated unit test samples * Remove newline in generated build.gradle files * [typescript-fetch] add interfaces, withInterfaces (#5612) * typescript-fetch: interfaces, first draft * fix name in description * [scala] Regenerate akka sample (#5622) * scala-version 2.11.12 (#5618) * micheleISEP->michelealbano (#5625) * [Powershell] refactor the client generator (#5629) * add api client * add local variables * add configuration * add header/query/form parameter support * add partial header * add auth, fix parameters type * fix accept, content type * url query string * fix path, header * remove dep on C# client * fix method naming with package name * fix object * convert result from json * better response handling * remove tostring method * fix model doc * fix default module * generate api test files * better api, model tests * fix add pet * add appveyor * fix accept, content type * add petstore tests * fix form parameters * test delete * better file handling (upload) * better code sample * add package version, better doc * delete unused files * fix header parameters * clean up api client * update samples * support query parameter * better method and parameter naming * minor formatting change * better doc, fix cookie parameter * better doc * add api prefix support * better api nam prefix option * fix configuration * throw errors for required parameter * fix authentication * add try catch block to sample code * rename model * use debug, clean up comment * revise code * move bin script * update doc * add new file * better map support * [PowerShell] minor improvements and bug fixes (#5635) * add output type, minor format fix * minor test improvement * Port client updates to server (#5634) * Revert "scala-version 2.11.12 (#5618)" This reverts commit 6b984a926a0f99120a4ad80cef73bee19f8614cd. * update release date * Handle negative response from the server (#5649) * Fix integration tests (Travis, CircleCI) (#5672) * fix php tests * fix scala tests * update ts angular v6 rest * fix user create test * fix spring cloud test * comment out user delete * fix angular v7 tests * fix user test * fix tests * fix go exp tests * commented out delete user tests * comment out delete user tests in go openapi 3 * fix clojure tests * [PowerShell] Fixes typo (#5648) * Solving issue #5623 and supporting bools for C client label:"Client: C" (#5624) * Removed stray "printf"s in modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CLibcurlClientCodegen.java * Support for booleans in C client * Update README.md * Change to C API mustache files to solve issue #5623 * Debugging of C's modle-body.mustache, as suggested by ityuhui * Final changes suggested by ityuhui * [PowerShell] Fix map type (#5638) * fix map type * remove output type, fix appveyor * test macos * comment out failing scala test * fix typo: configuration * Revert "comment out failing scala test" This reverts commit 1dcf84ffcbb7ab520938ae7c75d60a8329f71478. * [powershell-experimental] Protects against stackoverflow when OAS spec has circular references (#5646) * protects against stackoverflow when OAS spec has circular references * protects against stackoverflow when OAS spec has circular references * Adds configuration option to skip certificate check. Fixes a typo. Fixes an issue which was restricting from cookie to get consumed (#5657) * [k6] bugfixes to improve the output script (#5614) * [k6] Skip appDescription escaping * [k6] Fix variable identifier in output * [k6] Fix bug with reserved words handling * [C][Client] Check the pointer before deleting operation to avoid core dump label:"Client C" (#5626) * [C-libcurl] Check the pointer before deleting operation to avoid core dump * [C-libcurl] Check the pointer before deleting operation, update sample * [kotlin][client] Add Jackson to interface properties and remove extra line feed (#5459) * [kotlin][client] Ensure Jackson annotations are consistent with interface vars * [kotlin][client] Rebuild samples * [kotlin][client] Some kotlin client enhancements - Don't use JsonFormat for Date objects, this should be controlled via a custom serializer/deserializer or a turning on and off serialization features of Jackson. I've updated the jacksonObjectMapper config to write the dates as strings, which I think was intended in the original commit. https://fasterxml.github.io/jackson-databind/javadoc/2.6/com/fasterxml/jackson/databind/SerializationFeature.html#WRITE_DATES_AS_TIMESTAMPS https://fasterxml.github.io/jackson-databind/javadoc/2.6/com/fasterxml/jackson/databind/cfg/MapperConfig.html#getDateFormat-- - Dont' use @JsonFormat(shape = JsonFormat.Shape.OBJECT) for enums. This causes Enums to be formatted as objects with an internal "value" field. In reality, OpenAPI enums are just strings without properties and should be treated as a string. https://www.baeldung.com/jackson-serialize-enums#2-enum-as-json-object - Add's Kotlin use site annotation @get: to JsonProperty for parent interface properties. Otherwise Kotlin will warn: "This annotation is not applicable to target 'member property without backing field or delegate'" - Add's JsonTypeInfo annotations to interfaces for inheritance. This was copied verbatim from the kotlin-spring generator. https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/main/resources/kotlin-spring/typeInfoAnnotation.mustache * [kotlin][client] Rebuild kotlin samples * Remove scala version in parent pom (#5647) * [asciidoc] Allow the inclusion of additional documentation to t… (#5260) * [asccidoc] Allow the inclusion of additional documentation to the asccidoc generated Resolves #5228 * [jaxrs-reasteasy-eap] Fix invalid Bean Validation annotations for Longs (#5659) * fix issue #5658 * update samples * [PowerShell] Test powershell petstore client in Appveyor (#5674) * remove scala version in parent pom * test ps petstore in appveyor * fix command * build and import * fix import module * fix import * skip module import * run multiple commands * move to test script * test ps exit * fix exit * check last status code * clean tests * exit last code * add import * change dir * skip build failure * fix check * trigger build failure * fail fast * restore c# test * new line comment * add powershell exp to ensure up to date script * [PowerShell][Experimental] Better docstring (#5688) * add docstring to powershell module * add doc string * Nodejs express js packages update (#5675) * Updated to new nodejs packages, depending heavily on express-openapi-validator. Requires quite a change in code. Updated the business-logic in the controllers/Controller.js file. Logger now records also timestamp of events. Files are uploaded according to definition in config.js file * Removed commented-out code; Changed openApi document extensions to suit new express-openapi-validator definition; multipart and file uploading is supported now; Automatic response returns the values the were sent in the request * fixed README documentation, fixed a mistage in package.json/mustache * added generated files that were created when running the ./bin/test file * [go-experimental] Fix nullable support (#5414) * Fix nullable support in go-experimental client * Fix support for models with parents and container fields * Make sure that oneOf interfaces serialize properly even if they're required (non-pointers) on other models * Spaces => tabs * Regenerate samples * Make some methods of nullables pointer-receivers, add tests * Improve the Get/Set logic to make usage more convenient * Address review * [kotlin][client] make base path globally configurable (#5450) * [kotlin][client] make base path configurable * [kotlin][client] update pet project * [kotlin][client] set default base path * [kotlin][client] set default base path * [kotlin][client] set default base path * Add michelealbano to C technical committee (#5692) * [Go][Experimental] Rename extensions from x-basetype to x-go-base-type (#5691) * rename go vendor extension * update go exp petstore samples oas3 * comment out powershell petstore in uptodate script * remove processing of http_signature_test.mustache (#5696) * Fix generation of oneOf interfaces for oneOf usage in properties (#5400) * Fix generation of oneOf interfaces for oneOf usage in properties * Only generate oneOf interface models when oneOf is defined * use basic parsing (#5702) * [python/asyncio] explicitly close client session via async context manager (#5621) * [gradle] Include engine option for handlebars generation (#5686) * [codegen][Go] Fix compilation error of generated go code when schema is free form object (#5391) * Fix code generation for free-form objects in go-experimental * Execute scripts in bin directory * Add more use cases for open-ended types * Add more use cases for open-ended types * Add more use cases for open-ended types * add code comments * Better name for test properties * handle scenario when type is arbitrary * handle interface{} scenario * handle interface{} scenario * add helper function isAnyType * isAnyType function * implementation of isAnyType function * fix javadoc issue * handle interface{} scenario * use equals comparison instead of == * merge from master * Add code documentation * add code comments, remove unused min/max attribute, fix equals method * Handle 'anytype' use case * add code comments * override postProcessModelProperty to set vendor extension * Use vendorExtensions.x-golang-is-container * fix compilation error of generated code * fix compilation error of generated code * fix compilation error of generated code * [Java] Update version of maven-surefire-plugin (#5509) * use more recent version of maven-surefire-plugin * use more recent version of maven-surefire-plugin * higher debug level for troubleshooting ci issue * temporarily increase debug log to help troubleshoot * Use local instance of pet store service for unit test purpose * Add more logging to troubleshoot unit test failures * Add more logging to troubleshoot unit test failures * Add more logging to troubleshoot unit test failures * Add more logging to troubleshoot unit test failures * Add more logging to troubleshoot unit test failures * use random ID for Java unit test instead of fixed id * add code comments and specify URL for java unit test * reenable quiet argument * fix java unit test issues * fix java unit test issues * Revert "fix java unit test issues" This reverts commit e8508416ff0f2aeb568e3f916b013dc967390f74. * fix java unit test issues * Generator for JavaScript/Apollo Client (#5645) Co-authored-by: William Cheng * Add yutaka0m to Kotlin Technical Committee (#5716) * Add Scala client scripts to ensure-uptodate process (#5712) * add scala client to ensure-upto-date * new scala-akka petstore oas3 folder * regenerate scala akka oas2 petstore * remove script * Minor improvments to JS apollo generator (#5714) * minor improvments to js apollo generator * comment out apollo * [Rust Server] Handle text/xml correctly (#5660) * [Rust Server] Handle text/xml correctly Treat application/xml the same as text/xml as per RFC 7303 * [Rust Server] Add test for text/xml * Update samples * 4.3.0 release (#5721) * update samples (#5722) * 5211 - Use allVars instead of vars for Kotlin client (#5396) * [C++] [Qt5] fixed cpp-client-qt5 HttpRequestWorker requests crashing on timeout... (#5651) * - fixed cpp-client-qt5 HttpRequestWorker requests crashing on timeout when they have actually NOT timed out (were calling back into a deleted struct). * #minor fixes after review * Regenerate changed files Co-authored-by: valentin Bisson Co-authored-by: etherealjoy * Fix SSL setting in checkout script (#5725) * fix ssl setting in checkout script * add check for sbt-openapi-generator * [C] fix decode funtion (#5642) * fix function names and add parameter to return decoded bytes length from base64decode function * format base64decode function to avoid unnecessary malloc and fix wrong length assigning * update the pointer assigning for some reason var++ / *var++ cannot be done on int *var, hence making a local variable which is incremented and at the end it is assigned to the pointer. * Update bump.sh to go SNAPSHOT to version (#5727) * Fix CI failures (#5734) * update ci to use petstore 1.0.4 * comment out test * comment out test * comment out update user test * comment out more tests * use latest petstore * comment out updatePetWithForm * comment out update pet test * fix file path in release_version_update_docs (#5724) * better appveyor test (#5739) * better readme, type mapping, new option (#5740) * Remove warning for unused camel case vendor extension for Qt5 client and server (#5731) * [PS][Experimental] Add multiple server support (#5741) * code comment * add get host setting * add multiple server support * add default headers support (#5746) * [C][Client] Support SSL client authentication for the c client (#5719) * [C][Client] Support SSL client authentication * [C][Client] Support SSL client authentication, update sample * [kotlin] Fix #5247 incorrect enum parameter type for arrays (#5435) * [Erlang-Server] security definition context changes don't propagate to handler (#5751) * Map Merge Context & Params handler requires context and params to be merged before returned to user defined request_handler. * post build & shell script * Delete VERSION * [PS][PowerShell] fix passthru, use switch instead of bool (#5768) * fix passthru, use switch * remove line * comment out kotlin vertx server test (#5767) * add support for common verbs (#5771) * fix request.on_complete message when tempfile is nil (#5745) * fix request.on_complete message when tempfile is nil * update faraday client sample * add openapi3 client samples * use prepare instead of new (#5773) * use Initialize instead of prepare (#5777) * add map example (#5778) * [PS][Experimental] Better common verb handling (#5783) * better common verb handling * better debugging * add option to customize common verb * [cli][docker] Better expose version/sha information of builds (#5736) * [cli] Some CLI improvements… * Introduce --version * Introduce --help * Add --sha to version command for short SHA display * Output Version and SHA details * In new --version output, display repo and doc site Additional cleanup to suppress warnings and code quality. * [docker] Adds labels for metadata This adds image labels to store metadata on the online and cli docker images, using standard labels: * org.opencontainers.image.created * org.opencontainers.image.revision * org.opencontainers.image.title * org.opencontainers.image.version These can be inspected via 'docker inspect IMAGE_NAME' and may be useful in tooling/automation or bug reports submitted by users. For more details on these labels, see: https://github.com/opencontainers/image-spec/blob/master/annotations.md * Include version --full for equiv to --version * [cli] Add --global-property for -D replacement (#5687) -D option has been deprecated as it was previously used to: * Pass "system properties" * Pass additional properties This was confusing because we already have --additional-properties and because Java System Properties are passed as -D before program arguments. Confusion around the -D option had existed for some time, but when we introduced the thread-safe GlobalSettings to avoid overwriting Java System Properties, we created a hard break from Java System Properties in the generator. This also disconnected the previous "system properties" from accepting additional properties. Once these newly deprecated methods are removed, we will have a clear separation of concerns between: * Java System Properties * Global generator properties (used as workflow context) * Additional properties (used as generator options) This commit marks multiple places for cleanup in 5.0. These will be breaking changes, and lower effort to break in 5.0 with deprecation warnings now rather than adding sibling properties throughout the code and potentially introducing logic errors. * [dart-dio] Fixes --model-name-suffix having no effect (#5669) Fixes #5409 * [go-experimental][go][client] Remove unreachable code in go client API methods (#5611) * [go-experimental][go][client] Remove unreachable code in go client API methods * Properly regenerate all samples * please add openVALIDATION Project to readme (#5534) * added openVALIDATION Project to readme * Update README.md Co-Authored-By: Akihito Nakano Co-authored-by: Akihito Nakano * [Csharp-client] Complex form parameters are not serialized as application/json (#5787) * [csharp-client] Complex form parameters are now correctly serialized as json. Reference: http://spec.openapis.org/oas/v3.0.3#special-considerations-for-multipart-content * Updated bin/windows csharp sample generation scripts to point to the correct directories * Updated csharp samples Co-authored-by: Olivier Leonard * fix scala-akka java8 serializers (#5742) * fix scala-akka java8 serializers * regenerate samples for akka-http * [typescript-axios][client] Unnecessary imports occurs when using withSeparateModelsAndApi (#5797) * add ts-ignore * add petstore sample * use write verbose in auth, better api doc (#5804) * [PS][Experimental] add withHttpInfo support, fix "null" return (#5811) * add with http support * use full name in tests * using full name in test * skip type check * [PS][Experimental] Add tests for array of object in response (#5814) * debugging array response * fix find pet tests * better tests to ignore order * [codegen] Use once(LOGGER) to reduce amount of identical warning messages (#5808) * Warn once instead of many times when the log statement does not have contextual information * Warn once instead of many times when the log statement does not have contextual information * make name cache configurabl (#5775) * [codegen] Cachesize config seconds (#5816) * make name cache configurable * Address review comments * [Python-experimental] Documentation enhancement for oneOf schema and minor err msg improvement (#5791) * Add documentation to generated code * Improve error message * Improve documentation * Improve documentation * Improve documentation * Improve documentation * Improve documentation * Improve documentation * Run sample scripts * Address review comments * Address review comments * Fix problem in python error message * rename hostsetting, validate base url (#5821) * fix array return (#5822) * Scala akka-http server (#5758) * Scala akka-http server base implementation * [scala-akka-http-server] petStore samples * Improved the formatting of generated files * Updated scala-akka-http server samples * [scala-akka-http-server] the groupId, artifactId and artifactVersion default value are used as intended. * Fixed the default operation not being correctly generated on parameterless operations * Added build.sbt.mustache supporting file * Updated scala-akka-http server samples * ScalaAkkaHttpServer: Fixed a String.format call to use Locale.ROOT for locale * [scala-akka-http-server] Fixed defaultValue being escaped during generation * Added scala-akka-http.md * Replaced all "⇒" character with "=>" to retain compatibility with scala 2.13 * [scala-akka-http] Added a config option akkaHttpVersion It's set in the generated build.sbt. * Updated scala-akka-http server samples * [scala-akka-http] More accurate akkaHttpVersion parsing * Updated scala-akka-http.md * [scala-akka-http] Changed the akka-http version check to fix the generation of StringDirectives * Updated scala-akka-http samples * updated scala-akka-http.md Co-authored-by: Olivier Leonard * Minor improvements to scala akka server (#5823) * minor improvements to scala akka server * add samples * update doc * Update swagger parser to 2.0.19 (#5413) * update swagger parser to 2.0.18 * fix online server exception * Revert "fix online server exception" This reverts commit fe3cb5221f362c00b176fa81411eaf368f0e446d. * update parser to 2.0.19 * [jaxrs-cxf-cdi] fix allOf equals and hashCode (#5756) When generating model that use allOf, the equals and hashCode methods must take the parent class into account. * [BUG] [KOTLIN] Fix default value generation for Kotlin Strings (#5776) * fix default value generation for kotlin * add updated pet templates * Revert "add updated pet templates" This reverts commit 7e8168ad * regen pet store projects code * tests for models for C-libcurl generator (#5699) * First try to generate unit tests for the models of the C-libcurl client. Models into models are not supported yet. * Added unit tests for the modules of the C-libcurl client to the git repository. * Support for objects having other objects as properties, for the C-libcurl client generator * Proper formatting of generated code * use allVars to cover all properties (#5835) * support enum in parameters (#5838) * [C++] [Qt5] [Client] fixed cpp-client-qt5 HttpRequestWorker contentCompression variables initialization (#5834) When contentCompression is not enabled, the variables isRequestCompressionEnabled and isResponseCompressionEnabled in HttpRequestWorker are not being initialized. Without initialization the compress function could be called and the request content could be an empty QByteArray instead of original request body. * minor fix to http basic auth (#5839) * Scala akka http server - normalization of some vendor extensions (#5829) * [scala-akka-http-server] Normalized vendor extension "paths" to "x-paths" * [scala-akka-http-server] Normalized vendor extension "hasDefaultValue", "isDefault", "specificMarshallers", "fileParams", "nonFileParams" Co-authored-by: Olivier Leonard * Add Bouill to the Scala technical committee (#5843) * C client generator improvements to support petstore. Solves #5836 (#5837) * C client generator improvement to support: openapi-generator/modules/openapi-generator/src/test/resources/3_0/petstore.yaml * Improvements to the C client generator: - moved base64* from apiClient.c to binary.h/binary.c - changed CR/LF to LF in binary.h/binary.c * C client generator: better support for base64encode / base64decode * Add openapi.yaml file to Java clients (#5765) * Add openapi.yaml file to Java client * Move supporting template file to Java root * Update petstore clients * [codegen] Fix 'super.HashCode' for oneOf and allOf Implementations (retry) (#5830) * Added hasVars after completion of all model post-processing (#5587) * Post ensure-up-to-date * Update to check the size of vars and not assume non-null * update mysql samples * Add default case to handle response code (#5825) * add default case to handle response code * fix default response code * add test for isDefault * fix user id in scala tc * Fix for Issue #4840 [BUG][JAVA][spring-mvc] Generated Code for Map of Maps Return Type does not compile (#5240) * add parent for allOf only (#5851) * Add pythonSrcRoot option to python servers (aiohttp/flask/blueplanet) to support src/ layout projects [and reenable/fix all python server tests] (#5423) * python server: Add pythonSrcRoot option This will allow the python project to be in a subdirectory (as specified in pythonSrcRoot). That could mean following the src layout with sources under src/ or lib/. Multi-language projects might use a sub directory like python/, or whatever makes sense for the project. By default, the pythonSrcRoot is "", meaning the existing behavior is the default. * python server: update template files to support pythonSrcRoot * python server: update docs to add pythonSrcRoot option * python server: add pythonSrcRoot sample script * python server: build sample srclayout project * [Python] copy test files preserving history * [Python] Make a conflict to preserve file copy history * [Python] customize pom.xml for src layout tests * [Python] add python-aiohttp-srclayout tests * [Python] Fix server tests by updating requirements Reverts the PR that disabled python2 server tests: https://github.com/OpenAPITools/openapi-generator/pull/4949 Reverts commits that disabled python3 server tests: 9adfedbfbb45c7059e64b3d9a285710bded4fb62 17ee990baaa80585242c7a07d64e2be4888fcfd0 Issue about the python 3 tests: https://github.com/OpenAPITools/openapi-generator/issues/5235 I couldn't find an issue about the python2 tests being disabled. I'm guessing build errors like the following were the trigger: https://travis-ci.org/github/OpenAPITools/openapi-generator/builds/634238181 Let's see what breaks! * [Python] Copy setup.py to python-aiohttp * [Python] Save history while copying setup.py to python-aiohttp * [Python] Add aiohttp server setup.py * [Python] Fix python server tests with src layout * [Python] bump Flask-Testing version * [Python] Pin pyyaml for py2.7 flask server * [Python] simplify flask server requirements * consolidate server tests * [Python] rebuild python server samples * [Python] Fix python server requirements for older pythons Documented minimum python version for our aiohttp server is 3.5. Documented minimum python version for our flask server is 3.4. Connexion 2.3 is the last version to support python 3.4 and 3.5, so fix the version pinning to correctly select <=2.3 for these EOL python versions. Newer pythons should get the latest if possible as there many relevant bug fixes. Werkzeug also needs to be pinned for these old versions in the aiohttp server just like for the flask server. 3.4 and 3.5 are EOL. We really should increase the minimum supported version, but that is for another PR to do. * stop error globally (#5858) * [PS][Experimental] Add validations to model (#5842) * add validations to model * better error message * improve validation * Updates to allow the setting of the dateTime format string (#5763) * [PS] Select Content-Type in the response (#5872) * better return type handling * update tempalte * better documentation * fix greater than * various enhancement to ps exp generator (#5875) * [C#] dependency upgrade (#5870) * Updating packages version (#5313) * Add support to RestSharp version 106.10.1 Restsharp 106.10.1 needs the Content Lenght as a parameter to AddFile method * Updating RestSharp Version Updating RestSharp Version * Update netcore_project.mustache * Update netcore_testproject.mustache * Update Project.mustache * Updating packages version Updating packages version * Updating packages version Updating packages version * Updating packages version Updating packages version * Updating packages version Updating packages version * Updating packages version Updating packages version * Updating packages version Updating packages version * Execute task async obsolete Use ExecuteAsync instead * update csharp samples Co-authored-by: William Cheng * [csharp] Library upgrade fix (#5848) * On .net45 framework, Restsharp version is updated to 106.10.1 Otherwise, it stays on version 105.1.0 * Added additionalProperties for library versions and target frameworks * Removed unused properties * Added an additional property to test for a specific version of RestSharp * Updated csharp samples * Fixed nuspec.mustache to use library specific additional properties * Updated csharp samples * Updating CI/samples.ci csharp petstore test project file. * Updated csharp.md Co-authored-by: Olivier Leonard * [csharp-client] Restored tests on csharp samples (#5879) * Restored tests on csharp samples * Restored a reference to the file used to test file uploads Co-authored-by: Olivier Leonard * update samples Co-authored-by: Igor Quirino Co-authored-by: Bouillie <34162532+Bouillie@users.noreply.github.com> Co-authored-by: Olivier Leonard * [Csharp-client] Complex form parameters are not serialized as application/json (#5849) * [csharp-client] Complex form parameters are now correctly serialized as json. * Updated csharp samples Co-authored-by: Olivier Leonard * docs: removes Nico from technical committee (#5883) * [PS] better handle special variables (#5885) * add variable * fix reserved words * update ps doc * [PS] add file post-processing to the PowerShell generator (#5864) * add post process to ps generator * add import * fix merge issue * consolidate header selection functions (#5889) * [Java-client] Add maven-compiler-plugin in pom.xml and enable linter checks by default (#5866) * Add maven-compiler-plugin plugin in Java pom.xml and enable linter checks by default * Add maven-compiler-plugin plugin in Java pom.xml and enable linter checks by default * Update enum.mustache (#5793) https://github.com/OpenAPITools/openapi-generator/issues/5792 * Update modelGeneric.mustache (#5378) * Update modelGeneric.mustache If maxlength is specified for a property type enum it there should be .ToString() appended before length check * ran the csharp petstore bar and updated the file Co-authored-by: Shweta Shukla * Fix Scala sttp generator packages (#5890) * Fix Scala sttp generator packages * Change package to parameterised * [Dart] Fix "basic" auth method and Add Bearer token support (#5743) * added auth check and lint * fixed basic auth condition * Added bearer auth * updated samples * update dart petstore samples Co-authored-by: William Cheng * Add date time format annotation on pojo for model query parameters (#5437) * Add date time format annotation on pojo for model query parameters * Regenetare samples * update spring samples Co-authored-by: William Cheng * [mysql] Add basic SQL queries (#5757) * Add basic SQL queries template * Add namedParametersEnabled option * Move model related SQLs into Model folder * Update README template * Refresh samples * [enhancement] [jaxrs-spec] Add builders to models (#4930) * Update formatting in jaxrs-spec POJOs * Add generateBuilders option * Update formatting in jaxrs-spec POJOs * Disable the builders generation by default * Ensure samples are up-to-date * Revert newline change * Run ensure-up-to-date * update doc * fix merge conflicts Co-authored-by: Artem Shubovych Co-authored-by: William Cheng * Update generated build files for REST Assured (#5873) * REST Assured 4.3.0 * Jackson 2.10.3 * Gson 2.8.6, GSON-Fire 1.8.4 * Okio 1.17.5 * Joda-Time 2.10.5 * ThreeTenBP 1.4.3 * Added missing dependencies for Bean Validation * Added missing dependencies for `@Generated` annotation * Refresh REST Assured sample project * [Java][Feign] Bug fix in @Param annotation (#5250) * FIX-5249 fix @Param annotation for Feign-client code generation Use paramName instead of baseName in order to make mapping in @Headers section fit the param-value. * update samples * FIX-5249 fix @Param annotation for Feign-client code generation Use paramName instead of baseName in order to make mapping in @Headers section fit the param-value. Co-authored-by: Christoph Preißner Co-authored-by: William Cheng * [Java] Increase java compiler stack size to handle large files (#5901) * increase java compiler stack size to handle large files * increase java compiler stack size to handle large files * Added emineo to list of companies on website (#5905) * add emineo to the list * [swift5] fix warning (#5900) * update bitwise config (#5904) * [Java] Discriminator lookup should not be case insensitive by default (#5894) * Add 'discriminatorCaseSensitive' property * Discriminator value lookup should not be case insensitive * fix typo * run scripts * execute ./bin/utils/export_docs_generators.sh * fix discriminator mapping, add code comments * minor fix to users.yml * Add a link to optim blog post (#5922) * [Java] Fix inclusive max validation (#5908) Co-authored-by: erikmolin * add bearer auth support to csharp netcore (#5921) * [Python][aiohttp] create venv as rule (#5913) * create venv as rule * create venv as rule II * Fix for Result Model Name collision (#5923) * Fix for Result Model Name collision * Run Scripts Co-authored-by: Sebastian Ohm * [Dart] Remove content type from header when content type is not specified (#5752) * accept empty content type * fixed test * updated samples * additional comment out * update dependency for java client (#5926) * Update axios dependency to the new minor version 0.19.0 (#5867) * Update axios dependency to 0.19.0 Axios (version 0.18.0) used by typescript-axios generator is more than two years old (released in Feb 2018). Axios 0.19.2 released earlier this year contains a lot of fixes and functionality, I recommend updating to 0.19.2. * Ran ./bin/typescript-axios-petstore-all.sh to update package.json in ./samples Co-authored-by: Chandra Yalangi * fixed README/doc of bearer auth support for csharp-netcore (#5931) * fix duplicated semi-colon in c# model (#5934) * [Python-experimental] Use DER encoding for ECDSA signatures, add parameter to configure hash algorithm (#5924) * Use DER encoding for ECDSA signatures * Use DER encoding for ECDSA signatures * Use DER encoding for ECDSA signatures * Use DER encoding for ECDSA signatures * fix python unit tests for http message signature * Fix error message * format python code * format python code * [Python-experimental] Fix TypeError: unhashable type: 'list' (#5810) * handle scenario when value is a list, fix TypeError: unhashable type: 'list' * Add __hash__ function * use list instead of set * use list instead of set * use list instead of set * use list instead of set * use list instead of set * use list instead of set * [python/asyncio] fix passing proxy parameters to aiohttp (#5943) * [C][Client]Fix data lost when libcurl write-data callback function is called multiple times (#5828) * [C][Client]Fix the defect of data lost when libcurl write-data callback function (configured by CURLOPT_WRITEFUNCTION) is called multiple times. * [C][Client]Fix data lost when libcurl write-data callback function is called multiple times (Reset count) * [typescript-axios][client] Allow apiKey type Promise. (#5953) * change apiKey type * recreate sample * Add YITU Technology to the user list (#5967) * add yitu to the user list * use yitu technology * Use model as body param for generateAliasAsModel (#4569) * generateAliasAsModel: Use model name as body param * Update samples * resolve merge conflicts in the core generator files * fix merge conflicts in pom.xml * Resolve Elm merge conflicts * [Rust Server] Fix up merge conflicts * Update samples * [Rust Server] Add debug log for rust-server-petstore.sh * update samples * update more samples * fix dart openapi-generator version * remove deprecated c# files * update meta codegen * fix port in pom.xml * fix port in sample * update jaxrs cxf version Co-authored-by: sunn <33183834+etherealjoy@users.noreply.github.com> Co-authored-by: dwlabcube <46682038+dwlabcube@users.noreply.github.com> Co-authored-by: Herve DARRITCHON Co-authored-by: Akihito Nakano Co-authored-by: Johnny Peck Co-authored-by: Michele Albano Co-authored-by: Jim Schubert Co-authored-by: Nikita Co-authored-by: Alexey Makhrov Co-authored-by: val Co-authored-by: Bruno Coelho <4brunu@users.noreply.github.com> Co-authored-by: Aleksandr Nekrasov Co-authored-by: Akira Tanimura Co-authored-by: Justin Co-authored-by: Justin Black Co-authored-by: Jiri Kuncar Co-authored-by: Hui Yu Co-authored-by: Yutaka Miyamae <48900426+yutaka0m@users.noreply.github.com> Co-authored-by: Mateusz Szychowski (Muttley) Co-authored-by: Jorge Rodriguez Co-authored-by: Gonzalo Co-authored-by: ChristianCiach Co-authored-by: Bodo Graumann Co-authored-by: Yuriy Belenko Co-authored-by: Daniel Klessing Co-authored-by: copypasta-g <53397163+copypasta-g@users.noreply.github.com> Co-authored-by: Mahdi Dibaiee Co-authored-by: Sebastien Rosset Co-authored-by: siada Co-authored-by: Samuel Hoffstaetter Co-authored-by: Esteban Gehring Co-authored-by: Jon Schoning Co-authored-by: Marcin Kubala Co-authored-by: anoohya-n <51289018+anoohya-n@users.noreply.github.com> Co-authored-by: Antoine Reilles Co-authored-by: Clemens Angermann Co-authored-by: Mostafa Moradian Co-authored-by: Adam Co-authored-by: Lars Hvam Co-authored-by: sullis Co-authored-by: Vikrant Balyan Co-authored-by: Matt Traynham Co-authored-by: LEZIER-S2 <60382243+LEZIER-S2@users.noreply.github.com> Co-authored-by: Thomas Enderle Co-authored-by: YishTish Co-authored-by: Slavek Kabrda Co-authored-by: Tomasz Prus Co-authored-by: Erica Kastner Co-authored-by: Richard Whitehouse Co-authored-by: valentin Bisson Co-authored-by: etherealjoy Co-authored-by: Hemant Zope <42613258+zhemant@users.noreply.github.com> Co-authored-by: Even André Fiskvik Co-authored-by: ehansen31 Co-authored-by: Timur Platonov Co-authored-by: Josh Burton Co-authored-by: Ilja leyberman <7ilya@gmx.de> Co-authored-by: Bouillie <34162532+Bouillie@users.noreply.github.com> Co-authored-by: Olivier Leonard Co-authored-by: tanmen Co-authored-by: Alex Buchkovsky Co-authored-by: Natan Laverde Co-authored-by: Nicholas Muesch Co-authored-by: jburgess <11861789+jburgess@users.noreply.github.com> Co-authored-by: emileonhardt <40421857+emileonhardt@users.noreply.github.com> Co-authored-by: Jacob Floyd Co-authored-by: Igor Quirino Co-authored-by: Nico König Co-authored-by: https://gitlab.com/selankon Co-authored-by: Shweta Shukla <25539662+shwetashukla@users.noreply.github.com> Co-authored-by: Shweta Shukla Co-authored-by: Bartek Kowalik Co-authored-by: Shinya Sugmoto <34866626+gasugesu@users.noreply.github.com> Co-authored-by: Artem Shubovych Co-authored-by: Artem Shubovych Co-authored-by: Jochen Schalanda Co-authored-by: Chr1st0ph Co-authored-by: Christoph Preißner Co-authored-by: Erikmolin Co-authored-by: erikmolin Co-authored-by: Nicolas Homble Co-authored-by: Sebastian <63457660+sebohdev@users.noreply.github.com> Co-authored-by: Sebastian Ohm Co-authored-by: chandra-gh <63366477+chandra-gh@users.noreply.github.com> Co-authored-by: Chandra Yalangi Co-authored-by: Fabian Freund Co-authored-by: Erik Timmers --- ApiClient.mustache | 72 +++++++- JSON.mustache | 15 +- ServerConfiguration.mustache | 58 +++++++ ServerVariable.mustache | 23 +++ beanValidationCore.mustache | 2 +- build.gradle.mustache | 9 +- build.sbt.mustache | 1 + libraries/feign/api.mustache | 4 +- libraries/feign/auth/OAuth.mustache | 6 +- libraries/feign/build.gradle.mustache | 8 +- libraries/feign/build.sbt.mustache | 14 +- libraries/feign/pom.mustache | 13 +- libraries/google-api-client/pom.mustache | 9 +- libraries/jersey2/ApiClient.mustache | 161 +++++++++++++++++- libraries/jersey2/api.mustache | 2 +- libraries/jersey2/build.gradle.mustache | 4 +- libraries/jersey2/build.sbt.mustache | 6 +- libraries/jersey2/pom.mustache | 7 +- libraries/microprofile/pojo.mustache | 6 +- libraries/native/ApiClient.mustache | 29 +++- libraries/native/api.mustache | 7 +- libraries/okhttp-gson/ApiClient.mustache | 47 ++++- .../okhttp-gson/auth/RetryingOAuth.mustache | 7 + libraries/okhttp-gson/build.gradle.mustache | 16 +- libraries/okhttp-gson/build.sbt.mustache | 15 +- libraries/okhttp-gson/pom.mustache | 38 +++-- libraries/rest-assured/build.gradle.mustache | 22 ++- libraries/rest-assured/build.sbt.mustache | 24 ++- libraries/rest-assured/pom.mustache | 86 +++++++--- libraries/resteasy/build.gradle.mustache | 4 +- libraries/resteasy/build.sbt.mustache | 6 +- libraries/resteasy/pom.mustache | 9 +- libraries/resttemplate/build.gradle.mustache | 4 +- libraries/resttemplate/pom.mustache | 9 +- libraries/retrofit/pom.mustache | 5 +- libraries/retrofit2/build.gradle.mustache | 4 +- libraries/retrofit2/build.sbt.mustache | 12 +- libraries/retrofit2/pom.mustache | 11 +- libraries/vertx/build.gradle.mustache | 4 +- libraries/vertx/pom.mustache | 9 +- libraries/webclient/ApiClient.mustache | 14 +- libraries/webclient/api.mustache | 73 +++++--- libraries/webclient/pom.mustache | 4 +- model.mustache | 2 +- model_test.mustache | 4 +- oneof_interface.mustache | 2 +- openapi.mustache | 1 + pojo.mustache | 64 +++---- pojo_doc.mustache | 18 +- pom.mustache | 27 ++- 50 files changed, 750 insertions(+), 247 deletions(-) create mode 100644 ServerConfiguration.mustache create mode 100644 ServerVariable.mustache create mode 100644 openapi.mustache diff --git a/ApiClient.mustache b/ApiClient.mustache index 1ae6c36f68a..8b71c1551e3 100644 --- a/ApiClient.mustache +++ b/ApiClient.mustache @@ -38,7 +38,9 @@ import java.util.Collections; import java.util.Map; import java.util.Map.Entry; import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Arrays; import java.util.ArrayList; import java.util.Date; import java.util.TimeZone; @@ -63,6 +65,33 @@ public class ApiClient { private Map defaultHeaderMap = new HashMap(); private Map defaultCookieMap = new HashMap(); private String basePath = "{{{basePath}}}"; + protected List servers = new ArrayList({{#servers}}{{#-first}}Arrays.asList( +{{/-first}} new ServerConfiguration( + "{{{url}}}", + "{{{description}}}{{^description}}No description provided{{/description}}", + new HashMap(){{#variables}}{{#-first}} {{ +{{/-first}} put("{{{name}}}", new ServerVariable( + "{{{description}}}{{^description}}No description provided{{/description}}", + "{{{defaultValue}}}", + new HashSet( + {{#enumValues}} + {{#-first}} + Arrays.asList( + {{/-first}} + "{{{.}}}"{{^-last}},{{/-last}} + {{#-last}} + ) + {{/-last}} + {{/enumValues}} + ) + )); + {{#-last}} + }}{{/-last}}{{/variables}} + ){{^-last}},{{/-last}} + {{#-last}} + ){{/-last}}{{/servers}}); + protected Integer serverIndex = 0; + protected Map serverVariables = null; private boolean debugging = false; private int connectionTimeout = 0; @@ -177,6 +206,33 @@ public class ApiClient { return this; } + public List getServers() { + return servers; + } + + public ApiClient setServers(List servers) { + this.servers = servers; + return this; + } + + public Integer getServerIndex() { + return serverIndex; + } + + public ApiClient setServerIndex(Integer serverIndex) { + this.serverIndex = serverIndex; + return this; + } + + public Map getServerVariables() { + return serverVariables; + } + + public ApiClient setServerVariables(Map serverVariables) { + this.serverVariables = serverVariables; + return this; + } + /** * Gets the status code of the previous request * @return Status code @@ -252,7 +308,7 @@ public class ApiClient { } throw new RuntimeException("No API key authentication configured!"); } - + /** * Helper method to set API key prefix for the first API key authentication. * @param apiKeyPrefix API key prefix @@ -626,8 +682,20 @@ public class ApiClient { * @return The full URL */ private String buildUrl(String path, List queryParams, List collectionQueryParams) { + String baseURL; + if (serverIndex != null) { + if (serverIndex < 0 || serverIndex >= servers.size()) { + throw new ArrayIndexOutOfBoundsException(String.format( + "Invalid index %d when selecting the host settings. Must be less than %d", serverIndex, servers.size() + )); + } + baseURL = servers.get(serverIndex).URL(serverVariables); + } else { + baseURL = basePath; + } + final StringBuilder url = new StringBuilder(); - url.append(basePath).append(path); + url.append(baseURL).append(path); if (queryParams != null && !queryParams.isEmpty()) { // support (constant) query string in `path`, e.g. "/posts?draft=1" diff --git a/JSON.mustache b/JSON.mustache index b951c3c555d..590ba386ea2 100644 --- a/JSON.mustache +++ b/JSON.mustache @@ -69,11 +69,11 @@ public class JSON { .registerTypeSelector({{classname}}.class, new TypeSelector() { @Override public Class getClassForElement(JsonElement readElement) { - Map classByDiscriminatorValue = new HashMap(); + Map classByDiscriminatorValue = new HashMap(); {{#mappedModels}} - classByDiscriminatorValue.put("{{mappingName}}".toUpperCase(Locale.ROOT), {{modelName}}.class); + classByDiscriminatorValue.put("{{mappingName}}"{{^discriminatorCaseSensitive}}.toUpperCase(Locale.ROOT){{/discriminatorCaseSensitive}}, {{modelName}}.class); {{/mappedModels}} - classByDiscriminatorValue.put("{{classname}}".toUpperCase(Locale.ROOT), {{classname}}.class); + classByDiscriminatorValue.put("{{name}}"{{^discriminatorCaseSensitive}}.toUpperCase(Locale.ROOT){{/discriminatorCaseSensitive}}, {{classname}}.class); return getClassByDiscriminator(classByDiscriminatorValue, getDiscriminatorValue(readElement, "{{{propertyBaseName}}}")); } @@ -97,8 +97,15 @@ public class JSON { return element.getAsString(); } + /** + * Returns the Java class that implements the OpenAPI schema for the specified discriminator value. + * + * @param classByDiscriminatorValue The map of discriminator values to Java classes. + * @param discriminatorValue The value of the OpenAPI discriminator in the input data. + * @return The Java class that implements the OpenAPI schema + */ private static Class getClassByDiscriminator(Map classByDiscriminatorValue, String discriminatorValue) { - Class clazz = (Class) classByDiscriminatorValue.get(discriminatorValue.toUpperCase(Locale.ROOT)); + Class clazz = (Class) classByDiscriminatorValue.get(discriminatorValue{{^discriminatorCaseSensitive}}.toUpperCase(Locale.ROOT){{/discriminatorCaseSensitive}}); if (null == clazz) { throw new IllegalArgumentException("cannot determine model class of name: <" + discriminatorValue + ">"); } diff --git a/ServerConfiguration.mustache b/ServerConfiguration.mustache new file mode 100644 index 00000000000..f976c542b19 --- /dev/null +++ b/ServerConfiguration.mustache @@ -0,0 +1,58 @@ +package {{invokerPackage}}; + +import java.util.Map; + +/** + * Representing a Server configuration. + */ +public class ServerConfiguration { + public String URL; + public String description; + public Map variables; + + /** + * @param URL A URL to the target host. + * @param description A describtion of the host designated by the URL. + * @param variables A map between a variable name and its value. The value is used for substitution in the server's URL template. + */ + public ServerConfiguration(String URL, String description, Map variables) { + this.URL = URL; + this.description = description; + this.variables = variables; + } + + /** + * Format URL template using given variables. + * + * @param variables A map between a variable name and its value. + * @return Formatted URL. + */ + public String URL(Map variables) { + String url = this.URL; + + // go through variables and replace placeholders + for (Map.Entry variable: this.variables.entrySet()) { + String name = variable.getKey(); + ServerVariable serverVariable = variable.getValue(); + String value = serverVariable.defaultValue; + + if (variables != null && variables.containsKey(name)) { + value = variables.get(name); + if (serverVariable.enumValues.size() > 0 && !serverVariable.enumValues.contains(value)) { + throw new RuntimeException("The variable " + name + " in the server URL has invalid value " + value + "."); + } + } + url = url.replaceAll("\\{" + name + "\\}", value); + } + return url; + } + + /** + * Format URL template using default server variables. + * + * @return Formatted URL. + */ + public String URL() { + return URL(null); + } +} diff --git a/ServerVariable.mustache b/ServerVariable.mustache new file mode 100644 index 00000000000..1978b1eb95e --- /dev/null +++ b/ServerVariable.mustache @@ -0,0 +1,23 @@ +package {{invokerPackage}}; + +import java.util.HashSet; + +/** + * Representing a Server Variable for server URL template substitution. + */ +public class ServerVariable { + public String description; + public String defaultValue; + public HashSet enumValues = null; + + /** + * @param description A description for the server variable. + * @param defaultValue The default value to use for substitution. + * @param enumValues An enumeration of string values to be used if the substitution options are from a limited set. + */ + public ServerVariable(String description, String defaultValue, HashSet enumValues) { + this.description = description; + this.defaultValue = defaultValue; + this.enumValues = enumValues; + } +} diff --git a/beanValidationCore.mustache b/beanValidationCore.mustache index d107c037b9a..ae26b2739f1 100644 --- a/beanValidationCore.mustache +++ b/beanValidationCore.mustache @@ -17,4 +17,4 @@ isInteger set isLong set }}{{#isLong}}{{#minimum}} @Min({{minimum}}L){{/minimum}}{{#maximum}} @Max({{maximum}}L){{/maximum}}{{/isLong}}{{! Not Integer, not Long => we have a decimal value! -}}{{^isInteger}}{{^isLong}}{{#minimum}} @DecimalMin({{#exclusiveMinimum}}value={{/exclusiveMinimum}}"{{minimum}}"{{#exclusiveMinimum}},inclusive=false{{/exclusiveMinimum}}){{/minimum}}{{#maximum}} @DecimalMax({{#exclusiveMinimum}}value={{/exclusiveMinimum}}"{{maximum}}"{{#exclusiveMinimum}},inclusive=false{{/exclusiveMinimum}}){{/maximum}}{{/isLong}}{{/isInteger}} \ No newline at end of file +}}{{^isInteger}}{{^isLong}}{{#minimum}} @DecimalMin({{#exclusiveMinimum}}value={{/exclusiveMinimum}}"{{minimum}}"{{#exclusiveMinimum}},inclusive=false{{/exclusiveMinimum}}){{/minimum}}{{#maximum}} @DecimalMax({{#exclusiveMaximum}}value={{/exclusiveMaximum}}"{{maximum}}"{{#exclusiveMaximum}},inclusive=false{{/exclusiveMaximum}}){{/maximum}}{{/isLong}}{{/isInteger}} \ No newline at end of file diff --git a/build.gradle.mustache b/build.gradle.mustache index 69707eadc16..c1bf968dbac 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -136,9 +136,12 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.10.1" - jackson_databind_version = "2.10.1" + jackson_version = "2.10.3" + jackson_databind_version = "2.10.3" jackson_databind_nullable_version = "0.2.1" + {{#threetenbp}} + jackson_threetenbp_version = "2.9.10" + {{/threetenbp}} jersey_version = "1.19.4" jodatime_version = "2.9.9" junit_version = "4.13" @@ -161,7 +164,7 @@ dependencies { compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_version" + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threetenbp_version" {{/threetenbp}} {{^java8}} compile "com.brsanthu:migbase64:2.2" diff --git a/build.sbt.mustache b/build.sbt.mustache index e69de29bb2d..464090415c4 100644 --- a/build.sbt.mustache +++ b/build.sbt.mustache @@ -0,0 +1 @@ +# TODO diff --git a/libraries/feign/api.mustache b/libraries/feign/api.mustache index 238079ca27c..cff48fcd2e4 100644 --- a/libraries/feign/api.mustache +++ b/libraries/feign/api.mustache @@ -42,7 +42,7 @@ public interface {{classname}} extends ApiClient.Api { "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{#hasMore}}, {{/hasMore}}{{/headerParams}} }) - {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isBodyParam}}{{^legacyDates}}@Param("{{baseName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{baseName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{baseName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); {{#hasQueryParams}} /** @@ -80,7 +80,7 @@ public interface {{classname}} extends ApiClient.Api { "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{#hasMore}}, {{/hasMore}}{{/headerParams}} }) - {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isQueryParam}}{{^isBodyParam}}{{^legacyDates}}@Param("{{baseName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{baseName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}, {{/isQueryParam}}{{/allParams}}@QueryMap(encoded=true) Map queryParams); + {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isQueryParam}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{baseName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}, {{/isQueryParam}}{{/allParams}}@QueryMap(encoded=true) Map queryParams); /** * A convenience class for generating query parameters for the diff --git a/libraries/feign/auth/OAuth.mustache b/libraries/feign/auth/OAuth.mustache index 25b1f193ba9..feefdb93981 100644 --- a/libraries/feign/auth/OAuth.mustache +++ b/libraries/feign/auth/OAuth.mustache @@ -83,20 +83,20 @@ public class OAuth implements RequestInterceptor { } // If first time, get the token if (expirationTimeMillis == null || System.currentTimeMillis() >= expirationTimeMillis) { - updateAccessToken(); + updateAccessToken(template); } if (getAccessToken() != null) { template.header("Authorization", "Bearer " + getAccessToken()); } } - public synchronized void updateAccessToken() { + public synchronized void updateAccessToken(RequestTemplate template) { OAuthJSONAccessTokenResponse accessTokenResponse; try { accessTokenResponse = oauthClient.accessToken(tokenRequestBuilder.buildBodyMessage()); } catch (Exception e) { {{#useFeign10}} - throw new RetryableException(0, e.getMessage(), HttpMethod.POST, e, null); + throw new RetryableException(0, e.getMessage(), HttpMethod.POST, e, null, template.request()); {{/useFeign10}} {{^useFeign10}} throw new RetryableException(e.getMessage(), e,null); diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index 69170a03177..2a6c4c79fbc 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -120,14 +120,14 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.10.1" - jackson_databind_version = "2.10.1" + jackson_version = "2.10.3" + jackson_databind_version = "2.10.3" jackson_databind_nullable_version = "0.2.1" {{#threetenbp}} jackson_threetenbp_version = "2.9.10" {{/threetenbp}} - feign_version = "{{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" - feign_form_version = "2.1.0" + feign_version = "{{#useFeign10}}10.7.4{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" + feign_form_version = "{{#useFeign10}}3.8.0{{/useFeign10}}{{^useFeign10}}2.1.0{{/useFeign10}}" junit_version = "4.13" oltu_version = "1.0.1" } diff --git a/libraries/feign/build.sbt.mustache b/libraries/feign/build.sbt.mustache index 907b7bd4d27..8fa1d345b26 100644 --- a/libraries/feign/build.sbt.mustache +++ b/libraries/feign/build.sbt.mustache @@ -10,13 +10,13 @@ lazy val root = (project in file(".")). resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( "io.swagger" % "swagger-annotations" % "1.5.22" % "compile", - "io.github.openfeign" % "feign-core" % "{{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", - "io.github.openfeign" % "feign-jackson" % "{{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", - "io.github.openfeign" % "feign-slf4j" % "{{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", - "io.github.openfeign.form" % "feign-form" % "2.1.0" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.1" % "compile", + "io.github.openfeign" % "feign-core" % "{{#useFeign10}}10.7.4{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", + "io.github.openfeign" % "feign-jackson" % "{{#useFeign10}}10.7.4{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", + "io.github.openfeign" % "feign-slf4j" % "{{#useFeign10}}10.7.4{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", + "io.github.openfeign.form" % "feign-form" % "{{#useFeign10}}3.8.0{{/useFeign10}}{{^useFeign10}}2.1.0{{/useFeign10}}" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", "com.fasterxml.jackson.datatype" % "jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}" % "2.9.10" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index e73e45de1b3..86f6f397781 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -142,7 +142,10 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.4 + 3.1.1 + + none + attach-javadocs @@ -312,11 +315,11 @@ ${java.version} ${java.version} 1.5.21 - {{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}} - 2.1.0 - 2.10.1 + {{#useFeign10}}10.7.4{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}} + {{#useFeign10}}3.8.0{{/useFeign10}}{{^useFeign10}}2.1.0{{/useFeign10}} + 2.10.3 0.2.1 - 2.10.1 + 2.10.3 {{#threetenbp}} 2.9.10 {{/threetenbp}} diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index 5e3c04fe93b..4d6a8c5e161 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -163,7 +163,10 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.4 + 3.1.1 + + none + attach-javadocs @@ -306,8 +309,8 @@ 1.5.22 1.30.2 2.25.1 - 2.10.1 - 2.10.1 + 2.10.3 + 2.10.3 0.2.1 {{#joda}} 2.9.9 diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 95fb8093bc3..0111a24c4da 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -37,7 +37,9 @@ import java.util.Collections; import java.util.Map; import java.util.Map.Entry; import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Arrays; import java.util.ArrayList; import java.util.Date; import java.util.TimeZone; @@ -55,6 +57,7 @@ import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; import {{invokerPackage}}.auth.HttpBearerAuth; import {{invokerPackage}}.auth.ApiKeyAuth; + {{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} @@ -64,6 +67,74 @@ public class ApiClient { protected Map defaultHeaderMap = new HashMap(); protected Map defaultCookieMap = new HashMap(); protected String basePath = "{{{basePath}}}"; + protected List servers = new ArrayList({{#servers}}{{#-first}}Arrays.asList( +{{/-first}} new ServerConfiguration( + "{{{url}}}", + "{{{description}}}{{^description}}No description provided{{/description}}", + new HashMap(){{#variables}}{{#-first}} {{ +{{/-first}} put("{{{name}}}", new ServerVariable( + "{{{description}}}{{^description}}No description provided{{/description}}", + "{{{defaultValue}}}", + new HashSet( + {{#enumValues}} + {{#-first}} + Arrays.asList( + {{/-first}} + "{{{.}}}"{{^-last}},{{/-last}} + {{#-last}} + ) + {{/-last}} + {{/enumValues}} + ) + )); + {{#-last}} + }}{{/-last}}{{/variables}} + ){{^-last}},{{/-last}} + {{#-last}} + ){{/-last}}{{/servers}}); + protected Integer serverIndex = 0; + protected Map serverVariables = null; + protected Map> operationServers = new HashMap>() {{ + {{#apiInfo}} + {{#apis}} + {{#operations}} + {{#operation}} + {{#servers}} + {{#-first}} + put("{{{classname}}}.{{{operationId}}}", new ArrayList(Arrays.asList( + {{/-first}} + new ServerConfiguration( + "{{{url}}}", + "{{{description}}}{{^description}}No description provided{{/description}}", + new HashMap(){{#variables}}{{#-first}} {{ +{{/-first}} put("{{{name}}}", new ServerVariable( + "{{{description}}}{{^description}}No description provided{{/description}}", + "{{{defaultValue}}}", + new HashSet( + {{#enumValues}} + {{#-first}} + Arrays.asList( + {{/-first}} + "{{{.}}}"{{^-last}},{{/-last}} + {{#-last}} + ) + {{/-last}} + {{/enumValues}} + ) + )); + {{#-last}} + }}{{/-last}}{{/variables}} + ){{^-last}},{{/-last}} + {{#-last}} + )));{{/-last}} + {{/servers}} + {{/operation}} + {{/operations}} + {{/apis}} + {{/apiInfo}} + }}; + protected Map operationServerIndex = new HashMap(); + protected Map> operationServerVariables = new HashMap>(); protected boolean debugging = false; protected int connectionTimeout = 0; private int readTimeout = 0; @@ -73,6 +144,7 @@ public class ApiClient { protected String tempFolderPath = null; protected Map authentications; + protected Map authenticationLookup; protected DateFormat dateFormat; @@ -93,6 +165,10 @@ public class ApiClient { authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} // Prevent the authentications from being modified. authentications = Collections.unmodifiableMap(authentications); + + // Setup authentication lookup (key: authentication alias, value: authentication name) + authenticationLookup = new HashMap();{{#authMethods}}{{#vendorExtensions.x-auth-id-alias}} + authenticationLookup.put("{{name}}", "{{.}}");{{/vendorExtensions.x-auth-id-alias}}{{/authMethods}} } /** @@ -121,6 +197,33 @@ public class ApiClient { return this; } + public List getServers() { + return servers; + } + + public ApiClient setServers(List servers) { + this.servers = servers; + return this; + } + + public Integer getServerIndex() { + return serverIndex; + } + + public ApiClient setServerIndex(Integer serverIndex) { + this.serverIndex = serverIndex; + return this; + } + + public Map getServerVariables() { + return serverVariables; + } + + public ApiClient setServerVariables(Map serverVariables) { + this.serverVariables = serverVariables; + return this; + } + /** * Get authentications (key: authentication name, value: authentication). * @return Map of authentication object @@ -181,6 +284,25 @@ public class ApiClient { throw new RuntimeException("No API key authentication configured!"); } + /** + * Helper method to configure authentications which respects aliases of API keys. + * + * @param secrets Hash map from authentication name to its secret. + */ + public void configureApiKeys(HashMap secrets) { + for (Map.Entry authEntry : authentications.entrySet()) { + Authentication auth = authEntry.getValue(); + if (auth instanceof ApiKeyAuth) { + String name = authEntry.getKey(); + // respect x-auth-id-alias property + name = authenticationLookup.getOrDefault(name, name); + if (secrets.containsKey(name)) { + ((ApiKeyAuth) auth).setApiKey(secrets.get(name)); + } + } + } + } + /** * Helper method to set API key prefix for the first API key authentication. * @param apiKeyPrefix API key prefix @@ -670,6 +792,7 @@ public class ApiClient { * Invoke API by sending HTTP request with the given options. * * @param Type + * @param operation The qualified name of the operation * @param path The sub-path of the HTTP URL * @param method The request method, one of "GET", "POST", "PUT", "HEAD" and "DELETE" * @param queryParams The query parameters @@ -684,12 +807,36 @@ public class ApiClient { * @return The response body in type of string * @throws ApiException API exception */ - public ApiResponse invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { + public ApiResponse invokeAPI(String operation, String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); - // Not using `.target(this.basePath).path(path)` below, + // Not using `.target(targetURL).path(path)` below, // to support (constant) query string in `path`, e.g. "/posts?draft=1" - WebTarget target = httpClient.target(this.basePath + path); + String targetURL; + if (serverIndex != null) { + Integer index; + List serverConfigurations; + Map variables; + + if (operationServers.containsKey(operation)) { + index = operationServerIndex.getOrDefault(operation, serverIndex); + variables = operationServerVariables.getOrDefault(operation, serverVariables); + serverConfigurations = operationServers.get(operation); + } else { + index = serverIndex; + variables = serverVariables; + serverConfigurations = servers; + } + if (index < 0 || index >= serverConfigurations.size()) { + throw new ArrayIndexOutOfBoundsException(String.format( + "Invalid index %d when selecting the host settings. Must be less than %d", index, serverConfigurations.size() + )); + } + targetURL = serverConfigurations.get(index).URL(variables) + path; + } else { + targetURL = this.basePath + path; + } + WebTarget target = httpClient.target(targetURL); if (queryParams != null) { for (Pair queryParam : queryParams) { @@ -793,6 +940,14 @@ public class ApiClient { } } + /** + * @deprecated Add qualified name of the operation as a first parameter. + */ + @Deprecated + public ApiResponse invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { + return invokeAPI(null, path, method, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType); + } + /** * Build the Client used to make HTTP requests. * @param debugging Debug setting diff --git a/libraries/jersey2/api.mustache b/libraries/jersey2/api.mustache index 3950d7a2af3..4a2e61afe8e 100644 --- a/libraries/jersey2/api.mustache +++ b/libraries/jersey2/api.mustache @@ -151,7 +151,7 @@ public class {{classname}} { String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; {{#returnType}}GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {};{{/returnType}} - return apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, {{#returnType}}localVarReturnType{{/returnType}}{{^returnType}}null{{/returnType}}); + return apiClient.invokeAPI("{{classname}}.{{operationId}}", localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, {{#returnType}}localVarReturnType{{/returnType}}{{^returnType}}null{{/returnType}}); } {{#vendorExtensions.x-group-parameters}} diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index 30aa47428cb..cdb451adb34 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -119,8 +119,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.10.1" - jackson_databind_version = "2.10.1" + jackson_version = "2.10.3" + jackson_databind_version = "2.10.3" jackson_databind_nullable_version = "0.2.1" {{#supportJava6}} jersey_version = "2.6" diff --git a/libraries/jersey2/build.sbt.mustache b/libraries/jersey2/build.sbt.mustache index 7e2dc832a2c..abb91ecdc99 100644 --- a/libraries/jersey2/build.sbt.mustache +++ b/libraries/jersey2/build.sbt.mustache @@ -13,9 +13,9 @@ lazy val root = (project in file(".")). "org.glassfish.jersey.core" % "jersey-client" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, "org.glassfish.jersey.media" % "jersey-media-multipart" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, "org.glassfish.jersey.media" % "jersey-media-json-jackson" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", {{#joda}} "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.10" % "compile", {{/joda}} diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index e9fc8ba3942..9bd8925f001 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -163,7 +163,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.4 + 3.1.1 attach-javadocs @@ -173,6 +173,7 @@ + none http.response.details @@ -360,8 +361,8 @@ 2.5 3.6 {{/supportJava6}} - 2.10.1 - 2.10.1 + 2.10.3 + 2.10.3 0.2.1 {{#threetenbp}} 2.9.10 diff --git a/libraries/microprofile/pojo.mustache b/libraries/microprofile/pojo.mustache index a7d3ddb77c1..4ded8e94e2e 100644 --- a/libraries/microprofile/pojo.mustache +++ b/libraries/microprofile/pojo.mustache @@ -57,9 +57,9 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}}{{#serializ * @return {{name}} **/ @JsonbProperty("{{baseName}}") -{{#vendorExtensions.extraAnnotation}} - {{{vendorExtensions.extraAnnotation}}} -{{/vendorExtensions.extraAnnotation}} +{{#vendorExtensions.x-extra-annotation}} + {{{vendorExtensions.x-extra-annotation}}} +{{/vendorExtensions.x-extra-annotation}} {{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} {{#isEnum}}{{^isListContainer}}{{^isMapContainer}}public {{dataType}} {{getter}}() { if ({{name}} == null) { return null; diff --git a/libraries/native/ApiClient.mustache b/libraries/native/ApiClient.mustache index 6bcad4a2f3f..fb83d919b93 100644 --- a/libraries/native/ApiClient.mustache +++ b/libraries/native/ApiClient.mustache @@ -8,10 +8,12 @@ import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.openapitools.jackson.nullable.JsonNullableModule; +import java.io.InputStream; import java.net.URI; import java.net.URLEncoder; import java.net.http.HttpClient; import java.net.http.HttpRequest; +import java.net.http.HttpResponse; import java.nio.charset.Charset; import java.time.Duration; import java.util.Collection; @@ -46,6 +48,7 @@ public class ApiClient { private int port; private String basePath; private Consumer interceptor; + private Consumer> responseInterceptor; private Duration readTimeout; private static String valueToString(Object value) { @@ -161,6 +164,7 @@ public class ApiClient { basePath = baseURI.getRawPath(); interceptor = null; readTimeout = null; + responseInterceptor = null; } /** @@ -292,6 +296,29 @@ public class ApiClient { return interceptor; } + /** + * Set a custom response interceptor. + * + *

This is useful for logging, monitoring or extraction of header variables

+ * + * @param interceptor A function invoked before creating each request. A value + * of null resets the interceptor to a no-op. + * @return This object. + */ + public ApiClient setResponseInterceptor(Consumer> interceptor) { + this.responseInterceptor = interceptor; + return this; + } + + /** + * Get the custom response interceptor. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer> getResponseInterceptor() { + return responseInterceptor; + } + /** * Set the read timeout for the http client. * @@ -307,7 +334,7 @@ public class ApiClient { this.readTimeout = readTimeout; return this; } - + /** * Get the read timeout that was set. * diff --git a/libraries/native/api.mustache b/libraries/native/api.mustache index 8c545a015f4..4c4848ca480 100644 --- a/libraries/native/api.mustache +++ b/libraries/native/api.mustache @@ -36,7 +36,8 @@ public class {{classname}} { private final String memberVarBaseUri; private final Consumer memberVarInterceptor; private final Duration memberVarReadTimeout; - + private final Consumer> memberVarResponseInterceptor; + public {{classname}}() { this(new ApiClient()); } @@ -47,6 +48,7 @@ public class {{classname}} { memberVarBaseUri = apiClient.getBaseUri(); memberVarInterceptor = apiClient.getRequestInterceptor(); memberVarReadTimeout = apiClient.getReadTimeout(); + memberVarResponseInterceptor = apiClient.getResponseInterceptor(); } {{#operation}} @@ -138,6 +140,9 @@ public class {{classname}} { HttpResponse localVarResponse = memberVarHttpClient.send( localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } if (localVarResponse.statusCode()/ 100 != 2) { throw new ApiException(localVarResponse.statusCode(), "{{operationId}} call received non-success response", diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index 3856ddf8c19..3969c08d391 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -30,6 +30,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.lang.reflect.Type; +import java.net.URI; import java.net.URLConnection; import java.net.URLEncoder; import java.security.GeneralSecurityException; @@ -90,6 +91,7 @@ public class ApiClient { */ public ApiClient() { init(); + initHttpClient(); // Setup authentications (key: authentication name, value: authentication).{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} @@ -121,16 +123,40 @@ public class ApiClient { * Constructor for ApiClient to support access token retry on 401/403 configured with client ID, secret, and additional parameters */ public ApiClient(String clientId, String clientSecret, Map parameters) { + this(null, clientId, clientSecret, parameters); + } + + /* + * Constructor for ApiClient to support access token retry on 401/403 configured with base path, client ID, secret, and additional parameters + */ + public ApiClient(String basePath, String clientId, String clientSecret, Map parameters) { init(); + if (basePath != null) { + this.basePath = basePath; + } {{#hasOAuthMethods}} - RetryingOAuth retryingOAuth = new RetryingOAuth("{{tokenUrl}}", clientId, OAuthFlow.{{flow}}, clientSecret, parameters); + String tokenUrl = "{{tokenUrl}}"; + if (!"".equals(tokenUrl) && !URI.create(tokenUrl).isAbsolute()) { + URI uri = URI.create(getBasePath()); + tokenUrl = uri.getScheme() + ":" + + (uri.getAuthority() != null ? "//" + uri.getAuthority() : "") + + tokenUrl; + if (!URI.create(tokenUrl).isAbsolute()) { + throw new IllegalArgumentException("OAuth2 token URL must be an absolute URL"); + } + } + RetryingOAuth retryingOAuth = new RetryingOAuth(tokenUrl, clientId, OAuthFlow.{{flow}}, clientSecret, parameters); authentications.put( "{{name}}", retryingOAuth ); - httpClient.interceptors().add(retryingOAuth); + initHttpClient(Collections.singletonList(retryingOAuth)); {{/hasOAuthMethods}} + // Setup authentications (key: authentication name, value: authentication).{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{/authMethods}} // Prevent the authentications from being modified. authentications = Collections.unmodifiableMap(authentications); @@ -139,16 +165,25 @@ public class ApiClient { {{/-first}} {{/oauthMethods}} {{/hasOAuthMethods}} - private void init() { + private void initHttpClient() { + initHttpClient(Collections.emptyList()); + } + + private void initHttpClient(List interceptors) { OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.addNetworkInterceptor(getProgressInterceptor()); - httpClient = builder.build(); - + for (Interceptor interceptor: interceptors) { + builder.addInterceptor(interceptor); + } {{#useGzipFeature}} // Enable gzip request compression - httpClient.interceptors().add(new GzipRequestInterceptor()); + builder.addInterceptor(new GzipRequestInterceptor()); {{/useGzipFeature}} + httpClient = builder.build(); + } + + private void init() { verifyingSsl = true; json = new JSON(); diff --git a/libraries/okhttp-gson/auth/RetryingOAuth.mustache b/libraries/okhttp-gson/auth/RetryingOAuth.mustache index 94f1d6afcf9..3ddacedb70e 100644 --- a/libraries/okhttp-gson/auth/RetryingOAuth.mustache +++ b/libraries/okhttp-gson/auth/RetryingOAuth.mustache @@ -36,6 +36,13 @@ public class RetryingOAuth extends OAuth implements Interceptor { this(new OkHttpClient(), tokenRequestBuilder); } + /** + @param tokenUrl The token URL to be used for this OAuth2 flow. + Applicable to the following OAuth2 flows: "password", "clientCredentials" and "authorizationCode". + The value must be an absolute URL. + @param clientId The OAuth2 client ID for the "clientCredentials" flow. + @param clientSecret The OAuth2 client secret for the "clientCredentials" flow. + */ public RetryingOAuth( String tokenUrl, String clientId, diff --git a/libraries/okhttp-gson/build.gradle.mustache b/libraries/okhttp-gson/build.gradle.mustache index 304b00a445a..91913276775 100644 --- a/libraries/okhttp-gson/build.gradle.mustache +++ b/libraries/okhttp-gson/build.gradle.mustache @@ -68,7 +68,7 @@ if(hasProperty('target') && target == 'android') { } dependencies { - provided 'javax.annotation:jsr250-api:1.0' + provided 'javax.annotation:javax.annotation-api:1.3.2' } } @@ -126,21 +126,21 @@ if(hasProperty('target') && target == 'android') { } dependencies { - compile 'io.swagger:swagger-annotations:1.5.22' + compile 'io.swagger:swagger-annotations:1.5.24' compile "com.google.code.findbugs:jsr305:3.0.2" - compile 'com.squareup.okhttp3:okhttp:3.14.2' - compile 'com.squareup.okhttp3:logging-interceptor:3.14.2' - compile 'com.google.code.gson:gson:2.8.5' - compile 'io.gsonfire:gson-fire:1.8.3' + compile 'com.squareup.okhttp3:okhttp:3.14.7' + compile 'com.squareup.okhttp3:logging-interceptor:3.14.7' + compile 'com.google.code.gson:gson:2.8.6' + compile 'io.gsonfire:gson-fire:1.8.4' {{#hasOAuthMethods}} compile group: 'org.apache.oltu.oauth2', name: 'org.apache.oltu.oauth2.client', version: '1.0.1' {{/hasOAuthMethods}} - compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.9' + compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.10' {{#joda}} compile 'joda-time:joda-time:2.9.9' {{/joda}} {{#threetenbp}} - compile 'org.threeten:threetenbp:1.4.0' + compile 'org.threeten:threetenbp:1.4.3' {{/threetenbp}} testCompile 'junit:junit:4.13' } diff --git a/libraries/okhttp-gson/build.sbt.mustache b/libraries/okhttp-gson/build.sbt.mustache index 43907462202..7c137589e37 100644 --- a/libraries/okhttp-gson/build.sbt.mustache +++ b/libraries/okhttp-gson/build.sbt.mustache @@ -9,11 +9,11 @@ lazy val root = (project in file(".")). publishArtifact in (Compile, packageDoc) := false, resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( - "io.swagger" % "swagger-annotations" % "1.5.22", - "com.squareup.okhttp3" % "okhttp" % "3.14.2", - "com.squareup.okhttp3" % "logging-interceptor" % "3.14.2", - "com.google.code.gson" % "gson" % "2.8.5", - "org.apache.commons" % "commons-lang3" % "3.9", + "io.swagger" % "swagger-annotations" % "1.5.24", + "com.squareup.okhttp3" % "okhttp" % "3.14.7", + "com.squareup.okhttp3" % "logging-interceptor" % "3.14.7", + "com.google.code.gson" % "gson" % "2.8.6", + "org.apache.commons" % "commons-lang3" % "3.10", {{#hasOAuthMethods}} "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1", {{/hasOAuthMethods}} @@ -21,10 +21,11 @@ lazy val root = (project in file(".")). "joda-time" % "joda-time" % "2.9.9" % "compile", {{/joda}} {{#threetenbp}} - "org.threeten" % "threetenbp" % "1.4.0" % "compile", + "org.threeten" % "threetenbp" % "1.4.3" % "compile", {{/threetenbp}} "io.gsonfire" % "gson-fire" % "1.8.3" % "compile", - "javax.annotation" % "jsr250-api" % "1.0" % "compile", + "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", + "com.google.code.findbugs" % "jsr305" % "3.0.2" % "compile", "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index e4c05f4151d..b6d67f28350 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -40,6 +40,20 @@ + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + true + 128m + 512m + + -Xlint:all + -J-Xss4m + + + org.apache.maven.plugins maven-enforcer-plugin @@ -63,7 +77,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.12 + 3.0.0-M4 @@ -73,7 +87,7 @@ -Xms512m -Xmx1500m methods - pertest + 10 @@ -142,7 +156,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.4 + 3.1.1 attach-javadocs @@ -152,6 +166,7 @@ + none http.response.details @@ -292,7 +307,7 @@ {{/parcelableModel}} javax.annotation - jsr250-api + javax.annotation-api ${javax-annotation-version} @@ -307,19 +322,18 @@ {{#supportJava6}}1.6{{/supportJava6}}{{^supportJava6}}{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}{{/supportJava6}} ${java.version} ${java.version} - 1.8.3 - 1.5.22 - 3.14.2 - 2.8.5 - 3.9 + 1.8.4 + 1.5.24 + 3.14.7 + 2.8.6 + 3.10 {{#joda}} 2.9.9 {{/joda}} {{#threetenbp}} - 1.4.0 + 1.4.3 {{/threetenbp}} - 1.0.0 - 1.0 + 1.3.2 4.13 UTF-8 diff --git a/libraries/rest-assured/build.gradle.mustache b/libraries/rest-assured/build.gradle.mustache index b04e53f1e96..640ad1cd18c 100644 --- a/libraries/rest-assured/build.gradle.mustache +++ b/libraries/rest-assured/build.gradle.mustache @@ -96,24 +96,24 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.21" - rest_assured_version = "4.0.0" + rest_assured_version = "4.3.0" junit_version = "4.13" {{#jackson}} - jackson_version = "2.10.1" - jackson_databind_version = "2.9.10" + jackson_version = "2.10.3" + jackson_databind_version = "2.10.3" jackson_databind_nullable_version = 0.2.1 {{/jackson}} {{#gson}} - gson_version = "2.8.5" - gson_fire_version = "1.8.3" + gson_version = "2.8.6" + gson_fire_version = "1.8.4" {{/gson}} {{#joda}} - jodatime_version = "2.9.9" + jodatime_version = "2.10.5" {{/joda}} {{#threetenbp}} - threetenbp_version = "1.4.0" + threetenbp_version = "1.4.3" {{/threetenbp}} - okio_version = "1.13.0" + okio_version = "1.17.5" } dependencies { @@ -138,5 +138,11 @@ dependencies { compile "org.threeten:threetenbp:$threetenbp_version" {{/threetenbp}} compile "com.squareup.okio:okio:$okio_version" +{{#useBeanValidation}} + compile "javax.validation:validation-api:2.0.1.Final" +{{/useBeanValidation}} +{{#performBeanValidation}} + compile "org.hibernate:hibernate-validator:6.0.19.Final" +{{/performBeanValidation}} testCompile "junit:junit:$junit_version" } diff --git a/libraries/rest-assured/build.sbt.mustache b/libraries/rest-assured/build.sbt.mustache index 71f2eaeeba2..77f8af4f436 100644 --- a/libraries/rest-assured/build.sbt.mustache +++ b/libraries/rest-assured/build.sbt.mustache @@ -10,23 +10,29 @@ lazy val root = (project in file(".")). resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( "io.swagger" % "swagger-annotations" % "1.5.21", - "io.rest-assured" % "scala-support" % "4.0.0", + "io.rest-assured" % "scala-support" % "4.3.0", {{#jackson}} - "com.fasterxml.jackson.core" % "jackson-core" % "2.9.9" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.9" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", {{/jackson}} {{#gson}} - "com.google.code.gson" % "gson" % "2.8.5", - "io.gsonfire" % "gson-fire" % "1.8.3" % "compile", + "com.google.code.gson" % "gson" % "2.8.6", + "io.gsonfire" % "gson-fire" % "1.8.4" % "compile", {{/gson}} {{#joda}} - "joda-time" % "joda-time" % "2.9.9" % "compile", + "joda-time" % "joda-time" % "2.10.5" % "compile", {{/joda}} {{#threetenbp}} - "org.threeten" % "threetenbp" % "1.4.0" % "compile", + "org.threeten" % "threetenbp" % "1.4.3" % "compile", {{/threetenbp}} - "com.squareup.okio" % "okio" % "1.13.0" % "compile", + "com.squareup.okio" % "okio" % "1.17.5" % "compile", +{{#useBeanValidation}} + "javax.validation" % "validation-api" % "2.0.1.Final" % "compile", +{{/useBeanValidation}} +{{#performBeanValidation}} + "org.hibernate" % "hibernate-validator" "6.0.19.Final" % "compile", +{{/performBeanValidation}} "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) diff --git a/libraries/rest-assured/pom.mustache b/libraries/rest-assured/pom.mustache index 9c49fb07774..2e68695d431 100644 --- a/libraries/rest-assured/pom.mustache +++ b/libraries/rest-assured/pom.mustache @@ -43,7 +43,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.0.0-M1 + 3.0.0-M3 enforce-maven @@ -53,7 +53,7 @@ - 2.2.0 + 3.0.5 @@ -63,7 +63,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.12 + 2.22.2 @@ -71,9 +71,8 @@ conf/log4j.properties - -Xms512m -Xmx1500m - methods - pertest + false + 1C @@ -111,6 +110,7 @@ org.codehaus.mojo build-helper-maven-plugin + 3.1.0 add_sources @@ -141,7 +141,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.6.1 + 3.8.1 1.8 1.8 @@ -150,7 +150,10 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.4 + 3.2.0 + + none + attach-javadocs @@ -163,7 +166,7 @@ org.apache.maven.plugins maven-source-plugin - 2.2.1 + 3.2.0 attach-sources @@ -184,7 +187,7 @@ org.apache.maven.plugins maven-gpg-plugin - 1.5 + 1.6 sign-artifacts @@ -200,6 +203,20 @@ + {{#jackson}} + + + + com.fasterxml.jackson + jackson-bom + ${jackson-version} + pom + import + + + + {{/jackson}} + io.swagger @@ -212,6 +229,14 @@ jsr305 3.0.2 + {{^hideGenerationTimestamp}} + + javax.annotation + javax.annotation-api + 1.3.2 + provided + + {{/hideGenerationTimestamp}} io.rest-assured rest-assured @@ -250,17 +275,14 @@ com.fasterxml.jackson.core jackson-core - ${jackson-version} com.fasterxml.jackson.core jackson-annotations - ${jackson-version} com.fasterxml.jackson.core jackson-databind - ${jackson-databind-version} org.openapitools @@ -271,21 +293,18 @@ com.fasterxml.jackson.dataformat jackson-dataformat-xml - ${jackson-version} {{/withXml}} {{#joda}} com.fasterxml.jackson.datatype jackson-datatype-joda - ${jackson-version} {{/joda}} {{#java8}} com.fasterxml.jackson.datatype jackson-datatype-jsr310 - ${jackson-version} {{/java8}} {{#threetenbp}} @@ -301,6 +320,23 @@ okio ${okio-version} + {{#useBeanValidation}} + + + javax.validation + validation-api + 2.0.1.Final + provided + + {{/useBeanValidation}} + {{#performBeanValidation}} + + + org.hibernate + hibernate-validator + 6.0.19.Final + + {{/performBeanValidation}} junit @@ -312,25 +348,23 @@ UTF-8 1.5.21 - 4.0.0 - 2.8.5 - 1.8.3 - 1.0.0 + 4.3.0 + 2.8.6 + 1.8.4 {{#joda}} - 2.9.9 + 2.10.5 {{/joda}} {{#threetenbp}} - 1.4.0 + 1.4.3 {{/threetenbp}} {{#jackson}} - 2.10.1 - 2.9.10 + 2.10.3 0.2.1 {{#threetenbp}} - 2.9.10 + 2.10.0 {{/threetenbp}} {{/jackson}} - 1.13.0 + 1.17.5 4.13 diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index 59a0970f358..89c6fb24ee4 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -119,8 +119,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.10.1" - jackson_databind_version = "2.10.1" + jackson_version = "2.10.3" + jackson_databind_version = "2.10.3" jackson_databind_nullable_version = "0.2.1" threetenbp_version = "2.9.10" resteasy_version = "3.1.3.Final" diff --git a/libraries/resteasy/build.sbt.mustache b/libraries/resteasy/build.sbt.mustache index 936c4141f8f..351c072616f 100644 --- a/libraries/resteasy/build.sbt.mustache +++ b/libraries/resteasy/build.sbt.mustache @@ -13,9 +13,9 @@ lazy val root = (project in file(".")). "org.jboss.resteasy" % "resteasy-client" % "3.1.3.Final" % "compile", "org.jboss.resteasy" % "resteasy-multipart-provider" % "3.1.3.Final" % "compile", "org.jboss.resteasy" % "resteasy-jackson2-provider" % "3.1.3.Final" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", {{#java8}} "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.10" % "compile", diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index e3e127020e4..714f4299b74 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -161,7 +161,10 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.4 + 3.1.1 + + none + attach-javadocs @@ -294,8 +297,8 @@ UTF-8 1.5.22 3.1.3.Final - 2.10.1 - 2.10.1 + 2.10.3 + 2.10.3 0.2.1 2.9.10 {{^java8}} diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index 33d09ae8305..c61825adbb9 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -120,8 +120,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.10.1" - jackson_databind_version = "2.10.1" + jackson_version = "2.10.3" + jackson_databind_version = "2.10.3" jackson_databind_nullable_version = "0.2.1" spring_web_version = "4.3.9.RELEASE" jodatime_version = "2.9.9" diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache index 1f5e82d501f..c9f02fffca4 100644 --- a/libraries/resttemplate/pom.mustache +++ b/libraries/resttemplate/pom.mustache @@ -163,7 +163,10 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.4 + 3.1.1 + + none + attach-javadocs @@ -309,8 +312,8 @@ UTF-8 1.5.22 4.3.9.RELEASE - 2.10.1 - 2.10.1 + 2.10.3 + 2.10.3 0.2.1 {{#joda}} 2.9.9 diff --git a/libraries/retrofit/pom.mustache b/libraries/retrofit/pom.mustache index 5a40a07979c..7c689ae4b6c 100644 --- a/libraries/retrofit/pom.mustache +++ b/libraries/retrofit/pom.mustache @@ -163,7 +163,10 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.4 + 3.1.1 + + none + attach-javadocs diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index ea96f094165..82f7974062b 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -131,8 +131,8 @@ ext { play_version = "2.5.14" {{/play25}} {{#play26}} - jackson_version = "2.10.1" - jackson_databind_version = "2.10.1" + jackson_version = "2.10.3" + jackson_databind_version = "2.10.3" jackson_databind_nullable_version = "0.2.1" play_version = "2.6.7" {{/play26}} diff --git a/libraries/retrofit2/build.sbt.mustache b/libraries/retrofit2/build.sbt.mustache index be45635e47f..f7b7ce464d5 100644 --- a/libraries/retrofit2/build.sbt.mustache +++ b/libraries/retrofit2/build.sbt.mustache @@ -23,16 +23,16 @@ lazy val root = (project in file(".")). {{/play24}} {{#play25}} "com.typesafe.play" % "play-java-ws_2.11" % "2.5.15" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", {{/play25}} {{#play26}} "com.typesafe.play" % "play-ahc-ws_2.12" % "2.6.7" % "compile", "javax.validation" % "validation-api" % "1.1.0.Final" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10.3" % "compile", {{/play26}} "com.squareup.retrofit2" % "converter-jackson" % "2.3.0" % "compile", {{/usePlayWS}} diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index 9613f948416..06f19bcb034 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -142,7 +142,10 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.4 + 3.1.1 + + none + attach-javadocs @@ -375,17 +378,17 @@ 1.8.3 1.5.22 {{#usePlayWS}} - 2.10.1 + 2.10.3 {{#play24}} 2.6.6 2.4.11 {{/play24}} {{#play25}} - 2.10.1 + 2.10.3 2.5.15 {{/play25}} {{#play26}} - 2.10.1 + 2.10.3 2.6.7 {{/play26}} 0.2.1 diff --git a/libraries/vertx/build.gradle.mustache b/libraries/vertx/build.gradle.mustache index 53bc7b9a8e5..02760c59149 100644 --- a/libraries/vertx/build.gradle.mustache +++ b/libraries/vertx/build.gradle.mustache @@ -28,8 +28,8 @@ task execute(type:JavaExec) { ext { swagger_annotations_version = "1.5.21" - jackson_version = "2.10.1" - jackson_databind_version = "2.10.1" + jackson_version = "2.10.3" + jackson_databind_version = "2.10.3" vertx_version = "3.4.2" junit_version = "4.13" } diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache index 3ed8b93b490..b3539c9fd77 100644 --- a/libraries/vertx/pom.mustache +++ b/libraries/vertx/pom.mustache @@ -151,7 +151,10 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.4 + 3.1.1 + + none + attach-javadocs @@ -289,8 +292,8 @@ UTF-8 3.4.2 1.5.22 - 2.10.1 - 2.10.1 + 2.10.3 + 2.10.3 0.2.1 4.13 diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index e21f3847641..72b80bac81a 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -556,22 +556,10 @@ public class ApiClient { final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(path); if (queryParams != null) { - //encode the query parameters in case they contain unsafe characters - for (List values : queryParams.values()) { - if (values != null) { - for (int i = 0; i < values.size(); i++) { - try { - values.set(i, URLEncoder.encode(values.get(i), "utf8")); - } catch (UnsupportedEncodingException e) { - - } - } - } - } builder.queryParams(queryParams); } - final WebClient.RequestBodySpec requestBuilder = webClient.method(method).uri(builder.encode().toUriString(), pathParams); + final WebClient.RequestBodySpec requestBuilder = webClient.method(method).uri(builder.build(false).toUriString(), pathParams); if(accept != null) { requestBuilder.accept(accept.toArray(new MediaType[accept.size()])); } diff --git a/libraries/webclient/api.mustache b/libraries/webclient/api.mustache index 9138d7d2e7a..b852e87ec4e 100644 --- a/libraries/webclient/api.mustache +++ b/libraries/webclient/api.mustache @@ -4,11 +4,13 @@ import {{invokerPackage}}.ApiClient; {{#imports}}import {{import}}; {{/imports}} +{{^fullJavaUtil}} -{{^fullJavaUtil}}import java.util.HashMap; +import java.util.HashMap; import java.util.List; import java.util.Locale; -import java.util.Map;{{/fullJavaUtil}} +import java.util.Map; +{{/fullJavaUtil}} import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.LinkedMultiValueMap; @@ -62,49 +64,68 @@ public class {{classname}} { */ public {{#returnType}}{{#isListContainer}}Flux<{{{returnBaseType}}}>{{/isListContainer}}{{^isListContainer}}Mono<{{{returnType}}}>{{/isListContainer}} {{/returnType}}{{^returnType}}Mono {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { Object postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; - {{#allParams}}{{#required}} + {{#allParams}} + {{#required}} // verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); } - {{/required}}{{/allParams}} + {{/required}} + {{/allParams}} // create path and map variables - final Map pathParams = new HashMap();{{#hasPathParams}}{{#pathParams}} - pathParams.put("{{baseName}}", {{#collectionFormat}}apiClient.collectionPathParameterToString(ApiClient.CollectionFormat.valueOf("csv".toUpperCase()), {{/collectionFormat}}{{{paramName}}}{{#collectionFormat}}){{/collectionFormat}});{{/pathParams}}{{/hasPathParams}} + final Map pathParams = new HashMap(); + {{#hasPathParams}} + {{#pathParams}} + pathParams.put("{{baseName}}", {{#collectionFormat}}apiClient.collectionPathParameterToString(ApiClient.CollectionFormat.valueOf("csv".toUpperCase()), {{/collectionFormat}}{{{paramName}}}{{#collectionFormat}}){{/collectionFormat}}); + {{/pathParams}} + {{/hasPathParams}} final MultiValueMap queryParams = new LinkedMultiValueMap(); final HttpHeaders headerParams = new HttpHeaders(); final MultiValueMap cookieParams = new LinkedMultiValueMap(); - final MultiValueMap formParams = new LinkedMultiValueMap();{{#hasQueryParams}} + final MultiValueMap formParams = new LinkedMultiValueMap(); + {{#hasQueryParams}} - {{#queryParams}}queryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{#hasMore}} - {{/hasMore}}{{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}} + {{#queryParams}} + queryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}})); + {{/queryParams}} + {{/hasQueryParams}} + {{#hasHeaderParams}} - {{#headerParams}}if ({{paramName}} != null) + {{#headerParams}} + if ({{paramName}} != null) headerParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{#hasMore}} - {{/hasMore}}{{/headerParams}}{{/hasHeaderParams}}{{#hasCookieParams}} - - {{#cookieParams}}cookieParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{#hasMore}} - {{/hasMore}}{{/cookieParams}}{{/hasCookieParams}}{{#hasFormParams}} - - {{#formParams}}if ({{paramName}} != null) - formParams.add{{#collectionFormat}}All{{/collectionFormat}}("{{baseName}}", {{#isFile}}new FileSystemResource({{paramName}}){{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} - {{/hasMore}}{{/formParams}}{{/hasFormParams}} - - final String[] accepts = { {{#hasProduces}} + {{/hasMore}} + {{/headerParams}} + {{/hasHeaderParams}} + {{#hasCookieParams}} + + {{#cookieParams}} + cookieParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}})); + {{/cookieParams}} + {{/hasCookieParams}} + {{#hasFormParams}} + + {{#formParams}} + if ({{paramName}} != null) + formParams.add{{#collectionFormat}}All{{/collectionFormat}}("{{baseName}}", {{#isFile}}new FileSystemResource({{paramName}}){{/isFile}}{{^isFile}}{{paramName}}{{/isFile}}); + {{/formParams}} + {{/hasFormParams}} + + final String[] localVarAccepts = { {{#hasProduces}} {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} {{/hasProduces}}}; - final List accept = apiClient.selectHeaderAccept(accepts); - final String[] contentTypes = { {{#hasConsumes}} + final List localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); + final String[] localVarContentTypes = { {{#hasConsumes}} {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} {{/hasConsumes}}}; - final MediaType contentType = apiClient.selectHeaderContentType(contentTypes); + final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); - String[] authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; - {{#returnType}}ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}> returnType = new ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference returnType = new ParameterizedTypeReference() {};{{/returnType}} - return apiClient.{{#isListContainer}}invokeFluxAPI{{/isListContainer}}{{^isListContainer}}invokeAPI{{/isListContainer}}("{{{path}}}", HttpMethod.{{httpMethod}}, pathParams, queryParams, postBody, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType); + {{#returnType}}ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}> localVarReturnType = new ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference localVarReturnType = new ParameterizedTypeReference() {};{{/returnType}} + return apiClient.{{#isListContainer}}invokeFluxAPI{{/isListContainer}}{{^isListContainer}}invokeAPI{{/isListContainer}}("{{{path}}}", HttpMethod.{{httpMethod}}, pathParams, queryParams, postBody, headerParams, cookieParams, formParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType); } {{/operation}} } diff --git a/libraries/webclient/pom.mustache b/libraries/webclient/pom.mustache index 39cd7729c35..138270ea3f9 100644 --- a/libraries/webclient/pom.mustache +++ b/libraries/webclient/pom.mustache @@ -143,8 +143,8 @@ UTF-8 1.5.22 5.0.16.RELEASE - 2.10.1 - 2.10.1 + 2.10.3 + 2.10.3 0.2.1 4.13 3.1.8.RELEASE diff --git a/model.mustache b/model.mustache index 8763e3bd08b..d4d1447a1d4 100644 --- a/model.mustache +++ b/model.mustache @@ -42,6 +42,6 @@ import org.hibernate.validator.constraints.*; {{#models}} {{#model}} -{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{#vendorExtensions.isOneOfInterface}}{{>oneof_interface}}{{/vendorExtensions.isOneOfInterface}}{{^vendorExtensions.isOneOfInterface}}{{>pojo}}{{/vendorExtensions.isOneOfInterface}}{{/isEnum}} +{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{#vendorExtensions.x-is-one-of-interface}}{{>oneof_interface}}{{/vendorExtensions.x-is-one-of-interface}}{{^vendorExtensions.x-is-one-of-interface}}{{>pojo}}{{/vendorExtensions.x-is-one-of-interface}}{{/isEnum}} {{/model}} {{/models}} diff --git a/model_test.mustache b/model_test.mustache index 0258f350074..07468db5657 100644 --- a/model_test.mustache +++ b/model_test.mustache @@ -21,7 +21,7 @@ import java.util.Map; public class {{classname}}Test { {{#models}} {{#model}} - {{^vendorExtensions.isOneOfInterface}} + {{^vendorExtensions.x-is-one-of-interface}} {{^isEnum}} private final {{classname}} model = new {{classname}}(); @@ -44,7 +44,7 @@ public class {{classname}}Test { } {{/allVars}} - {{/vendorExtensions.isOneOfInterface}} + {{/vendorExtensions.x-is-one-of-interface}} {{/model}} {{/models}} } diff --git a/oneof_interface.mustache b/oneof_interface.mustache index c17cf0b31ca..02deb483d5f 100644 --- a/oneof_interface.mustache +++ b/oneof_interface.mustache @@ -1,5 +1,5 @@ {{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>typeInfoAnnotation}}{{>xmlAnnotation}} -public interface {{classname}} {{#vendorExtensions.implements}}{{#-first}}extends {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.implements}} { +public interface {{classname}} {{#vendorExtensions.x-implements}}{{#-first}}extends {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.x-implements}} { {{#discriminator}} public {{propertyType}} {{propertyGetter}}(); {{/discriminator}} diff --git a/openapi.mustache b/openapi.mustache new file mode 100644 index 00000000000..34fbb53f331 --- /dev/null +++ b/openapi.mustache @@ -0,0 +1 @@ +{{{openapi-yaml}}} diff --git a/pojo.mustache b/pojo.mustache index 3386b1b969a..c438cd43eb7 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -10,7 +10,7 @@ }) {{/jackson}} {{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} -public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorExtensions.implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.implements}}{ +public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{ {{#serializableModel}} private static final long serialVersionUID = 1L; @@ -56,22 +56,22 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{#gson}} @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}}) {{/gson}} - {{#vendorExtensions.isJacksonOptionalNullable}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} {{#isContainer}} private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined(); {{/isContainer}} {{^isContainer}} private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; {{/isContainer}} - {{/vendorExtensions.isJacksonOptionalNullable}} - {{^vendorExtensions.isJacksonOptionalNullable}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} {{#isContainer}} private {{{datatypeWithEnum}}} {{name}}{{#required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/required}}{{^required}} = null{{/required}}; {{/isContainer}} {{^isContainer}} private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; {{/isContainer}} - {{/vendorExtensions.isJacksonOptionalNullable}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} {{/vars}} {{#parcelableModel}} @@ -99,14 +99,14 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{^isReadOnly}} public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { - {{#vendorExtensions.isJacksonOptionalNullable}}this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});{{/vendorExtensions.isJacksonOptionalNullable}} - {{^vendorExtensions.isJacksonOptionalNullable}}this.{{name}} = {{name}};{{/vendorExtensions.isJacksonOptionalNullable}} + {{#vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});{{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = {{name}};{{/vendorExtensions.x-is-jackson-optional-nullable}} return this; } {{#isListContainer}} public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { - {{#vendorExtensions.isJacksonOptionalNullable}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} if (this.{{name}} == null || !this.{{name}}.isPresent()) { this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); } @@ -116,8 +116,8 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE // this can never happen, as we make sure above that the value is present } return this; - {{/vendorExtensions.isJacksonOptionalNullable}} - {{^vendorExtensions.isJacksonOptionalNullable}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} {{^required}} if (this.{{name}} == null) { this.{{name}} = {{{defaultValue}}}; @@ -125,13 +125,13 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{/required}} this.{{name}}.add({{name}}Item); return this; - {{/vendorExtensions.isJacksonOptionalNullable}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} } {{/isListContainer}} {{#isMapContainer}} public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { - {{#vendorExtensions.isJacksonOptionalNullable}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} if (this.{{name}} == null || !this.{{name}}.isPresent()) { this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); } @@ -141,8 +141,8 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE // this can never happen, as we make sure above that the value is present } return this; - {{/vendorExtensions.isJacksonOptionalNullable}} - {{^vendorExtensions.isJacksonOptionalNullable}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} {{^required}} if (this.{{name}} == null) { this.{{name}} = {{{defaultValue}}}; @@ -150,7 +150,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{/required}} this.{{name}}.put(key, {{name}}Item); return this; - {{/vendorExtensions.isJacksonOptionalNullable}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} } {{/isMapContainer}} @@ -179,49 +179,49 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE @javax.annotation.Nullable {{/required}} {{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} @ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") -{{#vendorExtensions.extraAnnotation}} - {{{vendorExtensions.extraAnnotation}}} -{{/vendorExtensions.extraAnnotation}} -{{#vendorExtensions.isJacksonOptionalNullable}} +{{#vendorExtensions.x-extra-annotation}} + {{{vendorExtensions.x-extra-annotation}}} +{{/vendorExtensions.x-extra-annotation}} +{{#vendorExtensions.x-is-jackson-optional-nullable}} {{!unannotated, Jackson would pick this up automatically and add it *in addition* to the _JsonNullable getter field}} @JsonIgnore -{{/vendorExtensions.isJacksonOptionalNullable}} -{{^vendorExtensions.isJacksonOptionalNullable}}{{#jackson}}{{> jackson_annotations}}{{/jackson}}{{/vendorExtensions.isJacksonOptionalNullable}} +{{/vendorExtensions.x-is-jackson-optional-nullable}} +{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#jackson}}{{> jackson_annotations}}{{/jackson}}{{/vendorExtensions.x-is-jackson-optional-nullable}} public {{{datatypeWithEnum}}} {{getter}}() { - {{#vendorExtensions.isJacksonOptionalNullable}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} {{#isReadOnly}}{{! A readonly attribute doesn't have setter => jackson will set null directly if explicitly returned by API, so make sure we have an empty JsonNullable}} if ({{name}} == null) { {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; } {{/isReadOnly}} return {{name}}.orElse(null); - {{/vendorExtensions.isJacksonOptionalNullable}} - {{^vendorExtensions.isJacksonOptionalNullable}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} return {{name}}; - {{/vendorExtensions.isJacksonOptionalNullable}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} } - {{#vendorExtensions.isJacksonOptionalNullable}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} {{> jackson_annotations}} public JsonNullable<{{{datatypeWithEnum}}}> {{getter}}_JsonNullable() { return {{name}}; } - {{/vendorExtensions.isJacksonOptionalNullable}}{{#vendorExtensions.isJacksonOptionalNullable}} + {{/vendorExtensions.x-is-jackson-optional-nullable}}{{#vendorExtensions.x-is-jackson-optional-nullable}} @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) {{#isReadOnly}}private{{/isReadOnly}}{{^isReadOnly}}public{{/isReadOnly}} void {{setter}}_JsonNullable(JsonNullable<{{{datatypeWithEnum}}}> {{name}}) { {{! For getters/setters that have name differing from attribute name, we must include setter (albeit private) for jackson to be able to set the attribute}} this.{{name}} = {{name}}; } - {{/vendorExtensions.isJacksonOptionalNullable}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} {{^isReadOnly}} public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { - {{#vendorExtensions.isJacksonOptionalNullable}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); - {{/vendorExtensions.isJacksonOptionalNullable}} - {{^vendorExtensions.isJacksonOptionalNullable}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} this.{{name}} = {{name}}; - {{/vendorExtensions.isJacksonOptionalNullable}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} } {{/isReadOnly}} diff --git a/pojo_doc.mustache b/pojo_doc.mustache index e63db5e2720..d9381323c87 100644 --- a/pojo_doc.mustache +++ b/pojo_doc.mustache @@ -1,8 +1,8 @@ -# {{#vendorExtensions.isOneOfInterface}}Interface {{/vendorExtensions.isOneOfInterface}}{{classname}} +# {{#vendorExtensions.x-is-one-of-interface}}Interface {{/vendorExtensions.x-is-one-of-interface}}{{classname}} {{#description}}{{&description}} {{/description}} -{{^vendorExtensions.isOneOfInterface}} +{{^vendorExtensions.x-is-one-of-interface}} ## Properties Name | Type | Description | Notes @@ -18,19 +18,19 @@ Name | Value ---- | -----{{#allowableValues}}{{#enumVars}} {{name}} | {{value}}{{/enumVars}}{{/allowableValues}} {{/isEnum}}{{/vars}} -{{#vendorExtensions.implements.0}} +{{#vendorExtensions.x-implements.0}} ## Implemented Interfaces -{{#vendorExtensions.implements}} +{{#vendorExtensions.x-implements}} * {{{.}}} -{{/vendorExtensions.implements}} -{{/vendorExtensions.implements.0}} -{{/vendorExtensions.isOneOfInterface}} -{{#vendorExtensions.isOneOfInterface}} +{{/vendorExtensions.x-implements}} +{{/vendorExtensions.x-implements.0}} +{{/vendorExtensions.x-is-one-of-interface}} +{{#vendorExtensions.x-is-one-of-interface}} ## Implementing Classes {{#oneOf}} * {{{.}}} {{/oneOf}} -{{/vendorExtensions.isOneOfInterface}} \ No newline at end of file +{{/vendorExtensions.x-is-one-of-interface}} \ No newline at end of file diff --git a/pom.mustache b/pom.mustache index b17b2357bad..e9cbf546b6d 100644 --- a/pom.mustache +++ b/pom.mustache @@ -40,6 +40,21 @@ + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + true + 128m + 512m + + -Xlint:all + -J-Xss4m + + + + org.apache.maven.plugins maven-enforcer-plugin @@ -163,7 +178,10 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.10.4 + 3.1.1 + + none + attach-javadocs @@ -289,7 +307,7 @@ com.github.joschi.jackson jackson-datatype-threetenbp - ${jackson-version} + ${jackson-threetenbp-version} {{/threetenbp}} {{^java8}} @@ -354,7 +372,10 @@ 2.5 3.6 {{/supportJava6}} - {{^threetenbp}}2.7.5{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} + 2.10.3 + {{#threetenbp}} + 2.9.10 + {{/threetenbp}} 1.0.0 4.13 From e4dc8a2ee84b4d3e968d022748ccb4346af0f7e1 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 22 Apr 2020 11:59:27 +0800 Subject: [PATCH 220/370] Revert "Sync master to 5.0.x (#5968)" This reverts commit 90dd7a03418ff4554ae8351b325eb86ee5794e92. --- ApiClient.mustache | 72 +------- JSON.mustache | 15 +- ServerConfiguration.mustache | 58 ------- ServerVariable.mustache | 23 --- beanValidationCore.mustache | 2 +- build.gradle.mustache | 9 +- build.sbt.mustache | 1 - libraries/feign/api.mustache | 4 +- libraries/feign/auth/OAuth.mustache | 6 +- libraries/feign/build.gradle.mustache | 8 +- libraries/feign/build.sbt.mustache | 14 +- libraries/feign/pom.mustache | 13 +- libraries/google-api-client/pom.mustache | 9 +- libraries/jersey2/ApiClient.mustache | 161 +----------------- libraries/jersey2/api.mustache | 2 +- libraries/jersey2/build.gradle.mustache | 4 +- libraries/jersey2/build.sbt.mustache | 6 +- libraries/jersey2/pom.mustache | 7 +- libraries/microprofile/pojo.mustache | 6 +- libraries/native/ApiClient.mustache | 29 +--- libraries/native/api.mustache | 7 +- libraries/okhttp-gson/ApiClient.mustache | 47 +---- .../okhttp-gson/auth/RetryingOAuth.mustache | 7 - libraries/okhttp-gson/build.gradle.mustache | 16 +- libraries/okhttp-gson/build.sbt.mustache | 15 +- libraries/okhttp-gson/pom.mustache | 38 ++--- libraries/rest-assured/build.gradle.mustache | 22 +-- libraries/rest-assured/build.sbt.mustache | 24 +-- libraries/rest-assured/pom.mustache | 86 +++------- libraries/resteasy/build.gradle.mustache | 4 +- libraries/resteasy/build.sbt.mustache | 6 +- libraries/resteasy/pom.mustache | 9 +- libraries/resttemplate/build.gradle.mustache | 4 +- libraries/resttemplate/pom.mustache | 9 +- libraries/retrofit/pom.mustache | 5 +- libraries/retrofit2/build.gradle.mustache | 4 +- libraries/retrofit2/build.sbt.mustache | 12 +- libraries/retrofit2/pom.mustache | 11 +- libraries/vertx/build.gradle.mustache | 4 +- libraries/vertx/pom.mustache | 9 +- libraries/webclient/ApiClient.mustache | 14 +- libraries/webclient/api.mustache | 73 +++----- libraries/webclient/pom.mustache | 4 +- model.mustache | 2 +- model_test.mustache | 4 +- oneof_interface.mustache | 2 +- openapi.mustache | 1 - pojo.mustache | 64 +++---- pojo_doc.mustache | 18 +- pom.mustache | 27 +-- 50 files changed, 247 insertions(+), 750 deletions(-) delete mode 100644 ServerConfiguration.mustache delete mode 100644 ServerVariable.mustache delete mode 100644 openapi.mustache diff --git a/ApiClient.mustache b/ApiClient.mustache index 8b71c1551e3..1ae6c36f68a 100644 --- a/ApiClient.mustache +++ b/ApiClient.mustache @@ -38,9 +38,7 @@ import java.util.Collections; import java.util.Map; import java.util.Map.Entry; import java.util.HashMap; -import java.util.HashSet; import java.util.List; -import java.util.Arrays; import java.util.ArrayList; import java.util.Date; import java.util.TimeZone; @@ -65,33 +63,6 @@ public class ApiClient { private Map defaultHeaderMap = new HashMap(); private Map defaultCookieMap = new HashMap(); private String basePath = "{{{basePath}}}"; - protected List servers = new ArrayList({{#servers}}{{#-first}}Arrays.asList( -{{/-first}} new ServerConfiguration( - "{{{url}}}", - "{{{description}}}{{^description}}No description provided{{/description}}", - new HashMap(){{#variables}}{{#-first}} {{ -{{/-first}} put("{{{name}}}", new ServerVariable( - "{{{description}}}{{^description}}No description provided{{/description}}", - "{{{defaultValue}}}", - new HashSet( - {{#enumValues}} - {{#-first}} - Arrays.asList( - {{/-first}} - "{{{.}}}"{{^-last}},{{/-last}} - {{#-last}} - ) - {{/-last}} - {{/enumValues}} - ) - )); - {{#-last}} - }}{{/-last}}{{/variables}} - ){{^-last}},{{/-last}} - {{#-last}} - ){{/-last}}{{/servers}}); - protected Integer serverIndex = 0; - protected Map serverVariables = null; private boolean debugging = false; private int connectionTimeout = 0; @@ -206,33 +177,6 @@ public class ApiClient { return this; } - public List getServers() { - return servers; - } - - public ApiClient setServers(List servers) { - this.servers = servers; - return this; - } - - public Integer getServerIndex() { - return serverIndex; - } - - public ApiClient setServerIndex(Integer serverIndex) { - this.serverIndex = serverIndex; - return this; - } - - public Map getServerVariables() { - return serverVariables; - } - - public ApiClient setServerVariables(Map serverVariables) { - this.serverVariables = serverVariables; - return this; - } - /** * Gets the status code of the previous request * @return Status code @@ -308,7 +252,7 @@ public class ApiClient { } throw new RuntimeException("No API key authentication configured!"); } - + /** * Helper method to set API key prefix for the first API key authentication. * @param apiKeyPrefix API key prefix @@ -682,20 +626,8 @@ public class ApiClient { * @return The full URL */ private String buildUrl(String path, List queryParams, List collectionQueryParams) { - String baseURL; - if (serverIndex != null) { - if (serverIndex < 0 || serverIndex >= servers.size()) { - throw new ArrayIndexOutOfBoundsException(String.format( - "Invalid index %d when selecting the host settings. Must be less than %d", serverIndex, servers.size() - )); - } - baseURL = servers.get(serverIndex).URL(serverVariables); - } else { - baseURL = basePath; - } - final StringBuilder url = new StringBuilder(); - url.append(baseURL).append(path); + url.append(basePath).append(path); if (queryParams != null && !queryParams.isEmpty()) { // support (constant) query string in `path`, e.g. "/posts?draft=1" diff --git a/JSON.mustache b/JSON.mustache index 590ba386ea2..b951c3c555d 100644 --- a/JSON.mustache +++ b/JSON.mustache @@ -69,11 +69,11 @@ public class JSON { .registerTypeSelector({{classname}}.class, new TypeSelector() { @Override public Class getClassForElement(JsonElement readElement) { - Map classByDiscriminatorValue = new HashMap(); + Map classByDiscriminatorValue = new HashMap(); {{#mappedModels}} - classByDiscriminatorValue.put("{{mappingName}}"{{^discriminatorCaseSensitive}}.toUpperCase(Locale.ROOT){{/discriminatorCaseSensitive}}, {{modelName}}.class); + classByDiscriminatorValue.put("{{mappingName}}".toUpperCase(Locale.ROOT), {{modelName}}.class); {{/mappedModels}} - classByDiscriminatorValue.put("{{name}}"{{^discriminatorCaseSensitive}}.toUpperCase(Locale.ROOT){{/discriminatorCaseSensitive}}, {{classname}}.class); + classByDiscriminatorValue.put("{{classname}}".toUpperCase(Locale.ROOT), {{classname}}.class); return getClassByDiscriminator(classByDiscriminatorValue, getDiscriminatorValue(readElement, "{{{propertyBaseName}}}")); } @@ -97,15 +97,8 @@ public class JSON { return element.getAsString(); } - /** - * Returns the Java class that implements the OpenAPI schema for the specified discriminator value. - * - * @param classByDiscriminatorValue The map of discriminator values to Java classes. - * @param discriminatorValue The value of the OpenAPI discriminator in the input data. - * @return The Java class that implements the OpenAPI schema - */ private static Class getClassByDiscriminator(Map classByDiscriminatorValue, String discriminatorValue) { - Class clazz = (Class) classByDiscriminatorValue.get(discriminatorValue{{^discriminatorCaseSensitive}}.toUpperCase(Locale.ROOT){{/discriminatorCaseSensitive}}); + Class clazz = (Class) classByDiscriminatorValue.get(discriminatorValue.toUpperCase(Locale.ROOT)); if (null == clazz) { throw new IllegalArgumentException("cannot determine model class of name: <" + discriminatorValue + ">"); } diff --git a/ServerConfiguration.mustache b/ServerConfiguration.mustache deleted file mode 100644 index f976c542b19..00000000000 --- a/ServerConfiguration.mustache +++ /dev/null @@ -1,58 +0,0 @@ -package {{invokerPackage}}; - -import java.util.Map; - -/** - * Representing a Server configuration. - */ -public class ServerConfiguration { - public String URL; - public String description; - public Map variables; - - /** - * @param URL A URL to the target host. - * @param description A describtion of the host designated by the URL. - * @param variables A map between a variable name and its value. The value is used for substitution in the server's URL template. - */ - public ServerConfiguration(String URL, String description, Map variables) { - this.URL = URL; - this.description = description; - this.variables = variables; - } - - /** - * Format URL template using given variables. - * - * @param variables A map between a variable name and its value. - * @return Formatted URL. - */ - public String URL(Map variables) { - String url = this.URL; - - // go through variables and replace placeholders - for (Map.Entry variable: this.variables.entrySet()) { - String name = variable.getKey(); - ServerVariable serverVariable = variable.getValue(); - String value = serverVariable.defaultValue; - - if (variables != null && variables.containsKey(name)) { - value = variables.get(name); - if (serverVariable.enumValues.size() > 0 && !serverVariable.enumValues.contains(value)) { - throw new RuntimeException("The variable " + name + " in the server URL has invalid value " + value + "."); - } - } - url = url.replaceAll("\\{" + name + "\\}", value); - } - return url; - } - - /** - * Format URL template using default server variables. - * - * @return Formatted URL. - */ - public String URL() { - return URL(null); - } -} diff --git a/ServerVariable.mustache b/ServerVariable.mustache deleted file mode 100644 index 1978b1eb95e..00000000000 --- a/ServerVariable.mustache +++ /dev/null @@ -1,23 +0,0 @@ -package {{invokerPackage}}; - -import java.util.HashSet; - -/** - * Representing a Server Variable for server URL template substitution. - */ -public class ServerVariable { - public String description; - public String defaultValue; - public HashSet enumValues = null; - - /** - * @param description A description for the server variable. - * @param defaultValue The default value to use for substitution. - * @param enumValues An enumeration of string values to be used if the substitution options are from a limited set. - */ - public ServerVariable(String description, String defaultValue, HashSet enumValues) { - this.description = description; - this.defaultValue = defaultValue; - this.enumValues = enumValues; - } -} diff --git a/beanValidationCore.mustache b/beanValidationCore.mustache index ae26b2739f1..d107c037b9a 100644 --- a/beanValidationCore.mustache +++ b/beanValidationCore.mustache @@ -17,4 +17,4 @@ isInteger set isLong set }}{{#isLong}}{{#minimum}} @Min({{minimum}}L){{/minimum}}{{#maximum}} @Max({{maximum}}L){{/maximum}}{{/isLong}}{{! Not Integer, not Long => we have a decimal value! -}}{{^isInteger}}{{^isLong}}{{#minimum}} @DecimalMin({{#exclusiveMinimum}}value={{/exclusiveMinimum}}"{{minimum}}"{{#exclusiveMinimum}},inclusive=false{{/exclusiveMinimum}}){{/minimum}}{{#maximum}} @DecimalMax({{#exclusiveMaximum}}value={{/exclusiveMaximum}}"{{maximum}}"{{#exclusiveMaximum}},inclusive=false{{/exclusiveMaximum}}){{/maximum}}{{/isLong}}{{/isInteger}} \ No newline at end of file +}}{{^isInteger}}{{^isLong}}{{#minimum}} @DecimalMin({{#exclusiveMinimum}}value={{/exclusiveMinimum}}"{{minimum}}"{{#exclusiveMinimum}},inclusive=false{{/exclusiveMinimum}}){{/minimum}}{{#maximum}} @DecimalMax({{#exclusiveMinimum}}value={{/exclusiveMinimum}}"{{maximum}}"{{#exclusiveMinimum}},inclusive=false{{/exclusiveMinimum}}){{/maximum}}{{/isLong}}{{/isInteger}} \ No newline at end of file diff --git a/build.gradle.mustache b/build.gradle.mustache index c1bf968dbac..69707eadc16 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -136,12 +136,9 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.10.3" - jackson_databind_version = "2.10.3" + jackson_version = "2.10.1" + jackson_databind_version = "2.10.1" jackson_databind_nullable_version = "0.2.1" - {{#threetenbp}} - jackson_threetenbp_version = "2.9.10" - {{/threetenbp}} jersey_version = "1.19.4" jodatime_version = "2.9.9" junit_version = "4.13" @@ -164,7 +161,7 @@ dependencies { compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threetenbp_version" + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_version" {{/threetenbp}} {{^java8}} compile "com.brsanthu:migbase64:2.2" diff --git a/build.sbt.mustache b/build.sbt.mustache index 464090415c4..e69de29bb2d 100644 --- a/build.sbt.mustache +++ b/build.sbt.mustache @@ -1 +0,0 @@ -# TODO diff --git a/libraries/feign/api.mustache b/libraries/feign/api.mustache index cff48fcd2e4..238079ca27c 100644 --- a/libraries/feign/api.mustache +++ b/libraries/feign/api.mustache @@ -42,7 +42,7 @@ public interface {{classname}} extends ApiClient.Api { "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{#hasMore}}, {{/hasMore}}{{/headerParams}} }) - {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{baseName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isBodyParam}}{{^legacyDates}}@Param("{{baseName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{baseName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); {{#hasQueryParams}} /** @@ -80,7 +80,7 @@ public interface {{classname}} extends ApiClient.Api { "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{#hasMore}}, {{/hasMore}}{{/headerParams}} }) - {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isQueryParam}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{baseName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}, {{/isQueryParam}}{{/allParams}}@QueryMap(encoded=true) Map queryParams); + {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isQueryParam}}{{^isBodyParam}}{{^legacyDates}}@Param("{{baseName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{baseName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}, {{/isQueryParam}}{{/allParams}}@QueryMap(encoded=true) Map queryParams); /** * A convenience class for generating query parameters for the diff --git a/libraries/feign/auth/OAuth.mustache b/libraries/feign/auth/OAuth.mustache index feefdb93981..25b1f193ba9 100644 --- a/libraries/feign/auth/OAuth.mustache +++ b/libraries/feign/auth/OAuth.mustache @@ -83,20 +83,20 @@ public class OAuth implements RequestInterceptor { } // If first time, get the token if (expirationTimeMillis == null || System.currentTimeMillis() >= expirationTimeMillis) { - updateAccessToken(template); + updateAccessToken(); } if (getAccessToken() != null) { template.header("Authorization", "Bearer " + getAccessToken()); } } - public synchronized void updateAccessToken(RequestTemplate template) { + public synchronized void updateAccessToken() { OAuthJSONAccessTokenResponse accessTokenResponse; try { accessTokenResponse = oauthClient.accessToken(tokenRequestBuilder.buildBodyMessage()); } catch (Exception e) { {{#useFeign10}} - throw new RetryableException(0, e.getMessage(), HttpMethod.POST, e, null, template.request()); + throw new RetryableException(0, e.getMessage(), HttpMethod.POST, e, null); {{/useFeign10}} {{^useFeign10}} throw new RetryableException(e.getMessage(), e,null); diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index 2a6c4c79fbc..69170a03177 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -120,14 +120,14 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.10.3" - jackson_databind_version = "2.10.3" + jackson_version = "2.10.1" + jackson_databind_version = "2.10.1" jackson_databind_nullable_version = "0.2.1" {{#threetenbp}} jackson_threetenbp_version = "2.9.10" {{/threetenbp}} - feign_version = "{{#useFeign10}}10.7.4{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" - feign_form_version = "{{#useFeign10}}3.8.0{{/useFeign10}}{{^useFeign10}}2.1.0{{/useFeign10}}" + feign_version = "{{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" + feign_form_version = "2.1.0" junit_version = "4.13" oltu_version = "1.0.1" } diff --git a/libraries/feign/build.sbt.mustache b/libraries/feign/build.sbt.mustache index 8fa1d345b26..907b7bd4d27 100644 --- a/libraries/feign/build.sbt.mustache +++ b/libraries/feign/build.sbt.mustache @@ -10,13 +10,13 @@ lazy val root = (project in file(".")). resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( "io.swagger" % "swagger-annotations" % "1.5.22" % "compile", - "io.github.openfeign" % "feign-core" % "{{#useFeign10}}10.7.4{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", - "io.github.openfeign" % "feign-jackson" % "{{#useFeign10}}10.7.4{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", - "io.github.openfeign" % "feign-slf4j" % "{{#useFeign10}}10.7.4{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", - "io.github.openfeign.form" % "feign-form" % "{{#useFeign10}}3.8.0{{/useFeign10}}{{^useFeign10}}2.1.0{{/useFeign10}}" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", + "io.github.openfeign" % "feign-core" % "{{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", + "io.github.openfeign" % "feign-jackson" % "{{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", + "io.github.openfeign" % "feign-slf4j" % "{{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", + "io.github.openfeign.form" % "feign-form" % "2.1.0" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.1" % "compile", "com.fasterxml.jackson.datatype" % "jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}" % "2.9.10" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index 86f6f397781..e73e45de1b3 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -142,10 +142,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.1.1 - - none - + 2.10.4 attach-javadocs @@ -315,11 +312,11 @@ ${java.version} ${java.version} 1.5.21 - {{#useFeign10}}10.7.4{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}} - {{#useFeign10}}3.8.0{{/useFeign10}}{{^useFeign10}}2.1.0{{/useFeign10}} - 2.10.3 + {{#useFeign10}}10.2.3{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}} + 2.1.0 + 2.10.1 0.2.1 - 2.10.3 + 2.10.1 {{#threetenbp}} 2.9.10 {{/threetenbp}} diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index 4d6a8c5e161..5e3c04fe93b 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -163,10 +163,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.1.1 - - none - + 2.10.4 attach-javadocs @@ -309,8 +306,8 @@ 1.5.22 1.30.2 2.25.1 - 2.10.3 - 2.10.3 + 2.10.1 + 2.10.1 0.2.1 {{#joda}} 2.9.9 diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 0111a24c4da..95fb8093bc3 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -37,9 +37,7 @@ import java.util.Collections; import java.util.Map; import java.util.Map.Entry; import java.util.HashMap; -import java.util.HashSet; import java.util.List; -import java.util.Arrays; import java.util.ArrayList; import java.util.Date; import java.util.TimeZone; @@ -57,7 +55,6 @@ import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; import {{invokerPackage}}.auth.HttpBearerAuth; import {{invokerPackage}}.auth.ApiKeyAuth; - {{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} @@ -67,74 +64,6 @@ public class ApiClient { protected Map defaultHeaderMap = new HashMap(); protected Map defaultCookieMap = new HashMap(); protected String basePath = "{{{basePath}}}"; - protected List servers = new ArrayList({{#servers}}{{#-first}}Arrays.asList( -{{/-first}} new ServerConfiguration( - "{{{url}}}", - "{{{description}}}{{^description}}No description provided{{/description}}", - new HashMap(){{#variables}}{{#-first}} {{ -{{/-first}} put("{{{name}}}", new ServerVariable( - "{{{description}}}{{^description}}No description provided{{/description}}", - "{{{defaultValue}}}", - new HashSet( - {{#enumValues}} - {{#-first}} - Arrays.asList( - {{/-first}} - "{{{.}}}"{{^-last}},{{/-last}} - {{#-last}} - ) - {{/-last}} - {{/enumValues}} - ) - )); - {{#-last}} - }}{{/-last}}{{/variables}} - ){{^-last}},{{/-last}} - {{#-last}} - ){{/-last}}{{/servers}}); - protected Integer serverIndex = 0; - protected Map serverVariables = null; - protected Map> operationServers = new HashMap>() {{ - {{#apiInfo}} - {{#apis}} - {{#operations}} - {{#operation}} - {{#servers}} - {{#-first}} - put("{{{classname}}}.{{{operationId}}}", new ArrayList(Arrays.asList( - {{/-first}} - new ServerConfiguration( - "{{{url}}}", - "{{{description}}}{{^description}}No description provided{{/description}}", - new HashMap(){{#variables}}{{#-first}} {{ -{{/-first}} put("{{{name}}}", new ServerVariable( - "{{{description}}}{{^description}}No description provided{{/description}}", - "{{{defaultValue}}}", - new HashSet( - {{#enumValues}} - {{#-first}} - Arrays.asList( - {{/-first}} - "{{{.}}}"{{^-last}},{{/-last}} - {{#-last}} - ) - {{/-last}} - {{/enumValues}} - ) - )); - {{#-last}} - }}{{/-last}}{{/variables}} - ){{^-last}},{{/-last}} - {{#-last}} - )));{{/-last}} - {{/servers}} - {{/operation}} - {{/operations}} - {{/apis}} - {{/apiInfo}} - }}; - protected Map operationServerIndex = new HashMap(); - protected Map> operationServerVariables = new HashMap>(); protected boolean debugging = false; protected int connectionTimeout = 0; private int readTimeout = 0; @@ -144,7 +73,6 @@ public class ApiClient { protected String tempFolderPath = null; protected Map authentications; - protected Map authenticationLookup; protected DateFormat dateFormat; @@ -165,10 +93,6 @@ public class ApiClient { authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} // Prevent the authentications from being modified. authentications = Collections.unmodifiableMap(authentications); - - // Setup authentication lookup (key: authentication alias, value: authentication name) - authenticationLookup = new HashMap();{{#authMethods}}{{#vendorExtensions.x-auth-id-alias}} - authenticationLookup.put("{{name}}", "{{.}}");{{/vendorExtensions.x-auth-id-alias}}{{/authMethods}} } /** @@ -197,33 +121,6 @@ public class ApiClient { return this; } - public List getServers() { - return servers; - } - - public ApiClient setServers(List servers) { - this.servers = servers; - return this; - } - - public Integer getServerIndex() { - return serverIndex; - } - - public ApiClient setServerIndex(Integer serverIndex) { - this.serverIndex = serverIndex; - return this; - } - - public Map getServerVariables() { - return serverVariables; - } - - public ApiClient setServerVariables(Map serverVariables) { - this.serverVariables = serverVariables; - return this; - } - /** * Get authentications (key: authentication name, value: authentication). * @return Map of authentication object @@ -284,25 +181,6 @@ public class ApiClient { throw new RuntimeException("No API key authentication configured!"); } - /** - * Helper method to configure authentications which respects aliases of API keys. - * - * @param secrets Hash map from authentication name to its secret. - */ - public void configureApiKeys(HashMap secrets) { - for (Map.Entry authEntry : authentications.entrySet()) { - Authentication auth = authEntry.getValue(); - if (auth instanceof ApiKeyAuth) { - String name = authEntry.getKey(); - // respect x-auth-id-alias property - name = authenticationLookup.getOrDefault(name, name); - if (secrets.containsKey(name)) { - ((ApiKeyAuth) auth).setApiKey(secrets.get(name)); - } - } - } - } - /** * Helper method to set API key prefix for the first API key authentication. * @param apiKeyPrefix API key prefix @@ -792,7 +670,6 @@ public class ApiClient { * Invoke API by sending HTTP request with the given options. * * @param Type - * @param operation The qualified name of the operation * @param path The sub-path of the HTTP URL * @param method The request method, one of "GET", "POST", "PUT", "HEAD" and "DELETE" * @param queryParams The query parameters @@ -807,36 +684,12 @@ public class ApiClient { * @return The response body in type of string * @throws ApiException API exception */ - public ApiResponse invokeAPI(String operation, String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { + public ApiResponse invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); - // Not using `.target(targetURL).path(path)` below, + // Not using `.target(this.basePath).path(path)` below, // to support (constant) query string in `path`, e.g. "/posts?draft=1" - String targetURL; - if (serverIndex != null) { - Integer index; - List serverConfigurations; - Map variables; - - if (operationServers.containsKey(operation)) { - index = operationServerIndex.getOrDefault(operation, serverIndex); - variables = operationServerVariables.getOrDefault(operation, serverVariables); - serverConfigurations = operationServers.get(operation); - } else { - index = serverIndex; - variables = serverVariables; - serverConfigurations = servers; - } - if (index < 0 || index >= serverConfigurations.size()) { - throw new ArrayIndexOutOfBoundsException(String.format( - "Invalid index %d when selecting the host settings. Must be less than %d", index, serverConfigurations.size() - )); - } - targetURL = serverConfigurations.get(index).URL(variables) + path; - } else { - targetURL = this.basePath + path; - } - WebTarget target = httpClient.target(targetURL); + WebTarget target = httpClient.target(this.basePath + path); if (queryParams != null) { for (Pair queryParam : queryParams) { @@ -940,14 +793,6 @@ public class ApiClient { } } - /** - * @deprecated Add qualified name of the operation as a first parameter. - */ - @Deprecated - public ApiResponse invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { - return invokeAPI(null, path, method, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType); - } - /** * Build the Client used to make HTTP requests. * @param debugging Debug setting diff --git a/libraries/jersey2/api.mustache b/libraries/jersey2/api.mustache index 4a2e61afe8e..3950d7a2af3 100644 --- a/libraries/jersey2/api.mustache +++ b/libraries/jersey2/api.mustache @@ -151,7 +151,7 @@ public class {{classname}} { String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; {{#returnType}}GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {};{{/returnType}} - return apiClient.invokeAPI("{{classname}}.{{operationId}}", localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, {{#returnType}}localVarReturnType{{/returnType}}{{^returnType}}null{{/returnType}}); + return apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, {{#returnType}}localVarReturnType{{/returnType}}{{^returnType}}null{{/returnType}}); } {{#vendorExtensions.x-group-parameters}} diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index cdb451adb34..30aa47428cb 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -119,8 +119,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.10.3" - jackson_databind_version = "2.10.3" + jackson_version = "2.10.1" + jackson_databind_version = "2.10.1" jackson_databind_nullable_version = "0.2.1" {{#supportJava6}} jersey_version = "2.6" diff --git a/libraries/jersey2/build.sbt.mustache b/libraries/jersey2/build.sbt.mustache index abb91ecdc99..7e2dc832a2c 100644 --- a/libraries/jersey2/build.sbt.mustache +++ b/libraries/jersey2/build.sbt.mustache @@ -13,9 +13,9 @@ lazy val root = (project in file(".")). "org.glassfish.jersey.core" % "jersey-client" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, "org.glassfish.jersey.media" % "jersey-media-multipart" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, "org.glassfish.jersey.media" % "jersey-media-json-jackson" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.1" % "compile", {{#joda}} "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.10" % "compile", {{/joda}} diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 9bd8925f001..e9fc8ba3942 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -163,7 +163,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.1.1 + 2.10.4 attach-javadocs @@ -173,7 +173,6 @@ - none http.response.details @@ -361,8 +360,8 @@ 2.5 3.6 {{/supportJava6}} - 2.10.3 - 2.10.3 + 2.10.1 + 2.10.1 0.2.1 {{#threetenbp}} 2.9.10 diff --git a/libraries/microprofile/pojo.mustache b/libraries/microprofile/pojo.mustache index 4ded8e94e2e..a7d3ddb77c1 100644 --- a/libraries/microprofile/pojo.mustache +++ b/libraries/microprofile/pojo.mustache @@ -57,9 +57,9 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}}{{#serializ * @return {{name}} **/ @JsonbProperty("{{baseName}}") -{{#vendorExtensions.x-extra-annotation}} - {{{vendorExtensions.x-extra-annotation}}} -{{/vendorExtensions.x-extra-annotation}} +{{#vendorExtensions.extraAnnotation}} + {{{vendorExtensions.extraAnnotation}}} +{{/vendorExtensions.extraAnnotation}} {{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} {{#isEnum}}{{^isListContainer}}{{^isMapContainer}}public {{dataType}} {{getter}}() { if ({{name}} == null) { return null; diff --git a/libraries/native/ApiClient.mustache b/libraries/native/ApiClient.mustache index fb83d919b93..6bcad4a2f3f 100644 --- a/libraries/native/ApiClient.mustache +++ b/libraries/native/ApiClient.mustache @@ -8,12 +8,10 @@ import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.openapitools.jackson.nullable.JsonNullableModule; -import java.io.InputStream; import java.net.URI; import java.net.URLEncoder; import java.net.http.HttpClient; import java.net.http.HttpRequest; -import java.net.http.HttpResponse; import java.nio.charset.Charset; import java.time.Duration; import java.util.Collection; @@ -48,7 +46,6 @@ public class ApiClient { private int port; private String basePath; private Consumer interceptor; - private Consumer> responseInterceptor; private Duration readTimeout; private static String valueToString(Object value) { @@ -164,7 +161,6 @@ public class ApiClient { basePath = baseURI.getRawPath(); interceptor = null; readTimeout = null; - responseInterceptor = null; } /** @@ -296,29 +292,6 @@ public class ApiClient { return interceptor; } - /** - * Set a custom response interceptor. - * - *

This is useful for logging, monitoring or extraction of header variables

- * - * @param interceptor A function invoked before creating each request. A value - * of null resets the interceptor to a no-op. - * @return This object. - */ - public ApiClient setResponseInterceptor(Consumer> interceptor) { - this.responseInterceptor = interceptor; - return this; - } - - /** - * Get the custom response interceptor. - * - * @return The custom interceptor that was set, or null if there isn't any. - */ - public Consumer> getResponseInterceptor() { - return responseInterceptor; - } - /** * Set the read timeout for the http client. * @@ -334,7 +307,7 @@ public class ApiClient { this.readTimeout = readTimeout; return this; } - + /** * Get the read timeout that was set. * diff --git a/libraries/native/api.mustache b/libraries/native/api.mustache index 4c4848ca480..8c545a015f4 100644 --- a/libraries/native/api.mustache +++ b/libraries/native/api.mustache @@ -36,8 +36,7 @@ public class {{classname}} { private final String memberVarBaseUri; private final Consumer memberVarInterceptor; private final Duration memberVarReadTimeout; - private final Consumer> memberVarResponseInterceptor; - + public {{classname}}() { this(new ApiClient()); } @@ -48,7 +47,6 @@ public class {{classname}} { memberVarBaseUri = apiClient.getBaseUri(); memberVarInterceptor = apiClient.getRequestInterceptor(); memberVarReadTimeout = apiClient.getReadTimeout(); - memberVarResponseInterceptor = apiClient.getResponseInterceptor(); } {{#operation}} @@ -140,9 +138,6 @@ public class {{classname}} { HttpResponse localVarResponse = memberVarHttpClient.send( localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofInputStream()); - if (memberVarResponseInterceptor != null) { - memberVarResponseInterceptor.accept(localVarResponse); - } if (localVarResponse.statusCode()/ 100 != 2) { throw new ApiException(localVarResponse.statusCode(), "{{operationId}} call received non-success response", diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index 3969c08d391..3856ddf8c19 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -30,7 +30,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.lang.reflect.Type; -import java.net.URI; import java.net.URLConnection; import java.net.URLEncoder; import java.security.GeneralSecurityException; @@ -91,7 +90,6 @@ public class ApiClient { */ public ApiClient() { init(); - initHttpClient(); // Setup authentications (key: authentication name, value: authentication).{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} @@ -123,40 +121,16 @@ public class ApiClient { * Constructor for ApiClient to support access token retry on 401/403 configured with client ID, secret, and additional parameters */ public ApiClient(String clientId, String clientSecret, Map parameters) { - this(null, clientId, clientSecret, parameters); - } - - /* - * Constructor for ApiClient to support access token retry on 401/403 configured with base path, client ID, secret, and additional parameters - */ - public ApiClient(String basePath, String clientId, String clientSecret, Map parameters) { init(); - if (basePath != null) { - this.basePath = basePath; - } {{#hasOAuthMethods}} - String tokenUrl = "{{tokenUrl}}"; - if (!"".equals(tokenUrl) && !URI.create(tokenUrl).isAbsolute()) { - URI uri = URI.create(getBasePath()); - tokenUrl = uri.getScheme() + ":" + - (uri.getAuthority() != null ? "//" + uri.getAuthority() : "") + - tokenUrl; - if (!URI.create(tokenUrl).isAbsolute()) { - throw new IllegalArgumentException("OAuth2 token URL must be an absolute URL"); - } - } - RetryingOAuth retryingOAuth = new RetryingOAuth(tokenUrl, clientId, OAuthFlow.{{flow}}, clientSecret, parameters); + RetryingOAuth retryingOAuth = new RetryingOAuth("{{tokenUrl}}", clientId, OAuthFlow.{{flow}}, clientSecret, parameters); authentications.put( "{{name}}", retryingOAuth ); - initHttpClient(Collections.singletonList(retryingOAuth)); + httpClient.interceptors().add(retryingOAuth); {{/hasOAuthMethods}} - // Setup authentications (key: authentication name, value: authentication).{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} - authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} - authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} - authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{/authMethods}} // Prevent the authentications from being modified. authentications = Collections.unmodifiableMap(authentications); @@ -165,25 +139,16 @@ public class ApiClient { {{/-first}} {{/oauthMethods}} {{/hasOAuthMethods}} - private void initHttpClient() { - initHttpClient(Collections.emptyList()); - } - - private void initHttpClient(List interceptors) { + private void init() { OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.addNetworkInterceptor(getProgressInterceptor()); - for (Interceptor interceptor: interceptors) { - builder.addInterceptor(interceptor); - } + httpClient = builder.build(); + {{#useGzipFeature}} // Enable gzip request compression - builder.addInterceptor(new GzipRequestInterceptor()); + httpClient.interceptors().add(new GzipRequestInterceptor()); {{/useGzipFeature}} - httpClient = builder.build(); - } - - private void init() { verifyingSsl = true; json = new JSON(); diff --git a/libraries/okhttp-gson/auth/RetryingOAuth.mustache b/libraries/okhttp-gson/auth/RetryingOAuth.mustache index 3ddacedb70e..94f1d6afcf9 100644 --- a/libraries/okhttp-gson/auth/RetryingOAuth.mustache +++ b/libraries/okhttp-gson/auth/RetryingOAuth.mustache @@ -36,13 +36,6 @@ public class RetryingOAuth extends OAuth implements Interceptor { this(new OkHttpClient(), tokenRequestBuilder); } - /** - @param tokenUrl The token URL to be used for this OAuth2 flow. - Applicable to the following OAuth2 flows: "password", "clientCredentials" and "authorizationCode". - The value must be an absolute URL. - @param clientId The OAuth2 client ID for the "clientCredentials" flow. - @param clientSecret The OAuth2 client secret for the "clientCredentials" flow. - */ public RetryingOAuth( String tokenUrl, String clientId, diff --git a/libraries/okhttp-gson/build.gradle.mustache b/libraries/okhttp-gson/build.gradle.mustache index 91913276775..304b00a445a 100644 --- a/libraries/okhttp-gson/build.gradle.mustache +++ b/libraries/okhttp-gson/build.gradle.mustache @@ -68,7 +68,7 @@ if(hasProperty('target') && target == 'android') { } dependencies { - provided 'javax.annotation:javax.annotation-api:1.3.2' + provided 'javax.annotation:jsr250-api:1.0' } } @@ -126,21 +126,21 @@ if(hasProperty('target') && target == 'android') { } dependencies { - compile 'io.swagger:swagger-annotations:1.5.24' + compile 'io.swagger:swagger-annotations:1.5.22' compile "com.google.code.findbugs:jsr305:3.0.2" - compile 'com.squareup.okhttp3:okhttp:3.14.7' - compile 'com.squareup.okhttp3:logging-interceptor:3.14.7' - compile 'com.google.code.gson:gson:2.8.6' - compile 'io.gsonfire:gson-fire:1.8.4' + compile 'com.squareup.okhttp3:okhttp:3.14.2' + compile 'com.squareup.okhttp3:logging-interceptor:3.14.2' + compile 'com.google.code.gson:gson:2.8.5' + compile 'io.gsonfire:gson-fire:1.8.3' {{#hasOAuthMethods}} compile group: 'org.apache.oltu.oauth2', name: 'org.apache.oltu.oauth2.client', version: '1.0.1' {{/hasOAuthMethods}} - compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.10' + compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.9' {{#joda}} compile 'joda-time:joda-time:2.9.9' {{/joda}} {{#threetenbp}} - compile 'org.threeten:threetenbp:1.4.3' + compile 'org.threeten:threetenbp:1.4.0' {{/threetenbp}} testCompile 'junit:junit:4.13' } diff --git a/libraries/okhttp-gson/build.sbt.mustache b/libraries/okhttp-gson/build.sbt.mustache index 7c137589e37..43907462202 100644 --- a/libraries/okhttp-gson/build.sbt.mustache +++ b/libraries/okhttp-gson/build.sbt.mustache @@ -9,11 +9,11 @@ lazy val root = (project in file(".")). publishArtifact in (Compile, packageDoc) := false, resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( - "io.swagger" % "swagger-annotations" % "1.5.24", - "com.squareup.okhttp3" % "okhttp" % "3.14.7", - "com.squareup.okhttp3" % "logging-interceptor" % "3.14.7", - "com.google.code.gson" % "gson" % "2.8.6", - "org.apache.commons" % "commons-lang3" % "3.10", + "io.swagger" % "swagger-annotations" % "1.5.22", + "com.squareup.okhttp3" % "okhttp" % "3.14.2", + "com.squareup.okhttp3" % "logging-interceptor" % "3.14.2", + "com.google.code.gson" % "gson" % "2.8.5", + "org.apache.commons" % "commons-lang3" % "3.9", {{#hasOAuthMethods}} "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1", {{/hasOAuthMethods}} @@ -21,11 +21,10 @@ lazy val root = (project in file(".")). "joda-time" % "joda-time" % "2.9.9" % "compile", {{/joda}} {{#threetenbp}} - "org.threeten" % "threetenbp" % "1.4.3" % "compile", + "org.threeten" % "threetenbp" % "1.4.0" % "compile", {{/threetenbp}} "io.gsonfire" % "gson-fire" % "1.8.3" % "compile", - "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", - "com.google.code.findbugs" % "jsr305" % "3.0.2" % "compile", + "javax.annotation" % "jsr250-api" % "1.0" % "compile", "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index b6d67f28350..e4c05f4151d 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -40,20 +40,6 @@ - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - true - 128m - 512m - - -Xlint:all - -J-Xss4m - - - org.apache.maven.plugins maven-enforcer-plugin @@ -77,7 +63,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M4 + 2.12 @@ -87,7 +73,7 @@ -Xms512m -Xmx1500m methods - 10 + pertest @@ -156,7 +142,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.1.1 + 2.10.4 attach-javadocs @@ -166,7 +152,6 @@ - none http.response.details @@ -307,7 +292,7 @@ {{/parcelableModel}} javax.annotation - javax.annotation-api + jsr250-api ${javax-annotation-version} @@ -322,18 +307,19 @@ {{#supportJava6}}1.6{{/supportJava6}}{{^supportJava6}}{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}{{/supportJava6}} ${java.version} ${java.version} - 1.8.4 - 1.5.24 - 3.14.7 - 2.8.6 - 3.10 + 1.8.3 + 1.5.22 + 3.14.2 + 2.8.5 + 3.9 {{#joda}} 2.9.9 {{/joda}} {{#threetenbp}} - 1.4.3 + 1.4.0 {{/threetenbp}} - 1.3.2 + 1.0.0 + 1.0 4.13 UTF-8 diff --git a/libraries/rest-assured/build.gradle.mustache b/libraries/rest-assured/build.gradle.mustache index 640ad1cd18c..b04e53f1e96 100644 --- a/libraries/rest-assured/build.gradle.mustache +++ b/libraries/rest-assured/build.gradle.mustache @@ -96,24 +96,24 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.21" - rest_assured_version = "4.3.0" + rest_assured_version = "4.0.0" junit_version = "4.13" {{#jackson}} - jackson_version = "2.10.3" - jackson_databind_version = "2.10.3" + jackson_version = "2.10.1" + jackson_databind_version = "2.9.10" jackson_databind_nullable_version = 0.2.1 {{/jackson}} {{#gson}} - gson_version = "2.8.6" - gson_fire_version = "1.8.4" + gson_version = "2.8.5" + gson_fire_version = "1.8.3" {{/gson}} {{#joda}} - jodatime_version = "2.10.5" + jodatime_version = "2.9.9" {{/joda}} {{#threetenbp}} - threetenbp_version = "1.4.3" + threetenbp_version = "1.4.0" {{/threetenbp}} - okio_version = "1.17.5" + okio_version = "1.13.0" } dependencies { @@ -138,11 +138,5 @@ dependencies { compile "org.threeten:threetenbp:$threetenbp_version" {{/threetenbp}} compile "com.squareup.okio:okio:$okio_version" -{{#useBeanValidation}} - compile "javax.validation:validation-api:2.0.1.Final" -{{/useBeanValidation}} -{{#performBeanValidation}} - compile "org.hibernate:hibernate-validator:6.0.19.Final" -{{/performBeanValidation}} testCompile "junit:junit:$junit_version" } diff --git a/libraries/rest-assured/build.sbt.mustache b/libraries/rest-assured/build.sbt.mustache index 77f8af4f436..71f2eaeeba2 100644 --- a/libraries/rest-assured/build.sbt.mustache +++ b/libraries/rest-assured/build.sbt.mustache @@ -10,29 +10,23 @@ lazy val root = (project in file(".")). resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( "io.swagger" % "swagger-annotations" % "1.5.21", - "io.rest-assured" % "scala-support" % "4.3.0", + "io.rest-assured" % "scala-support" % "4.0.0", {{#jackson}} - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.9.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.9" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.9" % "compile", {{/jackson}} {{#gson}} - "com.google.code.gson" % "gson" % "2.8.6", - "io.gsonfire" % "gson-fire" % "1.8.4" % "compile", + "com.google.code.gson" % "gson" % "2.8.5", + "io.gsonfire" % "gson-fire" % "1.8.3" % "compile", {{/gson}} {{#joda}} - "joda-time" % "joda-time" % "2.10.5" % "compile", + "joda-time" % "joda-time" % "2.9.9" % "compile", {{/joda}} {{#threetenbp}} - "org.threeten" % "threetenbp" % "1.4.3" % "compile", + "org.threeten" % "threetenbp" % "1.4.0" % "compile", {{/threetenbp}} - "com.squareup.okio" % "okio" % "1.17.5" % "compile", -{{#useBeanValidation}} - "javax.validation" % "validation-api" % "2.0.1.Final" % "compile", -{{/useBeanValidation}} -{{#performBeanValidation}} - "org.hibernate" % "hibernate-validator" "6.0.19.Final" % "compile", -{{/performBeanValidation}} + "com.squareup.okio" % "okio" % "1.13.0" % "compile", "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) diff --git a/libraries/rest-assured/pom.mustache b/libraries/rest-assured/pom.mustache index 2e68695d431..9c49fb07774 100644 --- a/libraries/rest-assured/pom.mustache +++ b/libraries/rest-assured/pom.mustache @@ -43,7 +43,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.0.0-M3 + 3.0.0-M1 enforce-maven @@ -53,7 +53,7 @@ - 3.0.5 + 2.2.0 @@ -63,7 +63,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.22.2 + 2.12 @@ -71,8 +71,9 @@ conf/log4j.properties - false - 1C + -Xms512m -Xmx1500m + methods + pertest @@ -110,7 +111,6 @@ org.codehaus.mojo build-helper-maven-plugin - 3.1.0 add_sources @@ -141,7 +141,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.6.1 1.8 1.8 @@ -150,10 +150,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.2.0 - - none - + 2.10.4 attach-javadocs @@ -166,7 +163,7 @@ org.apache.maven.plugins maven-source-plugin - 3.2.0 + 2.2.1 attach-sources @@ -187,7 +184,7 @@ org.apache.maven.plugins maven-gpg-plugin - 1.6 + 1.5 sign-artifacts @@ -203,20 +200,6 @@ - {{#jackson}} - - - - com.fasterxml.jackson - jackson-bom - ${jackson-version} - pom - import - - - - {{/jackson}} - io.swagger @@ -229,14 +212,6 @@ jsr305 3.0.2 - {{^hideGenerationTimestamp}} - - javax.annotation - javax.annotation-api - 1.3.2 - provided - - {{/hideGenerationTimestamp}} io.rest-assured rest-assured @@ -275,14 +250,17 @@ com.fasterxml.jackson.core jackson-core + ${jackson-version} com.fasterxml.jackson.core jackson-annotations + ${jackson-version} com.fasterxml.jackson.core jackson-databind + ${jackson-databind-version} org.openapitools @@ -293,18 +271,21 @@ com.fasterxml.jackson.dataformat jackson-dataformat-xml + ${jackson-version} {{/withXml}} {{#joda}} com.fasterxml.jackson.datatype jackson-datatype-joda + ${jackson-version} {{/joda}} {{#java8}} com.fasterxml.jackson.datatype jackson-datatype-jsr310 + ${jackson-version} {{/java8}} {{#threetenbp}} @@ -320,23 +301,6 @@ okio ${okio-version} - {{#useBeanValidation}} - - - javax.validation - validation-api - 2.0.1.Final - provided - - {{/useBeanValidation}} - {{#performBeanValidation}} - - - org.hibernate - hibernate-validator - 6.0.19.Final - - {{/performBeanValidation}} junit @@ -348,23 +312,25 @@ UTF-8 1.5.21 - 4.3.0 - 2.8.6 - 1.8.4 + 4.0.0 + 2.8.5 + 1.8.3 + 1.0.0 {{#joda}} - 2.10.5 + 2.9.9 {{/joda}} {{#threetenbp}} - 1.4.3 + 1.4.0 {{/threetenbp}} {{#jackson}} - 2.10.3 + 2.10.1 + 2.9.10 0.2.1 {{#threetenbp}} - 2.10.0 + 2.9.10 {{/threetenbp}} {{/jackson}} - 1.17.5 + 1.13.0 4.13 diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index 89c6fb24ee4..59a0970f358 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -119,8 +119,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.10.3" - jackson_databind_version = "2.10.3" + jackson_version = "2.10.1" + jackson_databind_version = "2.10.1" jackson_databind_nullable_version = "0.2.1" threetenbp_version = "2.9.10" resteasy_version = "3.1.3.Final" diff --git a/libraries/resteasy/build.sbt.mustache b/libraries/resteasy/build.sbt.mustache index 351c072616f..936c4141f8f 100644 --- a/libraries/resteasy/build.sbt.mustache +++ b/libraries/resteasy/build.sbt.mustache @@ -13,9 +13,9 @@ lazy val root = (project in file(".")). "org.jboss.resteasy" % "resteasy-client" % "3.1.3.Final" % "compile", "org.jboss.resteasy" % "resteasy-multipart-provider" % "3.1.3.Final" % "compile", "org.jboss.resteasy" % "resteasy-jackson2-provider" % "3.1.3.Final" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.1" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", {{#java8}} "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.10" % "compile", diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index 714f4299b74..e3e127020e4 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -161,10 +161,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.1.1 - - none - + 2.10.4 attach-javadocs @@ -297,8 +294,8 @@ UTF-8 1.5.22 3.1.3.Final - 2.10.3 - 2.10.3 + 2.10.1 + 2.10.1 0.2.1 2.9.10 {{^java8}} diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index c61825adbb9..33d09ae8305 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -120,8 +120,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.10.3" - jackson_databind_version = "2.10.3" + jackson_version = "2.10.1" + jackson_databind_version = "2.10.1" jackson_databind_nullable_version = "0.2.1" spring_web_version = "4.3.9.RELEASE" jodatime_version = "2.9.9" diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache index c9f02fffca4..1f5e82d501f 100644 --- a/libraries/resttemplate/pom.mustache +++ b/libraries/resttemplate/pom.mustache @@ -163,10 +163,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.1.1 - - none - + 2.10.4 attach-javadocs @@ -312,8 +309,8 @@ UTF-8 1.5.22 4.3.9.RELEASE - 2.10.3 - 2.10.3 + 2.10.1 + 2.10.1 0.2.1 {{#joda}} 2.9.9 diff --git a/libraries/retrofit/pom.mustache b/libraries/retrofit/pom.mustache index 7c689ae4b6c..5a40a07979c 100644 --- a/libraries/retrofit/pom.mustache +++ b/libraries/retrofit/pom.mustache @@ -163,10 +163,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.1.1 - - none - + 2.10.4 attach-javadocs diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index 82f7974062b..ea96f094165 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -131,8 +131,8 @@ ext { play_version = "2.5.14" {{/play25}} {{#play26}} - jackson_version = "2.10.3" - jackson_databind_version = "2.10.3" + jackson_version = "2.10.1" + jackson_databind_version = "2.10.1" jackson_databind_nullable_version = "0.2.1" play_version = "2.6.7" {{/play26}} diff --git a/libraries/retrofit2/build.sbt.mustache b/libraries/retrofit2/build.sbt.mustache index f7b7ce464d5..be45635e47f 100644 --- a/libraries/retrofit2/build.sbt.mustache +++ b/libraries/retrofit2/build.sbt.mustache @@ -23,16 +23,16 @@ lazy val root = (project in file(".")). {{/play24}} {{#play25}} "com.typesafe.play" % "play-java-ws_2.11" % "2.5.15" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.1" % "compile", {{/play25}} {{#play26}} "com.typesafe.play" % "play-ahc-ws_2.12" % "2.6.7" % "compile", "javax.validation" % "validation-api" % "1.1.0.Final" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10" % "compile", {{/play26}} "com.squareup.retrofit2" % "converter-jackson" % "2.3.0" % "compile", {{/usePlayWS}} diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index 06f19bcb034..9613f948416 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -142,10 +142,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.1.1 - - none - + 2.10.4 attach-javadocs @@ -378,17 +375,17 @@ 1.8.3 1.5.22 {{#usePlayWS}} - 2.10.3 + 2.10.1 {{#play24}} 2.6.6 2.4.11 {{/play24}} {{#play25}} - 2.10.3 + 2.10.1 2.5.15 {{/play25}} {{#play26}} - 2.10.3 + 2.10.1 2.6.7 {{/play26}} 0.2.1 diff --git a/libraries/vertx/build.gradle.mustache b/libraries/vertx/build.gradle.mustache index 02760c59149..53bc7b9a8e5 100644 --- a/libraries/vertx/build.gradle.mustache +++ b/libraries/vertx/build.gradle.mustache @@ -28,8 +28,8 @@ task execute(type:JavaExec) { ext { swagger_annotations_version = "1.5.21" - jackson_version = "2.10.3" - jackson_databind_version = "2.10.3" + jackson_version = "2.10.1" + jackson_databind_version = "2.10.1" vertx_version = "3.4.2" junit_version = "4.13" } diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache index b3539c9fd77..3ed8b93b490 100644 --- a/libraries/vertx/pom.mustache +++ b/libraries/vertx/pom.mustache @@ -151,10 +151,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.1.1 - - none - + 2.10.4 attach-javadocs @@ -292,8 +289,8 @@ UTF-8 3.4.2 1.5.22 - 2.10.3 - 2.10.3 + 2.10.1 + 2.10.1 0.2.1 4.13 diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index 72b80bac81a..e21f3847641 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -556,10 +556,22 @@ public class ApiClient { final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(path); if (queryParams != null) { + //encode the query parameters in case they contain unsafe characters + for (List values : queryParams.values()) { + if (values != null) { + for (int i = 0; i < values.size(); i++) { + try { + values.set(i, URLEncoder.encode(values.get(i), "utf8")); + } catch (UnsupportedEncodingException e) { + + } + } + } + } builder.queryParams(queryParams); } - final WebClient.RequestBodySpec requestBuilder = webClient.method(method).uri(builder.build(false).toUriString(), pathParams); + final WebClient.RequestBodySpec requestBuilder = webClient.method(method).uri(builder.encode().toUriString(), pathParams); if(accept != null) { requestBuilder.accept(accept.toArray(new MediaType[accept.size()])); } diff --git a/libraries/webclient/api.mustache b/libraries/webclient/api.mustache index b852e87ec4e..9138d7d2e7a 100644 --- a/libraries/webclient/api.mustache +++ b/libraries/webclient/api.mustache @@ -4,13 +4,11 @@ import {{invokerPackage}}.ApiClient; {{#imports}}import {{import}}; {{/imports}} -{{^fullJavaUtil}} -import java.util.HashMap; +{{^fullJavaUtil}}import java.util.HashMap; import java.util.List; import java.util.Locale; -import java.util.Map; -{{/fullJavaUtil}} +import java.util.Map;{{/fullJavaUtil}} import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.LinkedMultiValueMap; @@ -64,68 +62,49 @@ public class {{classname}} { */ public {{#returnType}}{{#isListContainer}}Flux<{{{returnBaseType}}}>{{/isListContainer}}{{^isListContainer}}Mono<{{{returnType}}}>{{/isListContainer}} {{/returnType}}{{^returnType}}Mono {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { Object postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; - {{#allParams}} - {{#required}} + {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); } - {{/required}} - {{/allParams}} + {{/required}}{{/allParams}} // create path and map variables - final Map pathParams = new HashMap(); - {{#hasPathParams}} + final Map pathParams = new HashMap();{{#hasPathParams}}{{#pathParams}} + pathParams.put("{{baseName}}", {{#collectionFormat}}apiClient.collectionPathParameterToString(ApiClient.CollectionFormat.valueOf("csv".toUpperCase()), {{/collectionFormat}}{{{paramName}}}{{#collectionFormat}}){{/collectionFormat}});{{/pathParams}}{{/hasPathParams}} - {{#pathParams}} - pathParams.put("{{baseName}}", {{#collectionFormat}}apiClient.collectionPathParameterToString(ApiClient.CollectionFormat.valueOf("csv".toUpperCase()), {{/collectionFormat}}{{{paramName}}}{{#collectionFormat}}){{/collectionFormat}}); - {{/pathParams}} - {{/hasPathParams}} final MultiValueMap queryParams = new LinkedMultiValueMap(); final HttpHeaders headerParams = new HttpHeaders(); final MultiValueMap cookieParams = new LinkedMultiValueMap(); - final MultiValueMap formParams = new LinkedMultiValueMap(); - {{#hasQueryParams}} + final MultiValueMap formParams = new LinkedMultiValueMap();{{#hasQueryParams}} - {{#queryParams}} - queryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}})); - {{/queryParams}} - {{/hasQueryParams}} - {{#hasHeaderParams}} + {{#queryParams}}queryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{#hasMore}} + {{/hasMore}}{{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}} - {{#headerParams}} - if ({{paramName}} != null) + {{#headerParams}}if ({{paramName}} != null) headerParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{#hasMore}} - {{/hasMore}} - {{/headerParams}} - {{/hasHeaderParams}} - {{#hasCookieParams}} - - {{#cookieParams}} - cookieParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}})); - {{/cookieParams}} - {{/hasCookieParams}} - {{#hasFormParams}} - - {{#formParams}} - if ({{paramName}} != null) - formParams.add{{#collectionFormat}}All{{/collectionFormat}}("{{baseName}}", {{#isFile}}new FileSystemResource({{paramName}}){{/isFile}}{{^isFile}}{{paramName}}{{/isFile}}); - {{/formParams}} - {{/hasFormParams}} - - final String[] localVarAccepts = { {{#hasProduces}} + {{/hasMore}}{{/headerParams}}{{/hasHeaderParams}}{{#hasCookieParams}} + + {{#cookieParams}}cookieParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{#hasMore}} + {{/hasMore}}{{/cookieParams}}{{/hasCookieParams}}{{#hasFormParams}} + + {{#formParams}}if ({{paramName}} != null) + formParams.add{{#collectionFormat}}All{{/collectionFormat}}("{{baseName}}", {{#isFile}}new FileSystemResource({{paramName}}){{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} + {{/hasMore}}{{/formParams}}{{/hasFormParams}} + + final String[] accepts = { {{#hasProduces}} {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} {{/hasProduces}}}; - final List localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); - final String[] localVarContentTypes = { {{#hasConsumes}} + final List accept = apiClient.selectHeaderAccept(accepts); + final String[] contentTypes = { {{#hasConsumes}} {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} {{/hasConsumes}}}; - final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); + final MediaType contentType = apiClient.selectHeaderContentType(contentTypes); - String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + String[] authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; - {{#returnType}}ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}> localVarReturnType = new ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference localVarReturnType = new ParameterizedTypeReference() {};{{/returnType}} - return apiClient.{{#isListContainer}}invokeFluxAPI{{/isListContainer}}{{^isListContainer}}invokeAPI{{/isListContainer}}("{{{path}}}", HttpMethod.{{httpMethod}}, pathParams, queryParams, postBody, headerParams, cookieParams, formParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType); + {{#returnType}}ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}> returnType = new ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference returnType = new ParameterizedTypeReference() {};{{/returnType}} + return apiClient.{{#isListContainer}}invokeFluxAPI{{/isListContainer}}{{^isListContainer}}invokeAPI{{/isListContainer}}("{{{path}}}", HttpMethod.{{httpMethod}}, pathParams, queryParams, postBody, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType); } {{/operation}} } diff --git a/libraries/webclient/pom.mustache b/libraries/webclient/pom.mustache index 138270ea3f9..39cd7729c35 100644 --- a/libraries/webclient/pom.mustache +++ b/libraries/webclient/pom.mustache @@ -143,8 +143,8 @@ UTF-8 1.5.22 5.0.16.RELEASE - 2.10.3 - 2.10.3 + 2.10.1 + 2.10.1 0.2.1 4.13 3.1.8.RELEASE diff --git a/model.mustache b/model.mustache index d4d1447a1d4..8763e3bd08b 100644 --- a/model.mustache +++ b/model.mustache @@ -42,6 +42,6 @@ import org.hibernate.validator.constraints.*; {{#models}} {{#model}} -{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{#vendorExtensions.x-is-one-of-interface}}{{>oneof_interface}}{{/vendorExtensions.x-is-one-of-interface}}{{^vendorExtensions.x-is-one-of-interface}}{{>pojo}}{{/vendorExtensions.x-is-one-of-interface}}{{/isEnum}} +{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{#vendorExtensions.isOneOfInterface}}{{>oneof_interface}}{{/vendorExtensions.isOneOfInterface}}{{^vendorExtensions.isOneOfInterface}}{{>pojo}}{{/vendorExtensions.isOneOfInterface}}{{/isEnum}} {{/model}} {{/models}} diff --git a/model_test.mustache b/model_test.mustache index 07468db5657..0258f350074 100644 --- a/model_test.mustache +++ b/model_test.mustache @@ -21,7 +21,7 @@ import java.util.Map; public class {{classname}}Test { {{#models}} {{#model}} - {{^vendorExtensions.x-is-one-of-interface}} + {{^vendorExtensions.isOneOfInterface}} {{^isEnum}} private final {{classname}} model = new {{classname}}(); @@ -44,7 +44,7 @@ public class {{classname}}Test { } {{/allVars}} - {{/vendorExtensions.x-is-one-of-interface}} + {{/vendorExtensions.isOneOfInterface}} {{/model}} {{/models}} } diff --git a/oneof_interface.mustache b/oneof_interface.mustache index 02deb483d5f..c17cf0b31ca 100644 --- a/oneof_interface.mustache +++ b/oneof_interface.mustache @@ -1,5 +1,5 @@ {{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>typeInfoAnnotation}}{{>xmlAnnotation}} -public interface {{classname}} {{#vendorExtensions.x-implements}}{{#-first}}extends {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.x-implements}} { +public interface {{classname}} {{#vendorExtensions.implements}}{{#-first}}extends {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.implements}} { {{#discriminator}} public {{propertyType}} {{propertyGetter}}(); {{/discriminator}} diff --git a/openapi.mustache b/openapi.mustache deleted file mode 100644 index 34fbb53f331..00000000000 --- a/openapi.mustache +++ /dev/null @@ -1 +0,0 @@ -{{{openapi-yaml}}} diff --git a/pojo.mustache b/pojo.mustache index c438cd43eb7..3386b1b969a 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -10,7 +10,7 @@ }) {{/jackson}} {{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} -public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{ +public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorExtensions.implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.implements}}{ {{#serializableModel}} private static final long serialVersionUID = 1L; @@ -56,22 +56,22 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{#gson}} @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}}) {{/gson}} - {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#vendorExtensions.isJacksonOptionalNullable}} {{#isContainer}} private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined(); {{/isContainer}} {{^isContainer}} private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; {{/isContainer}} - {{/vendorExtensions.x-is-jackson-optional-nullable}} - {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{/vendorExtensions.isJacksonOptionalNullable}} + {{^vendorExtensions.isJacksonOptionalNullable}} {{#isContainer}} private {{{datatypeWithEnum}}} {{name}}{{#required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/required}}{{^required}} = null{{/required}}; {{/isContainer}} {{^isContainer}} private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; {{/isContainer}} - {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{/vendorExtensions.isJacksonOptionalNullable}} {{/vars}} {{#parcelableModel}} @@ -99,14 +99,14 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{^isReadOnly}} public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { - {{#vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});{{/vendorExtensions.x-is-jackson-optional-nullable}} - {{^vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = {{name}};{{/vendorExtensions.x-is-jackson-optional-nullable}} + {{#vendorExtensions.isJacksonOptionalNullable}}this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});{{/vendorExtensions.isJacksonOptionalNullable}} + {{^vendorExtensions.isJacksonOptionalNullable}}this.{{name}} = {{name}};{{/vendorExtensions.isJacksonOptionalNullable}} return this; } {{#isListContainer}} public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { - {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#vendorExtensions.isJacksonOptionalNullable}} if (this.{{name}} == null || !this.{{name}}.isPresent()) { this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); } @@ -116,8 +116,8 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE // this can never happen, as we make sure above that the value is present } return this; - {{/vendorExtensions.x-is-jackson-optional-nullable}} - {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{/vendorExtensions.isJacksonOptionalNullable}} + {{^vendorExtensions.isJacksonOptionalNullable}} {{^required}} if (this.{{name}} == null) { this.{{name}} = {{{defaultValue}}}; @@ -125,13 +125,13 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{/required}} this.{{name}}.add({{name}}Item); return this; - {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{/vendorExtensions.isJacksonOptionalNullable}} } {{/isListContainer}} {{#isMapContainer}} public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { - {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#vendorExtensions.isJacksonOptionalNullable}} if (this.{{name}} == null || !this.{{name}}.isPresent()) { this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); } @@ -141,8 +141,8 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE // this can never happen, as we make sure above that the value is present } return this; - {{/vendorExtensions.x-is-jackson-optional-nullable}} - {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{/vendorExtensions.isJacksonOptionalNullable}} + {{^vendorExtensions.isJacksonOptionalNullable}} {{^required}} if (this.{{name}} == null) { this.{{name}} = {{{defaultValue}}}; @@ -150,7 +150,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{/required}} this.{{name}}.put(key, {{name}}Item); return this; - {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{/vendorExtensions.isJacksonOptionalNullable}} } {{/isMapContainer}} @@ -179,49 +179,49 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE @javax.annotation.Nullable {{/required}} {{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} @ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") -{{#vendorExtensions.x-extra-annotation}} - {{{vendorExtensions.x-extra-annotation}}} -{{/vendorExtensions.x-extra-annotation}} -{{#vendorExtensions.x-is-jackson-optional-nullable}} +{{#vendorExtensions.extraAnnotation}} + {{{vendorExtensions.extraAnnotation}}} +{{/vendorExtensions.extraAnnotation}} +{{#vendorExtensions.isJacksonOptionalNullable}} {{!unannotated, Jackson would pick this up automatically and add it *in addition* to the _JsonNullable getter field}} @JsonIgnore -{{/vendorExtensions.x-is-jackson-optional-nullable}} -{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#jackson}}{{> jackson_annotations}}{{/jackson}}{{/vendorExtensions.x-is-jackson-optional-nullable}} +{{/vendorExtensions.isJacksonOptionalNullable}} +{{^vendorExtensions.isJacksonOptionalNullable}}{{#jackson}}{{> jackson_annotations}}{{/jackson}}{{/vendorExtensions.isJacksonOptionalNullable}} public {{{datatypeWithEnum}}} {{getter}}() { - {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#vendorExtensions.isJacksonOptionalNullable}} {{#isReadOnly}}{{! A readonly attribute doesn't have setter => jackson will set null directly if explicitly returned by API, so make sure we have an empty JsonNullable}} if ({{name}} == null) { {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; } {{/isReadOnly}} return {{name}}.orElse(null); - {{/vendorExtensions.x-is-jackson-optional-nullable}} - {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{/vendorExtensions.isJacksonOptionalNullable}} + {{^vendorExtensions.isJacksonOptionalNullable}} return {{name}}; - {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{/vendorExtensions.isJacksonOptionalNullable}} } - {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#vendorExtensions.isJacksonOptionalNullable}} {{> jackson_annotations}} public JsonNullable<{{{datatypeWithEnum}}}> {{getter}}_JsonNullable() { return {{name}}; } - {{/vendorExtensions.x-is-jackson-optional-nullable}}{{#vendorExtensions.x-is-jackson-optional-nullable}} + {{/vendorExtensions.isJacksonOptionalNullable}}{{#vendorExtensions.isJacksonOptionalNullable}} @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) {{#isReadOnly}}private{{/isReadOnly}}{{^isReadOnly}}public{{/isReadOnly}} void {{setter}}_JsonNullable(JsonNullable<{{{datatypeWithEnum}}}> {{name}}) { {{! For getters/setters that have name differing from attribute name, we must include setter (albeit private) for jackson to be able to set the attribute}} this.{{name}} = {{name}}; } - {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{/vendorExtensions.isJacksonOptionalNullable}} {{^isReadOnly}} public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { - {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#vendorExtensions.isJacksonOptionalNullable}} this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); - {{/vendorExtensions.x-is-jackson-optional-nullable}} - {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{/vendorExtensions.isJacksonOptionalNullable}} + {{^vendorExtensions.isJacksonOptionalNullable}} this.{{name}} = {{name}}; - {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{/vendorExtensions.isJacksonOptionalNullable}} } {{/isReadOnly}} diff --git a/pojo_doc.mustache b/pojo_doc.mustache index d9381323c87..e63db5e2720 100644 --- a/pojo_doc.mustache +++ b/pojo_doc.mustache @@ -1,8 +1,8 @@ -# {{#vendorExtensions.x-is-one-of-interface}}Interface {{/vendorExtensions.x-is-one-of-interface}}{{classname}} +# {{#vendorExtensions.isOneOfInterface}}Interface {{/vendorExtensions.isOneOfInterface}}{{classname}} {{#description}}{{&description}} {{/description}} -{{^vendorExtensions.x-is-one-of-interface}} +{{^vendorExtensions.isOneOfInterface}} ## Properties Name | Type | Description | Notes @@ -18,19 +18,19 @@ Name | Value ---- | -----{{#allowableValues}}{{#enumVars}} {{name}} | {{value}}{{/enumVars}}{{/allowableValues}} {{/isEnum}}{{/vars}} -{{#vendorExtensions.x-implements.0}} +{{#vendorExtensions.implements.0}} ## Implemented Interfaces -{{#vendorExtensions.x-implements}} +{{#vendorExtensions.implements}} * {{{.}}} -{{/vendorExtensions.x-implements}} -{{/vendorExtensions.x-implements.0}} -{{/vendorExtensions.x-is-one-of-interface}} -{{#vendorExtensions.x-is-one-of-interface}} +{{/vendorExtensions.implements}} +{{/vendorExtensions.implements.0}} +{{/vendorExtensions.isOneOfInterface}} +{{#vendorExtensions.isOneOfInterface}} ## Implementing Classes {{#oneOf}} * {{{.}}} {{/oneOf}} -{{/vendorExtensions.x-is-one-of-interface}} \ No newline at end of file +{{/vendorExtensions.isOneOfInterface}} \ No newline at end of file diff --git a/pom.mustache b/pom.mustache index e9cbf546b6d..b17b2357bad 100644 --- a/pom.mustache +++ b/pom.mustache @@ -40,21 +40,6 @@ - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - true - 128m - 512m - - -Xlint:all - -J-Xss4m - - - - org.apache.maven.plugins maven-enforcer-plugin @@ -178,10 +163,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.1.1 - - none - + 2.10.4 attach-javadocs @@ -307,7 +289,7 @@ com.github.joschi.jackson jackson-datatype-threetenbp - ${jackson-threetenbp-version} + ${jackson-version} {{/threetenbp}} {{^java8}} @@ -372,10 +354,7 @@ 2.5 3.6 {{/supportJava6}} - 2.10.3 - {{#threetenbp}} - 2.9.10 - {{/threetenbp}} + {{^threetenbp}}2.7.5{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} 1.0.0 4.13 From cfe65f7d8330018913aab938a18a1334f7d99cb9 Mon Sep 17 00:00:00 2001 From: "Francisco A. Lozano" Date: Thu, 23 Apr 2020 17:25:35 +0200 Subject: [PATCH 221/370] Change access updateParamsForAuth to protected (#5940) So that it can be overridden with a custom behaviour. --- libraries/resttemplate/ApiClient.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/resttemplate/ApiClient.mustache b/libraries/resttemplate/ApiClient.mustache index b160b7cca23..a2e66a62b61 100644 --- a/libraries/resttemplate/ApiClient.mustache +++ b/libraries/resttemplate/ApiClient.mustache @@ -716,7 +716,7 @@ public class ApiClient { * @param queryParams The query parameters * @param headerParams The header parameters */ - private void updateParamsForAuth(String[] authNames, MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams) { + protected void updateParamsForAuth(String[] authNames, MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams) { for (String authName : authNames) { Authentication auth = authentications.get(authName); if (auth == null) { From 32f74934fd00444bd568c7b8f88614468ab0a31b Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 24 Apr 2020 12:47:25 +0800 Subject: [PATCH 222/370] Add jersey2-experimental to Java client generator (#6024) * add jersey2 experimental * add new files * add abstract one of class * read the stream multiple times * rename to getActualInstance * update petstore * fix jackon check * test new java petstore in ci * fix broken tests * remove todo * better exception message, primitive type handling * add anyof support * update samples * add new files * update all java client samples * update doc, fix pom * better null check for allOf * add primitive types support in oneof, anyof * better validation * update python exp samples * remove primitive type support in allOf --- api_test.mustache | 22 +- .../AbstractOpenApiSchema.mustache | 30 + .../jersey2-experimental/ApiClient.mustache | 1072 +++++++++++++++++ .../jersey2-experimental/ApiResponse.mustache | 58 + libraries/jersey2-experimental/JSON.mustache | 65 + .../jersey2-experimental/anyof_model.mustache | 28 + libraries/jersey2-experimental/api.mustache | 244 ++++ .../apiException.mustache | 96 ++ .../jersey2-experimental/api_doc.mustache | 121 ++ .../jersey2-experimental/api_test.mustache | 51 + .../build.gradle.mustache | 170 +++ .../jersey2-experimental/build.sbt.mustache | 38 + libraries/jersey2-experimental/model.mustache | 47 + .../jersey2-experimental/oneof_model.mustache | 45 + libraries/jersey2-experimental/pojo.mustache | 369 ++++++ libraries/jersey2-experimental/pom.mustache | 372 ++++++ libraries/jersey2/pom.mustache | 2 +- 17 files changed, 2821 insertions(+), 9 deletions(-) create mode 100644 libraries/jersey2-experimental/AbstractOpenApiSchema.mustache create mode 100644 libraries/jersey2-experimental/ApiClient.mustache create mode 100644 libraries/jersey2-experimental/ApiResponse.mustache create mode 100644 libraries/jersey2-experimental/JSON.mustache create mode 100644 libraries/jersey2-experimental/anyof_model.mustache create mode 100644 libraries/jersey2-experimental/api.mustache create mode 100644 libraries/jersey2-experimental/apiException.mustache create mode 100644 libraries/jersey2-experimental/api_doc.mustache create mode 100644 libraries/jersey2-experimental/api_test.mustache create mode 100644 libraries/jersey2-experimental/build.gradle.mustache create mode 100644 libraries/jersey2-experimental/build.sbt.mustache create mode 100644 libraries/jersey2-experimental/model.mustache create mode 100644 libraries/jersey2-experimental/oneof_model.mustache create mode 100644 libraries/jersey2-experimental/pojo.mustache create mode 100644 libraries/jersey2-experimental/pom.mustache diff --git a/api_test.mustache b/api_test.mustache index 1d95ac2ed89..7011191c80a 100644 --- a/api_test.mustache +++ b/api_test.mustache @@ -7,39 +7,45 @@ import {{invokerPackage}}.ApiException; {{/imports}} import org.junit.Test; import org.junit.Ignore; +import org.junit.Assert; {{^fullJavaUtil}} import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -{{/fullJavaUtil}} +{{/fullJavaUtil}} /** * API tests for {{classname}} */ -@Ignore public class {{classname}}Test { private final {{classname}} api = new {{classname}}(); - {{#operations}}{{#operation}} + {{#operations}} + {{#operation}} /** + {{#summary}} * {{summary}} * + {{/summary}} + {{#notes}} * {{notes}} * + {{/notes}} * @throws ApiException * if the Api call fails */ @Test public void {{operationId}}Test() throws ApiException { - {{#allParams}} - {{{dataType}}} {{paramName}} = null; - {{/allParams}} - {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + //{{#allParams}} + //{{{dataType}}} {{paramName}} = null; + //{{/allParams}} + //{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); // TODO: test validations } - {{/operation}}{{/operations}} + {{/operation}} + {{/operations}} } diff --git a/libraries/jersey2-experimental/AbstractOpenApiSchema.mustache b/libraries/jersey2-experimental/AbstractOpenApiSchema.mustache new file mode 100644 index 00000000000..607c223aa26 --- /dev/null +++ b/libraries/jersey2-experimental/AbstractOpenApiSchema.mustache @@ -0,0 +1,30 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.model; + +import org.openapitools.client.ApiException; +import java.lang.reflect.Type; +import java.util.Map; +import javax.ws.rs.core.GenericType; + +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}} +public abstract class AbstractOpenApiSchema { + + private Object instance; + + public final String schemaType; + + public AbstractOpenApiSchema(String schemaType) { + this.schemaType = schemaType; + } + + public abstract Map getSchemas(); + + public Object getActualInstance() {return instance;} + + public void setActualInstance(Object instance) {this.instance = instance;} + + public String getSchemaType() { + return schemaType; + } +} diff --git a/libraries/jersey2-experimental/ApiClient.mustache b/libraries/jersey2-experimental/ApiClient.mustache new file mode 100644 index 00000000000..618264dc90c --- /dev/null +++ b/libraries/jersey2-experimental/ApiClient.mustache @@ -0,0 +1,1072 @@ +package {{invokerPackage}}; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.Form; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.glassfish.jersey.client.ClientConfig; +import org.glassfish.jersey.client.ClientProperties; +import org.glassfish.jersey.client.HttpUrlConnectorProvider; +import org.glassfish.jersey.jackson.JacksonFeature; +import org.glassfish.jersey.media.multipart.FormDataBodyPart; +import org.glassfish.jersey.media.multipart.FormDataContentDisposition; +import org.glassfish.jersey.media.multipart.MultiPart; +import org.glassfish.jersey.media.multipart.MultiPartFeature; + +import java.io.IOException; +import java.io.InputStream; + +{{^supportJava6}} +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import org.glassfish.jersey.logging.LoggingFeature; +{{/supportJava6}} +{{#supportJava6}} +import org.apache.commons.io.FileUtils; +import org.glassfish.jersey.filter.LoggingFilter; +{{/supportJava6}} +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Map.Entry; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Date; +import java.util.TimeZone; + +import java.net.URLEncoder; + +import java.io.File; +import java.io.UnsupportedEncodingException; + +import java.text.DateFormat; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import {{invokerPackage}}.auth.Authentication; +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.HttpBearerAuth; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.model.AbstractOpenApiSchema; + +{{#hasOAuthMethods}} +import {{invokerPackage}}.auth.OAuth; +{{/hasOAuthMethods}} + +{{>generatedAnnotation}} +public class ApiClient { + protected Map defaultHeaderMap = new HashMap(); + protected Map defaultCookieMap = new HashMap(); + protected String basePath = "{{{basePath}}}"; + protected List servers = new ArrayList({{#servers}}{{#-first}}Arrays.asList( +{{/-first}} new ServerConfiguration( + "{{{url}}}", + "{{{description}}}{{^description}}No description provided{{/description}}", + new HashMap(){{#variables}}{{#-first}} {{ +{{/-first}} put("{{{name}}}", new ServerVariable( + "{{{description}}}{{^description}}No description provided{{/description}}", + "{{{defaultValue}}}", + new HashSet( + {{#enumValues}} + {{#-first}} + Arrays.asList( + {{/-first}} + "{{{.}}}"{{^-last}},{{/-last}} + {{#-last}} + ) + {{/-last}} + {{/enumValues}} + ) + )); + {{#-last}} + }}{{/-last}}{{/variables}} + ){{^-last}},{{/-last}} + {{#-last}} + ){{/-last}}{{/servers}}); + protected Integer serverIndex = 0; + protected Map serverVariables = null; + protected Map> operationServers = new HashMap>() {{ + {{#apiInfo}} + {{#apis}} + {{#operations}} + {{#operation}} + {{#servers}} + {{#-first}} + put("{{{classname}}}.{{{operationId}}}", new ArrayList(Arrays.asList( + {{/-first}} + new ServerConfiguration( + "{{{url}}}", + "{{{description}}}{{^description}}No description provided{{/description}}", + new HashMap(){{#variables}}{{#-first}} {{ +{{/-first}} put("{{{name}}}", new ServerVariable( + "{{{description}}}{{^description}}No description provided{{/description}}", + "{{{defaultValue}}}", + new HashSet( + {{#enumValues}} + {{#-first}} + Arrays.asList( + {{/-first}} + "{{{.}}}"{{^-last}},{{/-last}} + {{#-last}} + ) + {{/-last}} + {{/enumValues}} + ) + )); + {{#-last}} + }}{{/-last}}{{/variables}} + ){{^-last}},{{/-last}} + {{#-last}} + )));{{/-last}} + {{/servers}} + {{/operation}} + {{/operations}} + {{/apis}} + {{/apiInfo}} + }}; + protected Map operationServerIndex = new HashMap(); + protected Map> operationServerVariables = new HashMap>(); + protected boolean debugging = false; + protected int connectionTimeout = 0; + private int readTimeout = 0; + + protected Client httpClient; + protected JSON json; + protected String tempFolderPath = null; + + protected Map authentications; + protected Map authenticationLookup; + + protected DateFormat dateFormat; + + public ApiClient() { + json = new JSON(); + httpClient = buildHttpClient(debugging); + + this.dateFormat = new RFC3339DateFormat(); + + // Set default User-Agent. + setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + + // Setup authentication lookup (key: authentication alias, value: authentication name) + authenticationLookup = new HashMap();{{#authMethods}}{{#vendorExtensions.x-auth-id-alias}} + authenticationLookup.put("{{name}}", "{{.}}");{{/vendorExtensions.x-auth-id-alias}}{{/authMethods}} + } + + /** + * Gets the JSON instance to do JSON serialization and deserialization. + * @return JSON + */ + public JSON getJSON() { + return json; + } + + public Client getHttpClient() { + return httpClient; + } + + public ApiClient setHttpClient(Client httpClient) { + this.httpClient = httpClient; + return this; + } + + public String getBasePath() { + return basePath; + } + + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + public List getServers() { + return servers; + } + + public ApiClient setServers(List servers) { + this.servers = servers; + return this; + } + + public Integer getServerIndex() { + return serverIndex; + } + + public ApiClient setServerIndex(Integer serverIndex) { + this.serverIndex = serverIndex; + return this; + } + + public Map getServerVariables() { + return serverVariables; + } + + public ApiClient setServerVariables(Map serverVariables) { + this.serverVariables = serverVariables; + return this; + } + + /** + * Get authentications (key: authentication name, value: authentication). + * @return Map of authentication object + */ + public Map getAuthentications() { + return authentications; + } + + /** + * Get authentication for the given name. + * + * @param authName The authentication name + * @return The authentication, null if not found + */ + public Authentication getAuthentication(String authName) { + return authentications.get(authName); + } + + /** + * Helper method to set username for the first HTTP basic authentication. + * @param username Username + */ + public void setUsername(String username) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setUsername(username); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set password for the first HTTP basic authentication. + * @param password Password + */ + public void setPassword(String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setPassword(password); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set API key value for the first API key authentication. + * @param apiKey API key + */ + public void setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to configure authentications which respects aliases of API keys. + * + * @param secrets Hash map from authentication name to its secret. + */ + public void configureApiKeys(HashMap secrets) { + for (Map.Entry authEntry : authentications.entrySet()) { + Authentication auth = authEntry.getValue(); + if (auth instanceof ApiKeyAuth) { + String name = authEntry.getKey(); + // respect x-auth-id-alias property + name = authenticationLookup.getOrDefault(name, name); + if (secrets.containsKey(name)) { + ((ApiKeyAuth) auth).setApiKey(secrets.get(name)); + } + } + } + } + + /** + * Helper method to set API key prefix for the first API key authentication. + * @param apiKeyPrefix API key prefix + */ + public void setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set bearer token for the first Bearer authentication. + * @param bearerToken Bearer token + */ + public void setBearerToken(String bearerToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBearerAuth) { + ((HttpBearerAuth) auth).setBearerToken(bearerToken); + return; + } + } + throw new RuntimeException("No Bearer authentication configured!"); + } + + {{#hasOAuthMethods}} + /** + * Helper method to set access token for the first OAuth2 authentication. + * @param accessToken Access token + */ + public void setAccessToken(String accessToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setAccessToken(accessToken); + return; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + {{/hasOAuthMethods}} + /** + * Set the User-Agent header's value (by adding to the default header map). + * @param userAgent Http user agent + * @return API client + */ + public ApiClient setUserAgent(String userAgent) { + addDefaultHeader("User-Agent", userAgent); + return this; + } + + /** + * Add a default header. + * + * @param key The header's key + * @param value The header's value + * @return API client + */ + public ApiClient addDefaultHeader(String key, String value) { + defaultHeaderMap.put(key, value); + return this; + } + + /** + * Add a default cookie. + * + * @param key The cookie's key + * @param value The cookie's value + * @return API client + */ + public ApiClient addDefaultCookie(String key, String value) { + defaultCookieMap.put(key, value); + return this; + } + + /** + * Check that whether debugging is enabled for this API client. + * @return True if debugging is switched on + */ + public boolean isDebugging() { + return debugging; + } + + /** + * Enable/disable debugging for this API client. + * + * @param debugging To enable (true) or disable (false) debugging + * @return API client + */ + public ApiClient setDebugging(boolean debugging) { + this.debugging = debugging; + // Rebuild HTTP Client according to the new "debugging" value. + this.httpClient = buildHttpClient(debugging); + return this; + } + + /** + * The path of temporary folder used to store downloaded files from endpoints + * with file response. The default value is null, i.e. using + * the system's default tempopary folder. + * + * @return Temp folder path + */ + public String getTempFolderPath() { + return tempFolderPath; + } + + /** + * Set temp folder path + * @param tempFolderPath Temp folder path + * @return API client + */ + public ApiClient setTempFolderPath(String tempFolderPath) { + this.tempFolderPath = tempFolderPath; + return this; + } + + /** + * Connect timeout (in milliseconds). + * @return Connection timeout + */ + public int getConnectTimeout() { + return connectionTimeout; + } + + /** + * Set the connect timeout (in milliseconds). + * A value of 0 means no timeout, otherwise values must be between 1 and + * {@link Integer#MAX_VALUE}. + * @param connectionTimeout Connection timeout in milliseconds + * @return API client + */ + public ApiClient setConnectTimeout(int connectionTimeout) { + this.connectionTimeout = connectionTimeout; + httpClient.property(ClientProperties.CONNECT_TIMEOUT, connectionTimeout); + return this; + } + + /** + * read timeout (in milliseconds). + * @return Read timeout + */ + public int getReadTimeout() { + return readTimeout; + } + + /** + * Set the read timeout (in milliseconds). + * A value of 0 means no timeout, otherwise values must be between 1 and + * {@link Integer#MAX_VALUE}. + * @param readTimeout Read timeout in milliseconds + * @return API client + */ + public ApiClient setReadTimeout(int readTimeout) { + this.readTimeout = readTimeout; + httpClient.property(ClientProperties.READ_TIMEOUT, readTimeout); + return this; + } + + /** + * Get the date format used to parse/format date parameters. + * @return Date format + */ + public DateFormat getDateFormat() { + return dateFormat; + } + + /** + * Set the date format used to parse/format date parameters. + * @param dateFormat Date format + * @return API client + */ + public ApiClient setDateFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + // also set the date format for model (de)serialization with Date properties + this.json.setDateFormat((DateFormat) dateFormat.clone()); + return this; + } + + /** + * Parse the given string into Date object. + * @param str String + * @return Date + */ + public Date parseDate(String str) { + try { + return dateFormat.parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(e); + } + } + + /** + * Format the given Date object into string. + * @param date Date + * @return Date in string format + */ + public String formatDate(Date date) { + return dateFormat.format(date); + } + + /** + * Format the given parameter object into string. + * @param param Object + * @return Object in string format + */ + public String parameterToString(Object param) { + if (param == null) { + return ""; + } else if (param instanceof Date) { + return formatDate((Date) param); + } else if (param instanceof Collection) { + StringBuilder b = new StringBuilder(); + for(Object o : (Collection)param) { + if(b.length() > 0) { + b.append(','); + } + b.append(String.valueOf(o)); + } + return b.toString(); + } else { + return String.valueOf(param); + } + } + + /* + * Format to {@code Pair} objects. + * @param collectionFormat Collection format + * @param name Name + * @param value Value + * @return List of pairs + */ + public List parameterToPairs(String collectionFormat, String name, Object value){ + List params = new ArrayList(); + + // preconditions + if (name == null || name.isEmpty() || value == null) return params; + + Collection valueCollection; + if (value instanceof Collection) { + valueCollection = (Collection) value; + } else { + params.add(new Pair(name, parameterToString(value))); + return params; + } + + if (valueCollection.isEmpty()){ + return params; + } + + // get the collection format (default: csv) + String format = (collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat); + + // create the params based on the collection format + if ("multi".equals(format)) { + for (Object item : valueCollection) { + params.add(new Pair(name, parameterToString(item))); + } + + return params; + } + + String delimiter = ","; + + if ("csv".equals(format)) { + delimiter = ","; + } else if ("ssv".equals(format)) { + delimiter = " "; + } else if ("tsv".equals(format)) { + delimiter = "\t"; + } else if ("pipes".equals(format)) { + delimiter = "|"; + } + + StringBuilder sb = new StringBuilder() ; + for (Object item : valueCollection) { + sb.append(delimiter); + sb.append(parameterToString(item)); + } + + params.add(new Pair(name, sb.substring(1))); + + return params; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * application/vnd.company+json + * "* / *" is also default to JSON + * @param mime MIME + * @return True if the MIME type is JSON + */ + public boolean isJsonMime(String mime) { + String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$"; + return mime != null && (mime.matches(jsonMime) || mime.equals("*/*")); + } + + /** + * Select the Accept header's value from the given accepts array: + * if JSON exists in the given array, use it; + * otherwise use all of them (joining into a string) + * + * @param accepts The accepts array to select from + * @return The Accept header to use. If the given array is empty, + * null will be returned (not to set the Accept header explicitly). + */ + public String selectHeaderAccept(String[] accepts) { + if (accepts.length == 0) { + return null; + } + for (String accept : accepts) { + if (isJsonMime(accept)) { + return accept; + } + } + return StringUtil.join(accepts, ","); + } + + /** + * Select the Content-Type header's value from the given array: + * if JSON exists in the given array, use it; + * otherwise use the first one of the array. + * + * @param contentTypes The Content-Type array to select from + * @return The Content-Type header to use. If the given array is empty, + * JSON will be used. + */ + public String selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0) { + return "application/json"; + } + for (String contentType : contentTypes) { + if (isJsonMime(contentType)) { + return contentType; + } + } + return contentTypes[0]; + } + + /** + * Escape the given string to be used as URL query value. + * @param str String + * @return Escaped string + */ + public String escapeString(String str) { + try { + return URLEncoder.encode(str, "utf8").replaceAll("\\+", "%20"); + } catch (UnsupportedEncodingException e) { + return str; + } + } + + /** + * Serialize the given Java object into string entity according the given + * Content-Type (only JSON is supported for now). + * @param obj Object + * @param formParams Form parameters + * @param contentType Context type + * @return Entity + * @throws ApiException API exception + */ + public Entity serialize(Object obj, Map formParams, String contentType) throws ApiException { + Entity entity; + if (contentType.startsWith("multipart/form-data")) { + MultiPart multiPart = new MultiPart(); + for (Entry param: formParams.entrySet()) { + if (param.getValue() instanceof File) { + File file = (File) param.getValue(); + FormDataContentDisposition contentDisp = FormDataContentDisposition.name(param.getKey()) + .fileName(file.getName()).size(file.length()).build(); + multiPart.bodyPart(new FormDataBodyPart(contentDisp, file, MediaType.APPLICATION_OCTET_STREAM_TYPE)); + } else { + FormDataContentDisposition contentDisp = FormDataContentDisposition.name(param.getKey()).build(); + multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(param.getValue()))); + } + } + entity = Entity.entity(multiPart, MediaType.MULTIPART_FORM_DATA_TYPE); + } else if (contentType.startsWith("application/x-www-form-urlencoded")) { + Form form = new Form(); + for (Entry param: formParams.entrySet()) { + form.param(param.getKey(), parameterToString(param.getValue())); + } + entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE); + } else { + // We let jersey handle the serialization + entity = Entity.entity(obj == null ? Entity.text("") : obj, contentType); + } + return entity; + } + + public AbstractOpenApiSchema deserializeSchemas(Response response, AbstractOpenApiSchema schema) throws ApiException{ + + Object result = null; + int matchCounter = 0; + ArrayList matchSchemas = new ArrayList<>(); + + for (Map.Entry entry : schema.getSchemas().entrySet()) { + String schemaName = entry.getKey(); + GenericType schemaType = entry.getValue(); + + if (schemaType instanceof GenericType) { // model + try { + Object deserializedObject = deserialize(response, schemaType); + if (deserializedObject != null) { + result = deserializedObject; + matchCounter++; + + if ("anyOf".equals(schema.getSchemaType())) { + break; + } else if ("oneOf".equals(schema.getSchemaType())) { + matchSchemas.add(schemaName); + } else { + throw new ApiException("Unknowe type found while expecting anyOf/oneOf:" + schema.getSchemaType()); + } + } else { + // failed to deserialize the response in the schema provided, proceed to the next one if any + } + } catch (Exception ex) { + // failed to deserialize, do nothing and try next one (schema) + } + } else {// unknown type + throw new ApiException(schemaType.getClass() + " is not a GenericType and cannot be handled properly in deserialization."); + } + + } + + if (matchCounter > 1 && "oneOf".equals(schema.getSchemaType())) {// more than 1 match for oneOf + throw new ApiException("Response body is invalid as it matches more than one schema (" + String.join(", ", matchSchemas) + ") defined in the oneOf model: " + schema.getClass().getName()); + } else if (matchCounter == 0) { // fail to match any in oneOf/anyOf schemas + throw new ApiException("Response body is invalid as it doens't match any schemas (" + String.join(", ", schema.getSchemas().keySet()) + ") defined in the oneOf/anyOf model: " + schema.getClass().getName()); + } else { // only one matched + schema.setActualInstance(result); + return schema; + } + + } + + + + /** + * Deserialize response body to Java object according to the Content-Type. + * @param Type + * @param response Response + * @param returnType Return type + * @return Deserialize object + * @throws ApiException API exception + */ + @SuppressWarnings("unchecked") + public T deserialize(Response response, GenericType returnType) throws ApiException { + if (response == null || returnType == null) { + return null; + } + + if ("byte[]".equals(returnType.toString())) { + // Handle binary response (byte array). + return (T) response.readEntity(byte[].class); + } else if (returnType.getRawType() == File.class) { + // Handle file downloading. + T file = (T) downloadFileFromResponse(response); + return file; + } + + String contentType = null; + List contentTypes = response.getHeaders().get("Content-Type"); + if (contentTypes != null && !contentTypes.isEmpty()) + contentType = String.valueOf(contentTypes.get(0)); + + // read the entity stream multiple times + response.bufferEntity(); + + return response.readEntity(returnType); + } + + /** + * Download file from the given response. + * @param response Response + * @return File + * @throws ApiException If fail to read file content from response and write to disk + */ + public File downloadFileFromResponse(Response response) throws ApiException { + try { + File file = prepareDownloadFile(response); +{{^supportJava6}} + Files.copy(response.readEntity(InputStream.class), file.toPath(), StandardCopyOption.REPLACE_EXISTING); +{{/supportJava6}} +{{#supportJava6}} + // Java6 falls back to commons.io for file copying + FileUtils.copyToFile(response.readEntity(InputStream.class), file); +{{/supportJava6}} + return file; + } catch (IOException e) { + throw new ApiException(e); + } + } + + public File prepareDownloadFile(Response response) throws IOException { + String filename = null; + String contentDisposition = (String) response.getHeaders().getFirst("Content-Disposition"); + if (contentDisposition != null && !"".equals(contentDisposition)) { + // Get filename from the Content-Disposition header. + Pattern pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?"); + Matcher matcher = pattern.matcher(contentDisposition); + if (matcher.find()) + filename = matcher.group(1); + } + + String prefix; + String suffix = null; + if (filename == null) { + prefix = "download-"; + suffix = ""; + } else { + int pos = filename.lastIndexOf('.'); + if (pos == -1) { + prefix = filename + "-"; + } else { + prefix = filename.substring(0, pos) + "-"; + suffix = filename.substring(pos); + } + // File.createTempFile requires the prefix to be at least three characters long + if (prefix.length() < 3) + prefix = "download-"; + } + + if (tempFolderPath == null) + return File.createTempFile(prefix, suffix); + else + return File.createTempFile(prefix, suffix, new File(tempFolderPath)); + } + + /** + * Invoke API by sending HTTP request with the given options. + * + * @param Type + * @param operation The qualified name of the operation + * @param path The sub-path of the HTTP URL + * @param method The request method, one of "GET", "POST", "PUT", "HEAD" and "DELETE" + * @param queryParams The query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param cookieParams The cookie parameters + * @param formParams The form parameters + * @param accept The request's Accept header + * @param contentType The request's Content-Type header + * @param authNames The authentications to apply + * @param returnType The return type into which to deserialize the response + * @param schema An instance of the response that uses oneOf/anyOf + * @return The response body in type of string + * @throws ApiException API exception + */ + public ApiResponse invokeAPI(String operation, String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType, AbstractOpenApiSchema schema) throws ApiException { + updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); + + // Not using `.target(targetURL).path(path)` below, + // to support (constant) query string in `path`, e.g. "/posts?draft=1" + String targetURL; + if (serverIndex != null) { + Integer index; + List serverConfigurations; + Map variables; + + if (operationServers.containsKey(operation)) { + index = operationServerIndex.getOrDefault(operation, serverIndex); + variables = operationServerVariables.getOrDefault(operation, serverVariables); + serverConfigurations = operationServers.get(operation); + } else { + index = serverIndex; + variables = serverVariables; + serverConfigurations = servers; + } + if (index < 0 || index >= serverConfigurations.size()) { + throw new ArrayIndexOutOfBoundsException(String.format( + "Invalid index %d when selecting the host settings. Must be less than %d", index, serverConfigurations.size() + )); + } + targetURL = serverConfigurations.get(index).URL(variables) + path; + } else { + targetURL = this.basePath + path; + } + WebTarget target = httpClient.target(targetURL); + + if (queryParams != null) { + for (Pair queryParam : queryParams) { + if (queryParam.getValue() != null) { + target = target.queryParam(queryParam.getName(), escapeString(queryParam.getValue())); + } + } + } + + Invocation.Builder invocationBuilder = target.request().accept(accept); + + for (Entry entry : headerParams.entrySet()) { + String value = entry.getValue(); + if (value != null) { + invocationBuilder = invocationBuilder.header(entry.getKey(), value); + } + } + + for (Entry entry : cookieParams.entrySet()) { + String value = entry.getValue(); + if (value != null) { + invocationBuilder = invocationBuilder.cookie(entry.getKey(), value); + } + } + + for (Entry entry : defaultCookieMap.entrySet()) { + String value = entry.getValue(); + if (value != null) { + invocationBuilder = invocationBuilder.cookie(entry.getKey(), value); + } + } + + for (Entry entry : defaultHeaderMap.entrySet()) { + String key = entry.getKey(); + if (!headerParams.containsKey(key)) { + String value = entry.getValue(); + if (value != null) { + invocationBuilder = invocationBuilder.header(key, value); + } + } + } + + Entity entity = serialize(body, formParams, contentType); + + Response response = null; + + try { + if ("GET".equals(method)) { + response = invocationBuilder.get(); + } else if ("POST".equals(method)) { + response = invocationBuilder.post(entity); + } else if ("PUT".equals(method)) { + response = invocationBuilder.put(entity); + } else if ("DELETE".equals(method)) { + response = invocationBuilder.method("DELETE", entity); + } else if ("PATCH".equals(method)) { + response = invocationBuilder.method("PATCH", entity); + } else if ("HEAD".equals(method)) { + response = invocationBuilder.head(); + } else if ("OPTIONS".equals(method)) { + response = invocationBuilder.options(); + } else if ("TRACE".equals(method)) { + response = invocationBuilder.trace(); + } else { + throw new ApiException(500, "unknown method type " + method); + } + + int statusCode = response.getStatusInfo().getStatusCode(); + Map> responseHeaders = buildResponseHeaders(response); + + if (response.getStatus() == Status.NO_CONTENT.getStatusCode()) { + return new ApiResponse<{{#supportJava6}}T{{/supportJava6}}>(statusCode, responseHeaders); + } else if (response.getStatusInfo().getFamily() == Status.Family.SUCCESSFUL) { + if (returnType == null) + return new ApiResponse<{{#supportJava6}}T{{/supportJava6}}>(statusCode, responseHeaders); + else + if (schema == null) { + return new ApiResponse<>(statusCode, responseHeaders, deserialize(response, returnType)); + } else { // oneOf/anyOf + return new ApiResponse<>(statusCode, responseHeaders, (T)deserializeSchemas(response, schema)); + } + } else { + String message = "error"; + String respBody = null; + if (response.hasEntity()) { + try { + respBody = String.valueOf(response.readEntity(String.class)); + message = respBody; + } catch (RuntimeException e) { + // e.printStackTrace(); + } + } + throw new ApiException( + response.getStatus(), + message, + buildResponseHeaders(response), + respBody); + } + } finally { + try { + response.close(); + } catch (Exception e) { + // it's not critical, since the response object is local in method invokeAPI; that's fine, just continue + } + } + } + + /** + * @deprecated Add qualified name of the operation as a first parameter. + */ + @Deprecated + public ApiResponse invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType, AbstractOpenApiSchema schema) throws ApiException { + return invokeAPI(null, path, method, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType, schema); + } + + /** + * Build the Client used to make HTTP requests. + * @param debugging Debug setting + * @return Client + */ + protected Client buildHttpClient(boolean debugging) { + final ClientConfig clientConfig = new ClientConfig(); + clientConfig.register(MultiPartFeature.class); + clientConfig.register(json); + clientConfig.register(JacksonFeature.class); + clientConfig.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true); + // turn off compliance validation to be able to send payloads with DELETE calls + clientConfig.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true); + if (debugging) { +{{^supportJava6}} + clientConfig.register(new LoggingFeature(java.util.logging.Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME), java.util.logging.Level.INFO, LoggingFeature.Verbosity.PAYLOAD_ANY, 1024*50 /* Log payloads up to 50K */)); + clientConfig.property(LoggingFeature.LOGGING_FEATURE_VERBOSITY, LoggingFeature.Verbosity.PAYLOAD_ANY); + // Set logger to ALL + java.util.logging.Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME).setLevel(java.util.logging.Level.ALL); +{{/supportJava6}} +{{#supportJava6}} + clientConfig.register(new LoggingFilter(java.util.logging.Logger.getLogger(LoggingFilter.class.getName()), true)); +{{/supportJava6}} + } else { + // suppress warnings for payloads with DELETE calls: + java.util.logging.Logger.getLogger("org.glassfish.jersey.client").setLevel(java.util.logging.Level.SEVERE); + } + performAdditionalClientConfiguration(clientConfig); + return ClientBuilder.newClient(clientConfig); + } + + protected void performAdditionalClientConfiguration(ClientConfig clientConfig) { + // No-op extension point + } + + protected Map> buildResponseHeaders(Response response) { + Map> responseHeaders = new HashMap>(); + for (Entry> entry: response.getHeaders().entrySet()) { + List values = entry.getValue(); + List headers = new ArrayList(); + for (Object o : values) { + headers.add(String.valueOf(o)); + } + responseHeaders.put(entry.getKey(), headers); + } + return responseHeaders; + } + + /** + * Update query and header parameters based on authentication settings. + * + * @param authNames The authentications to apply + * @param queryParams List of query parameters + * @param headerParams Map of header parameters + * @param cookieParams Map of cookie parameters + */ + protected void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams, Map cookieParams) { + for (String authName : authNames) { + Authentication auth = authentications.get(authName); + if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + auth.applyToParams(queryParams, headerParams, cookieParams); + } + } +} diff --git a/libraries/jersey2-experimental/ApiResponse.mustache b/libraries/jersey2-experimental/ApiResponse.mustache new file mode 100644 index 00000000000..a67b11f054c --- /dev/null +++ b/libraries/jersey2-experimental/ApiResponse.mustache @@ -0,0 +1,58 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import java.util.List; +import java.util.Map; +{{#caseInsensitiveResponseHeaders}} +import java.util.Map.Entry; +import java.util.TreeMap; +{{/caseInsensitiveResponseHeaders}} + +/** + * API response returned by API call. + * + * @param The type of data that is deserialized from response body + */ +public class ApiResponse { + private final int statusCode; + private final Map> headers; + private final T data; + + /** + * @param statusCode The status code of HTTP response + * @param headers The headers of HTTP response + */ + public ApiResponse(int statusCode, Map> headers) { + this(statusCode, headers, null); + } + + /** + * @param statusCode The status code of HTTP response + * @param headers The headers of HTTP response + * @param data The object deserialized from response bod + */ + public ApiResponse(int statusCode, Map> headers, T data) { + this.statusCode = statusCode; + {{#caseInsensitiveResponseHeaders}} + Map> responseHeaders = new TreeMap>(String.CASE_INSENSITIVE_ORDER); + for(Entry> entry : headers.entrySet()){ + responseHeaders.put(entry.getKey().toLowerCase(), entry.getValue()); + } + {{/caseInsensitiveResponseHeaders}} + this.headers = {{#caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}; + this.data = data; + } + + public int getStatusCode() { + return statusCode; + } + + public Map> getHeaders() { + return headers; + } + + public T getData() { + return data; + } +} diff --git a/libraries/jersey2-experimental/JSON.mustache b/libraries/jersey2-experimental/JSON.mustache new file mode 100644 index 00000000000..b442f0836da --- /dev/null +++ b/libraries/jersey2-experimental/JSON.mustache @@ -0,0 +1,65 @@ +package {{invokerPackage}}; + +{{#threetenbp}} +import org.threeten.bp.*; +{{/threetenbp}} +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.*; +import org.openapitools.jackson.nullable.JsonNullableModule; +{{#java8}} +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{/java8}} +{{#joda}} +import com.fasterxml.jackson.datatype.joda.JodaModule; +{{/joda}} +{{#threetenbp}} +import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; +{{/threetenbp}} + +import java.text.DateFormat; + +import javax.ws.rs.ext.ContextResolver; + +{{>generatedAnnotation}} +public class JSON implements ContextResolver { + private ObjectMapper mapper; + + public JSON() { + mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.setDateFormat(new RFC3339DateFormat()); + {{#java8}} + mapper.registerModule(new JavaTimeModule()); + {{/java8}} + {{#joda}} + mapper.registerModule(new JodaModule()); + {{/joda}} + {{#threetenbp}} + ThreeTenModule module = new ThreeTenModule(); + module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); + module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); + module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); + mapper.registerModule(module); + {{/threetenbp}} + JsonNullableModule jnm = new JsonNullableModule(); + mapper.registerModule(jnm); + } + + /** + * Set the date format for JSON (de)serialization with Date properties. + * @param dateFormat Date format + */ + public void setDateFormat(DateFormat dateFormat) { + mapper.setDateFormat(dateFormat); + } + + @Override + public ObjectMapper getContext(Class type) { + return mapper; + } +} diff --git a/libraries/jersey2-experimental/anyof_model.mustache b/libraries/jersey2-experimental/anyof_model.mustache new file mode 100644 index 00000000000..a3702d221ad --- /dev/null +++ b/libraries/jersey2-experimental/anyof_model.mustache @@ -0,0 +1,28 @@ +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.Response; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} +public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}}, {{{.}}}{{/vendorExtensions.x-implements}} { + + // store a list of schema names defined in anyOf + public final static Map schemas = new HashMap(); + + public {{classname}}() { + super("anyOf"); + } + + static { + {{#anyOf}} + schemas.put("{{{.}}}", new GenericType<{{{.}}}>() { + }); + {{/anyOf}} + } + + @Override + public Map getSchemas() { + return {{classname}}.schemas; + } +} diff --git a/libraries/jersey2-experimental/api.mustache b/libraries/jersey2-experimental/api.mustache new file mode 100644 index 00000000000..a0730135f71 --- /dev/null +++ b/libraries/jersey2-experimental/api.mustache @@ -0,0 +1,244 @@ +package {{package}}; + +import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.ApiResponse; +import {{invokerPackage}}.Configuration; +import {{invokerPackage}}.Pair; + +import javax.ws.rs.core.GenericType; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}} { + private ApiClient apiClient; + + public {{classname}}() { + this(Configuration.getDefaultApiClient()); + } + + public {{classname}}(ApiClient apiClient) { + this.apiClient = apiClient; + } + + public ApiClient getApiClient() { + return apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.apiClient = apiClient; + } + {{#operation}} + {{^vendorExtensions.x-group-parameters}} + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + {{#returnType}} + * @return {{returnType}} + {{/returnType}} + * @throws ApiException if fails to make API call + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + {{#returnType}}return {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#returnType}}.getData(){{/returnType}}; + } + {{/vendorExtensions.x-group-parameters}} + + {{^vendorExtensions.x-group-parameters}} + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @return ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + * @throws ApiException if fails to make API call + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + } + {{/required}}{{/allParams}} + // create path and map variables + String localVarPath = "{{{path}}}"{{#pathParams}} + .replaceAll("\\{" + "{{baseName}}" + "\\}", apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; + + // query params + {{javaUtilPrefix}}List localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}Map localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarCookieParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarFormParams = new {{javaUtilPrefix}}HashMap(); + + {{#queryParams}} + localVarQueryParams.addAll(apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); + {{/queryParams}} + + {{#headerParams}}if ({{paramName}} != null) + localVarHeaderParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); + {{/headerParams}} + + {{#cookieParams}}if ({{paramName}} != null) + localVarCookieParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); + {{/cookieParams}} + + {{#formParams}}if ({{paramName}} != null) + localVarFormParams.put("{{baseName}}", {{paramName}}); + {{/formParams}} + + final String[] localVarAccepts = { + {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} + }; + final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); + + final String[] localVarContentTypes = { + {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} + }; + final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); + + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + + {{#returnType}} + GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {}; + + {{/returnType}} + return apiClient.invokeAPI("{{classname}}.{{operationId}}", localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, + localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, + localVarAuthNames, {{#returnType}}localVarReturnType{{/returnType}}{{^returnType}}null{{/returnType}}, {{#vendorExtensions.x-java-return-type-one-of}}new {{{returnType}}}(){{/vendorExtensions.x-java-return-type-one-of}}{{^vendorExtensions.x-java-return-type-one-of}}{{#vendorExtensions.x-java-return-type-any-of}}new {{{returnType}}}(){{/vendorExtensions.x-java-return-type-any-of}}{{^vendorExtensions.x-java-return-type-any-of}}null{{/vendorExtensions.x-java-return-type-any-of}}{{/vendorExtensions.x-java-return-type-one-of}}); + } + {{#vendorExtensions.x-group-parameters}} + + public class API{{operationId}}Request { + {{#allParams}} + private {{#isRequired}}final {{/isRequired}}{{{dataType}}} {{localVariablePrefix}}{{paramName}}; + {{/allParams}} + + private API{{operationId}}Request({{#pathParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}) { + {{#pathParams}} + this.{{localVariablePrefix}}{{paramName}} = {{paramName}}; + {{/pathParams}} + } + {{#allParams}}{{^isPathParam}} + + /** + * Set {{paramName}} + * @param {{paramName}} {{description}} ({{^required}}optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}{{/required}}{{#required}}required{{/required}}) + * @return API{{operationId}}Request + */ + public API{{operationId}}Request {{paramName}}({{{dataType}}} {{paramName}}) { + this.{{localVariablePrefix}}{{paramName}} = {{paramName}}; + return this; + } + {{/isPathParam}}{{/allParams}} + + /** + * Execute {{operationId}} request + {{#returnType}}* @return {{.}}{{/returnType}} + * @throws ApiException if fails to make API call + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} + {{#isDeprecated}}* @deprecated{{/isDeprecated}} + */ + {{#isDeprecated}}@Deprecated{{/isDeprecated}} + public {{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}void{{/returnType}} execute() throws ApiException { + {{#returnType}}return {{/returnType}}this.executeWithHttpInfo().getData(); + } + + /** + * Execute {{operationId}} request with HTTP info returned + * @return ApiResponse<{{#returnType}}{{.}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + * @throws ApiException if fails to make API call + {{#responses.0}} + * @http.response.details + + + {{#responses}} + + {{/responses}} +
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
+ {{/responses.0}} + {{#isDeprecated}}* @deprecated{{/isDeprecated}} + */ + {{#isDeprecated}}@Deprecated{{/isDeprecated}} + public ApiResponse<{{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> executeWithHttpInfo() throws ApiException { + return {{operationId}}WithHttpInfo({{#allParams}}{{localVariablePrefix}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + } + } + + /** + * {{summary}} + * {{notes}}{{#pathParams}} + * @param {{paramName}} {{description}} (required){{/pathParams}} + * @return {{operationId}}Request + * @throws ApiException if fails to make API call + {{#isDeprecated}}* @deprecated{{/isDeprecated}} + {{#externalDocs}}* {{description}} + * @see {{summary}} Documentation{{/externalDocs}} + */ + {{#isDeprecated}}@Deprecated{{/isDeprecated}} + public API{{operationId}}Request {{operationId}}({{#pathParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}) throws ApiException { + return new API{{operationId}}Request({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}); + } + {{/vendorExtensions.x-group-parameters}} + {{/operation}} +} +{{/operations}} diff --git a/libraries/jersey2-experimental/apiException.mustache b/libraries/jersey2-experimental/apiException.mustache new file mode 100644 index 00000000000..e8952456591 --- /dev/null +++ b/libraries/jersey2-experimental/apiException.mustache @@ -0,0 +1,96 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import java.util.Map; +import java.util.List; +{{#caseInsensitiveResponseHeaders}} +import java.util.Map.Entry; +import java.util.TreeMap; +{{/caseInsensitiveResponseHeaders}} + +{{>generatedAnnotation}} +public class ApiException extends{{#useRuntimeException}} RuntimeException {{/useRuntimeException}}{{^useRuntimeException}} Exception {{/useRuntimeException}}{ + private int code = 0; + private Map> responseHeaders = null; + private String responseBody = null; + + public ApiException() {} + + public ApiException(Throwable throwable) { + super(throwable); + } + + public ApiException(String message) { + super(message); + } + + public ApiException(String message, Throwable throwable, int code, Map> responseHeaders, String responseBody) { + super(message, throwable); + this.code = code; + {{#caseInsensitiveResponseHeaders}} + Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER); + for(Entry> entry : responseHeaders.entrySet()){ + headers.put(entry.getKey().toLowerCase(), entry.getValue()); + } + {{/caseInsensitiveResponseHeaders}} + this.responseHeaders = {{#caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}; + this.responseBody = responseBody; + } + + public ApiException(String message, int code, Map> responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(String message, Throwable throwable, int code, Map> responseHeaders) { + this(message, throwable, code, responseHeaders, null); + } + + public ApiException(int code, Map> responseHeaders, String responseBody) { + this((String) null, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(int code, String message) { + super(message); + this.code = code; + } + + public ApiException(int code, String message, Map> responseHeaders, String responseBody) { + this(code, message); + {{#caseInsensitiveResponseHeaders}} + Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER); + for(Entry> entry : responseHeaders.entrySet()){ + headers.put(entry.getKey().toLowerCase(), entry.getValue()); + } + {{/caseInsensitiveResponseHeaders}} + this.responseHeaders = {{#caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}; + this.responseBody = responseBody; + } + + /** + * Get the HTTP status code. + * + * @return HTTP status code + */ + public int getCode() { + return code; + } + + /** + * Get the HTTP response headers. + * + * @return A map of list of string + */ + public Map> getResponseHeaders() { + return responseHeaders; + } + + /** + * Get the HTTP response body. + * + * @return Response body in the form of string + */ + public String getResponseBody() { + return responseBody; + } +} diff --git a/libraries/jersey2-experimental/api_doc.mustache b/libraries/jersey2-experimental/api_doc.mustache new file mode 100644 index 00000000000..f162d1cc974 --- /dev/null +++ b/libraries/jersey2-experimental/api_doc.mustache @@ -0,0 +1,121 @@ +# {{classname}}{{#description}} + +{{description}}{{/description}} + +All URIs are relative to *{{basePath}}* + +Method | HTTP request | Description +------------- | ------------- | ------------- +{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}} + +{{#operations}} +{{#operation}} + +## {{operationId}} + +{{^vendorExtensions.x-group-parameters}} +> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) +{{/vendorExtensions.x-group-parameters}} +{{#vendorExtensions.x-group-parameters}} +> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}){{#allParams}}{{^isPathParam}}.{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}}.execute(); +{{/vendorExtensions.x-group-parameters}} + +{{summary}}{{#notes}} + +{{{unescapedNotes}}}{{/notes}} + +### Example + +```java +// Import classes: +import {{{invokerPackage}}}.ApiClient; +import {{{invokerPackage}}}.ApiException; +import {{{invokerPackage}}}.Configuration;{{#hasAuthMethods}} +import {{{invokerPackage}}}.auth.*;{{/hasAuthMethods}} +import {{{invokerPackage}}}.models.*; +import {{{package}}}.{{{classname}}}; + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("{{{basePath}}}"); + {{#hasAuthMethods}} + {{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + // Configure HTTP basic authorization: {{{name}}} + HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setUsername("YOUR USERNAME"); + {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasicBasic}}{{#isBasicBearer}} + // Configure HTTP bearer authorization: {{{name}}} + HttpBearerAuth {{{name}}} = (HttpBearerAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setBearerToken("BEARER TOKEN");{{/isBasicBearer}}{{/isBasic}}{{#isApiKey}} + // Configure API key authorization: {{{name}}} + ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setApiKey("YOUR API KEY"); + // Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null) + //{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} + // Configure OAuth2 access token for authorization: {{{name}}} + OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}} + {{/authMethods}} + {{/hasAuthMethods}} + + {{{classname}}} apiInstance = new {{{classname}}}(defaultClient); + {{#allParams}} + {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} + {{/allParams}} + try { + {{^vendorExtensions.x-group-parameters}} + {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{/vendorExtensions.x-group-parameters}} + {{#vendorExtensions.x-group-parameters}} + {{#returnType}}{{{returnType}}} result = {{/returnType}}api.{{operationId}}({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}){{#allParams}}{{^isPathParam}} + .{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}} + .execute(); + {{/vendorExtensions.x-group-parameters}} + {{#returnType}} + System.out.println(result); + {{/returnType}} + } catch (ApiException e) { + System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } +} +``` + +### Parameters + +{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} +Name | Type | Description | Notes +------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} +{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{^isContainer}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} +{{/allParams}} + +### Return type + +{{#returnType}}{{#returnTypeIsPrimitive}}**{{returnType}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{returnType}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}null (empty response body){{/returnType}} + +### Authorization + +{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{name}}](../README.md#{{name}}){{^-last}}, {{/-last}}{{/authMethods}} + +### HTTP request headers + +- **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} +- **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} + +{{#responses.0}} +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +{{#responses}} +| **{{code}}** | {{message}} | {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}} | +{{/responses}} +{{/responses.0}} + +{{/operation}} +{{/operations}} diff --git a/libraries/jersey2-experimental/api_test.mustache b/libraries/jersey2-experimental/api_test.mustache new file mode 100644 index 00000000000..5ee6e494084 --- /dev/null +++ b/libraries/jersey2-experimental/api_test.mustache @@ -0,0 +1,51 @@ +{{>licenseInfo}} + +package {{package}}; + +import {{invokerPackage}}.ApiException; +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Test; +import org.junit.Ignore; +import org.junit.Assert; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * API tests for {{classname}} + */ +public class {{classname}}Test { + + private final {{classname}} api = new {{classname}}(); + + {{#operations}}{{#operation}} + /** + * {{summary}} + * + * {{notes}} + * + * @throws ApiException + * if the Api call fails + */ + @Test + public void {{operationId}}Test() throws ApiException { + {{#allParams}} + //{{{dataType}}} {{paramName}} = null; + {{/allParams}} + {{^vendorExtensions.x-group-parameters}} + //{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{/vendorExtensions.x-group-parameters}} + {{#vendorExtensions.x-group-parameters}} + //{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}){{#allParams}}{{^isPathParam}} + // .{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}} + // .execute(); + {{/vendorExtensions.x-group-parameters}} + // TODO: test validations + } + {{/operation}}{{/operations}} +} diff --git a/libraries/jersey2-experimental/build.gradle.mustache b/libraries/jersey2-experimental/build.gradle.mustache new file mode 100644 index 00000000000..cdb451adb34 --- /dev/null +++ b/libraries/jersey2-experimental/build.gradle.mustache @@ -0,0 +1,170 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + maven { url "https://repo1.maven.org/maven2" } + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + } +} + +repositories { + jcenter() +} + + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + } + compileOptions { + {{#supportJava6}} + sourceCompatibility JavaVersion.VERSION_1_6 + targetCompatibility JavaVersion.VERSION_1_6 + {{/supportJava6}} + {{^supportJava6}} + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + {{/supportJava6}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + {{#supportJava6}} + sourceCompatibility = JavaVersion.VERSION_1_6 + targetCompatibility = JavaVersion.VERSION_1_6 + {{/supportJava6}} + {{^supportJava6}} + {{#java8}} + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + {{/java8}} + {{/supportJava6}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + swagger_annotations_version = "1.5.22" + jackson_version = "2.10.3" + jackson_databind_version = "2.10.3" + jackson_databind_nullable_version = "0.2.1" + {{#supportJava6}} + jersey_version = "2.6" + commons_io_version=2.5 + commons_lang3_version=3.6 + {{/supportJava6}} + {{^supportJava6}} + jersey_version = "2.27" + {{/supportJava6}} + junit_version = "4.13" + {{#threetenbp}} + threetenbp_version = "2.9.10" + {{/threetenbp}} +} + +dependencies { + compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "com.google.code.findbugs:jsr305:3.0.2" + compile "org.glassfish.jersey.core:jersey-client:$jersey_version" + compile "org.glassfish.jersey.media:jersey-media-multipart:$jersey_version" + compile "org.glassfish.jersey.media:jersey-media-json-jackson:$jersey_version" + compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{#joda}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + {{/joda}} + {{#java8}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{/java8}} + {{#supportJava6}} + compile "commons-io:commons-io:$commons_io_version" + compile "org.apache.commons:commons-lang3:$commons_lang3_version" + {{/supportJava6}} + {{#threetenbp}} + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$threetenbp_version" + {{/threetenbp}} + {{^java8}} + compile "com.brsanthu:migbase64:2.2" + {{/java8}} + testCompile "junit:junit:$junit_version" +} + +javadoc { + options.tags = [ "http.response.details:a:Http Response Details" ] +} diff --git a/libraries/jersey2-experimental/build.sbt.mustache b/libraries/jersey2-experimental/build.sbt.mustache new file mode 100644 index 00000000000..abb91ecdc99 --- /dev/null +++ b/libraries/jersey2-experimental/build.sbt.mustache @@ -0,0 +1,38 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + javacOptions in compile ++= Seq("-Xlint:deprecation"), + publishArtifact in (Compile, packageDoc) := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "io.swagger" % "swagger-annotations" % "1.5.22", + "org.glassfish.jersey.core" % "jersey-client" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, + "org.glassfish.jersey.media" % "jersey-media-multipart" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, + "org.glassfish.jersey.media" % "jersey-media-json-jackson" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", + {{#joda}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.10" % "compile", + {{/joda}} + {{#java8}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.10" % "compile", + {{/java8}} + {{#threetenbp}} + "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", + {{/threetenbp}} + {{^java8}} + "com.brsanthu" % "migbase64" % "2.2", + {{/java8}} + {{#supportJava6}} + "org.apache.commons" % "commons-lang3" % "3.6", + "commons-io" % "commons-io" % "2.5", + {{/supportJava6}} + "junit" % "junit" % "4.13" % "test", + "com.novocode" % "junit-interface" % "0.10" % "test" + ) + ) diff --git a/libraries/jersey2-experimental/model.mustache b/libraries/jersey2-experimental/model.mustache new file mode 100644 index 00000000000..02787f8bb7f --- /dev/null +++ b/libraries/jersey2-experimental/model.mustache @@ -0,0 +1,47 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#useReflectionEqualsHashCode}} +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +{{/useReflectionEqualsHashCode}} +{{^supportJava6}} +import java.util.Objects; +import java.util.Arrays; +{{/supportJava6}} +{{#supportJava6}} +import org.apache.commons.lang3.ObjectUtils; +{{/supportJava6}} +{{#imports}} +import {{import}}; +{{/imports}} +{{#serializableModel}} +import java.io.Serializable; +{{/serializableModel}} +{{#jackson}} +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +{{#withXml}} +import com.fasterxml.jackson.dataformat.xml.annotation.*; +{{/withXml}} +{{/jackson}} +{{#withXml}} +import javax.xml.bind.annotation.*; +{{/withXml}} +{{#parcelableModel}} +import android.os.Parcelable; +import android.os.Parcel; +{{/parcelableModel}} +{{#useBeanValidation}} +import javax.validation.constraints.*; +import javax.validation.Valid; +{{/useBeanValidation}} +{{#performBeanValidation}} +import org.hibernate.validator.constraints.*; +{{/performBeanValidation}} + +{{#models}} +{{#model}} +{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{#oneOf}}{{#-first}}{{>oneof_model}}{{/-first}}{{/oneOf}}{{^oneOf}}{{#anyOf}}{{#-first}}{{>anyof_model}}{{/-first}}{{/anyOf}}{{^anyOf}}{{>pojo}}{{/anyOf}}{{/oneOf}}{{/isEnum}} +{{/model}} +{{/models}} diff --git a/libraries/jersey2-experimental/oneof_model.mustache b/libraries/jersey2-experimental/oneof_model.mustache new file mode 100644 index 00000000000..62289f9b2d7 --- /dev/null +++ b/libraries/jersey2-experimental/oneof_model.mustache @@ -0,0 +1,45 @@ +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.Response; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} +public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}}, {{{.}}}{{/vendorExtensions.x-implements}} { + + // store a list of schema names defined in oneOf + public final static Map schemas = new HashMap(); + + public {{classname}}() { + super("oneOf"); + } + + static { + {{#oneOf}} + schemas.put("{{{.}}}", new GenericType<{{{.}}}>() { + }); + {{/oneOf}} + } + + @Override + public Map getSchemas() { + return {{classname}}.schemas; + } + + public String getSchemaType() { + return schemaType; + } + + @Override + public void setActualInstance(Object instance) { + {{#oneOf}} + if (instance instanceof {{{.}}}) { + super.setActualInstance(instance); + return; + } + + {{/oneOf}} + throw new RuntimeException("Invalid instance type. Must be {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}"); + } + +} diff --git a/libraries/jersey2-experimental/pojo.mustache b/libraries/jersey2-experimental/pojo.mustache new file mode 100644 index 00000000000..c438cd43eb7 --- /dev/null +++ b/libraries/jersey2-experimental/pojo.mustache @@ -0,0 +1,369 @@ +/** + * {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}} + */{{#description}} +@ApiModel(description = "{{{description}}}"){{/description}} +{{#jackson}} +@JsonPropertyOrder({ +{{#vars}} + {{classname}}.JSON_PROPERTY_{{nameInSnakeCase}}{{^-last}},{{/-last}} +{{/vars}} +}) +{{/jackson}} +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} +public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{ +{{#serializableModel}} + private static final long serialVersionUID = 1L; + +{{/serializableModel}} + {{#vars}} + {{#isEnum}} + {{^isContainer}} +{{>modelInnerEnum}} + {{/isContainer}} + {{#isContainer}} + {{#mostInnerItems}} +{{>modelInnerEnum}} + {{/mostInnerItems}} + {{/isContainer}} + {{/isEnum}} + {{#gson}} + public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}"; + {{/gson}} + {{#jackson}} + public static final String JSON_PROPERTY_{{nameInSnakeCase}} = "{{baseName}}"; + {{/jackson}} + {{#withXml}} + {{#isXmlAttribute}} + @XmlAttribute(name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlAttribute}} + {{^isXmlAttribute}} + {{^isContainer}} + @XmlElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isContainer}} + {{#isContainer}} + // Is a container wrapped={{isXmlWrapped}} + {{#items}} + // items.name={{name}} items.baseName={{baseName}} items.xmlName={{xmlName}} items.xmlNamespace={{xmlNamespace}} + // items.example={{example}} items.type={{dataType}} + @XmlElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/items}} + {{#isXmlWrapped}} + @XmlElementWrapper({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlWrapped}} + {{/isContainer}} + {{/isXmlAttribute}} + {{/withXml}} + {{#gson}} + @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}}) + {{/gson}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#isContainer}} + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined(); + {{/isContainer}} + {{^isContainer}} + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + {{/isContainer}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{#isContainer}} + private {{{datatypeWithEnum}}} {{name}}{{#required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/required}}{{^required}} = null{{/required}}; + {{/isContainer}} + {{^isContainer}} + private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; + {{/isContainer}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + + {{/vars}} + {{#parcelableModel}} + public {{classname}}() { + {{#parent}} + super(); + {{/parent}} + {{#gson}} + {{#discriminator}} + this.{{{discriminatorName}}} = this.getClass().getSimpleName(); + {{/discriminator}} + {{/gson}} + } + {{/parcelableModel}} + {{^parcelableModel}} + {{#gson}} + {{#discriminator}} + public {{classname}}() { + this.{{{discriminatorName}}} = this.getClass().getSimpleName(); + } + {{/discriminator}} + {{/gson}} + {{/parcelableModel}} + {{#vars}} + + {{^isReadOnly}} + public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});{{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = {{name}};{{/vendorExtensions.x-is-jackson-optional-nullable}} + return this; + } + {{#isListContainer}} + + public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null || !this.{{name}}.isPresent()) { + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); + } + try { + this.{{name}}.get().add({{name}}Item); + } catch (java.util.NoSuchElementException e) { + // this can never happen, as we make sure above that the value is present + } + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.add({{name}}Item); + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isListContainer}} + {{#isMapContainer}} + + public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null || !this.{{name}}.isPresent()) { + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); + } + try { + this.{{name}}.get().put(key, {{name}}Item); + } catch (java.util.NoSuchElementException e) { + // this can never happen, as we make sure above that the value is present + } + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.put(key, {{name}}Item); + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isMapContainer}} + + {{/isReadOnly}} + /** + {{#description}} + * {{description}} + {{/description}} + {{^description}} + * Get {{name}} + {{/description}} + {{#minimum}} + * minimum: {{minimum}} + {{/minimum}} + {{#maximum}} + * maximum: {{maximum}} + {{/maximum}} + * @return {{name}} + **/ +{{#required}} +{{#isNullable}} + @javax.annotation.Nullable +{{/isNullable}} +{{/required}} +{{^required}} + @javax.annotation.Nullable +{{/required}} +{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} @ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") +{{#vendorExtensions.x-extra-annotation}} + {{{vendorExtensions.x-extra-annotation}}} +{{/vendorExtensions.x-extra-annotation}} +{{#vendorExtensions.x-is-jackson-optional-nullable}} + {{!unannotated, Jackson would pick this up automatically and add it *in addition* to the _JsonNullable getter field}} + @JsonIgnore +{{/vendorExtensions.x-is-jackson-optional-nullable}} +{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#jackson}}{{> jackson_annotations}}{{/jackson}}{{/vendorExtensions.x-is-jackson-optional-nullable}} + public {{{datatypeWithEnum}}} {{getter}}() { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#isReadOnly}}{{! A readonly attribute doesn't have setter => jackson will set null directly if explicitly returned by API, so make sure we have an empty JsonNullable}} + if ({{name}} == null) { + {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + } + {{/isReadOnly}} + return {{name}}.orElse(null); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + return {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + + {{#vendorExtensions.x-is-jackson-optional-nullable}} +{{> jackson_annotations}} + public JsonNullable<{{{datatypeWithEnum}}}> {{getter}}_JsonNullable() { + return {{name}}; + } + {{/vendorExtensions.x-is-jackson-optional-nullable}}{{#vendorExtensions.x-is-jackson-optional-nullable}} + @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) + {{#isReadOnly}}private{{/isReadOnly}}{{^isReadOnly}}public{{/isReadOnly}} void {{setter}}_JsonNullable(JsonNullable<{{{datatypeWithEnum}}}> {{name}}) { + {{! For getters/setters that have name differing from attribute name, we must include setter (albeit private) for jackson to be able to set the attribute}} + this.{{name}} = {{name}}; + } + {{/vendorExtensions.x-is-jackson-optional-nullable}} + + {{^isReadOnly}} + public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isReadOnly}} + + {{/vars}} + +{{^supportJava6}} + @Override + public boolean equals(java.lang.Object o) { + {{#useReflectionEqualsHashCode}} + return EqualsBuilder.reflectionEquals(this, o, false, null, true); + {{/useReflectionEqualsHashCode}} + {{^useReflectionEqualsHashCode}} + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + }{{#hasVars}} + {{classname}} {{classVarName}} = ({{classname}}) o; + return {{#vars}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{#hasMore}} && + {{/hasMore}}{{/vars}}{{#parent}} && + super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} + return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}} + {{/useReflectionEqualsHashCode}} + } + + @Override + public int hashCode() { + {{#useReflectionEqualsHashCode}} + return HashCodeBuilder.reflectionHashCode(this); + {{/useReflectionEqualsHashCode}} + {{^useReflectionEqualsHashCode}} + return Objects.hash({{#vars}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{#hasMore}}, {{/hasMore}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); + {{/useReflectionEqualsHashCode}} + } + +{{/supportJava6}} +{{#supportJava6}} + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + }{{#hasVars}} + {{classname}} {{classVarName}} = ({{classname}}) o; + return {{#vars}}ObjectUtils.equals(this.{{name}}, {{classVarName}}.{{name}}){{#hasMore}} && + {{/hasMore}}{{/vars}}{{#parent}} && + super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} + return true;{{/hasVars}} + } + + @Override + public int hashCode() { + return ObjectUtils.hashCodeMulti({{#vars}}{{name}}{{#hasMore}}, {{/hasMore}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); + } + +{{/supportJava6}} + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class {{classname}} {\n"); + {{#parent}} + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + {{/parent}} + {{#vars}} + sb.append(" {{name}}: ").append(toIndentedString({{name}})).append("\n"); + {{/vars}} + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + +{{#parcelableModel}} + + public void writeToParcel(Parcel out, int flags) { +{{#model}} +{{#isArrayModel}} + out.writeList(this); +{{/isArrayModel}} +{{^isArrayModel}} +{{#parent}} + super.writeToParcel(out, flags); +{{/parent}} +{{#vars}} + out.writeValue({{name}}); +{{/vars}} +{{/isArrayModel}} +{{/model}} + } + + {{classname}}(Parcel in) { +{{#isArrayModel}} + in.readTypedList(this, {{arrayModelType}}.CREATOR); +{{/isArrayModel}} +{{^isArrayModel}} +{{#parent}} + super(in); +{{/parent}} +{{#vars}} +{{#isPrimitiveType}} + {{name}} = ({{{datatypeWithEnum}}})in.readValue(null); +{{/isPrimitiveType}} +{{^isPrimitiveType}} + {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader()); +{{/isPrimitiveType}} +{{/vars}} +{{/isArrayModel}} + } + + public int describeContents() { + return 0; + } + + public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() { + public {{classname}} createFromParcel(Parcel in) { +{{#model}} +{{#isArrayModel}} + {{classname}} result = new {{classname}}(); + result.addAll(in.readArrayList({{arrayModelType}}.class.getClassLoader())); + return result; +{{/isArrayModel}} +{{^isArrayModel}} + return new {{classname}}(in); +{{/isArrayModel}} +{{/model}} + } + public {{classname}}[] newArray(int size) { + return new {{classname}}[size]; + } + }; +{{/parcelableModel}} +} diff --git a/libraries/jersey2-experimental/pom.mustache b/libraries/jersey2-experimental/pom.mustache new file mode 100644 index 00000000000..bf1c3648c20 --- /dev/null +++ b/libraries/jersey2-experimental/pom.mustache @@ -0,0 +1,372 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{artifactUrl}} + {{artifactDescription}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + +{{#parentOverridden}} + + {{{parentGroupId}}} + {{{parentArtifactId}}} + {{{parentVersion}}} + +{{/parentOverridden}} + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.6 + + + + jar + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + + + add_sources + generate-sources + + add-source + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + {{#supportJava6}} + 1.6 + 1.6 + {{/supportJava6}} + {{^supportJava6}} + {{#java8}} + 1.8 + 1.8 + {{/java8}} + {{^java8}} + 1.7 + 1.7 + {{/java8}} + {{/supportJava6}} + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.1 + + + attach-javadocs + + jar + + + + + none + + + http.response.details + a + Http Response Details: + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + + io.swagger + swagger-annotations + ${swagger-annotations-version} + + + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + + + org.glassfish.jersey.core + jersey-client + ${jersey-version} + + {{^supportJava6}} + + org.glassfish.jersey.inject + jersey-hk2 + ${jersey-version} + + {{/supportJava6}} + + org.glassfish.jersey.media + jersey-media-multipart + ${jersey-version} + + + org.glassfish.jersey.media + jersey-media-json-jackson + ${jersey-version} + + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-databind-version} + + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + + {{#withXml}} + + + + org.glassfish.jersey.media + jersey-media-jaxb + ${jersey-version} + + + {{/withXml}} + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + {{/joda}} + {{#java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{/java8}} + {{#threetenbp}} + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${threetenbp-version} + + {{/threetenbp}} + {{^java8}} + + + com.brsanthu + migbase64 + 2.2 + + {{/java8}} + {{#supportJava6}} + + org.apache.commons + commons-lang3 + ${commons_lang3_version} + + + commons-io + commons-io + ${commons_io_version} + + {{/supportJava6}} + {{#useBeanValidation}} + + + javax.validation + validation-api + 1.1.0.Final + provided + + {{/useBeanValidation}} + + + junit + junit + ${junit-version} + test + + + + UTF-8 + 1.6.1 + {{^supportJava6}} + 2.30.1 + {{/supportJava6}} + {{#supportJava6}} + 2.6 + 2.5 + 3.6 + {{/supportJava6}} + 2.10.3 + 2.10.3 + 0.2.1 + {{#threetenbp}} + 2.9.10 + {{/threetenbp}} + 4.13 + + diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 9bd8925f001..d999ffaf0fa 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -352,7 +352,7 @@ UTF-8 - 1.5.22 + 1.6.1 {{^supportJava6}} 2.27 {{/supportJava6}} From 5bec255266481cc5b1b4718e8bd61cc780107bb1 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Fri, 24 Apr 2020 09:01:02 -0700 Subject: [PATCH 223/370] [CORE] Fixes composed schema discriminator map (#4906) * Adds addComposedMappedModels and testComposedSchemaOneOfDiscriminatorMap * Requires that discriminators be required properties * Strengthens discriminaotr validation, adds better error messages, adds schema oneof samples * Adds oneOf and anyOf invalidDiscriminator tests * Updates incorrect addOneOfInterfaceModel invocation * Runs ensure-up-to-date * Adds updates from Sebastien Rosset * Removes newlines * Uses df.isString * Fixes tests be correctly setting df.isString * Updates discriminatorExplicitMappingVerbose description per PR feedback * Adds description of how mappedModels is populated * Adds the suggestion exception raising when a MappedModel mappingName is null * Actually resolves merge conflicts * Switches two methods to package private because they are needed for testing * Allow nulls in MappedModel.getMappingName * Updates CLI flag name to legacyDiscriminatorBehavior, default=true Co-authored-by: William Cheng --- pojo.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pojo.mustache b/pojo.mustache index c438cd43eb7..653f44062d1 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -69,7 +69,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE private {{{datatypeWithEnum}}} {{name}}{{#required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/required}}{{^required}} = null{{/required}}; {{/isContainer}} {{^isContainer}} - private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; + {{#isDiscriminator}}protected{{/isDiscriminator}}{{^isDiscriminator}}private{{/isDiscriminator}} {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; {{/isContainer}} {{/vendorExtensions.x-is-jackson-optional-nullable}} From dcb3f368fc28be811178e4f4c024a5577a01c03f Mon Sep 17 00:00:00 2001 From: William Cheng Date: Tue, 28 Apr 2020 00:09:14 +0800 Subject: [PATCH 224/370] Update Java (feign) client dependency (#6068) * update feign dependency * update feign samples --- libraries/feign/build.gradle.mustache | 4 ++-- libraries/feign/build.sbt.mustache | 8 ++++---- libraries/feign/pom.mustache | 24 ++++++++++++++++++++---- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index 2a6c4c79fbc..86cdad95f82 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -119,14 +119,14 @@ if(hasProperty('target') && target == 'android') { } ext { - swagger_annotations_version = "1.5.22" + swagger_annotations_version = "1.5.24" jackson_version = "2.10.3" jackson_databind_version = "2.10.3" jackson_databind_nullable_version = "0.2.1" {{#threetenbp}} jackson_threetenbp_version = "2.9.10" {{/threetenbp}} - feign_version = "{{#useFeign10}}10.7.4{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" + feign_version = "{{#useFeign10}}11.0{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" feign_form_version = "{{#useFeign10}}3.8.0{{/useFeign10}}{{^useFeign10}}2.1.0{{/useFeign10}}" junit_version = "4.13" oltu_version = "1.0.1" diff --git a/libraries/feign/build.sbt.mustache b/libraries/feign/build.sbt.mustache index 8fa1d345b26..cd55527b8ec 100644 --- a/libraries/feign/build.sbt.mustache +++ b/libraries/feign/build.sbt.mustache @@ -9,10 +9,10 @@ lazy val root = (project in file(".")). publishArtifact in (Compile, packageDoc) := false, resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( - "io.swagger" % "swagger-annotations" % "1.5.22" % "compile", - "io.github.openfeign" % "feign-core" % "{{#useFeign10}}10.7.4{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", - "io.github.openfeign" % "feign-jackson" % "{{#useFeign10}}10.7.4{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", - "io.github.openfeign" % "feign-slf4j" % "{{#useFeign10}}10.7.4{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", + "io.swagger" % "swagger-annotations" % "1.5.24" % "compile", + "io.github.openfeign" % "feign-core" % "{{#useFeign10}}11.0{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", + "io.github.openfeign" % "feign-jackson" % "{{#useFeign10}}11.0{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", + "io.github.openfeign" % "feign-slf4j" % "{{#useFeign10}}11.0{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", "io.github.openfeign.form" % "feign-form" % "{{#useFeign10}}3.8.0{{/useFeign10}}{{^useFeign10}}2.1.0{{/useFeign10}}" % "compile", "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index 86f6f397781..a40806b32e9 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -63,7 +63,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.12 + 3.0.0-M4 @@ -73,7 +73,7 @@ -Xms512m -Xmx1500m methods - pertest + 10 @@ -139,6 +139,22 @@ + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + true + 128m + 512m + + -Xlint:all + -J-Xss4m + + + org.apache.maven.plugins maven-javadoc-plugin @@ -314,8 +330,8 @@ {{#supportJava6}}1.6{{/supportJava6}}{{^supportJava6}}{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}{{/supportJava6}} ${java.version} ${java.version} - 1.5.21 - {{#useFeign10}}10.7.4{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}} + 1.5.24 + {{#useFeign10}}11.0{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}} {{#useFeign10}}3.8.0{{/useFeign10}}{{^useFeign10}}2.1.0{{/useFeign10}} 2.10.3 0.2.1 From 8bf18a9570b97e2ebc3df3868c2d81bcc90229c2 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Tue, 28 Apr 2020 00:09:30 +0800 Subject: [PATCH 225/370] Add HTTP signature authentication support to Java (jersey2-experimental) (#6058) * add fmt-maven-plugin to jersey2 exp * update samples * add http signature auth template * minor fix * fix http beaer auth, update sample * fix http signature auth * fix http signature auth * header support * add query string to path * undo changes in default codegen * ignore fake test * add serialize to string method * add serialzie to string method * add get mapper * auto format java source code * remove plugin * update pom.xml * change back AbstractOpenApiSchema to T * skip mvn code formatter in bin script * undo changes to spec * update samples * add back HttpSignatureAuth.java --- .../jersey2-experimental/ApiClient.mustache | 79 ++++++++++-- libraries/jersey2-experimental/JSON.mustache | 2 + .../auth/ApiKeyAuth.mustache | 68 +++++++++++ .../auth/Authentication.mustache | 22 ++++ .../auth/HttpBasicAuth.mustache | 62 ++++++++++ .../auth/HttpBearerAuth.mustache | 51 ++++++++ .../auth/HttpSignatureAuth.mustache | 115 ++++++++++++++++++ .../jersey2-experimental/auth/OAuth.mustache | 30 +++++ .../auth/OAuthFlow.mustache | 7 ++ libraries/jersey2-experimental/pom.mustache | 113 +++++++++-------- 10 files changed, 489 insertions(+), 60 deletions(-) create mode 100644 libraries/jersey2-experimental/auth/ApiKeyAuth.mustache create mode 100644 libraries/jersey2-experimental/auth/Authentication.mustache create mode 100644 libraries/jersey2-experimental/auth/HttpBasicAuth.mustache create mode 100644 libraries/jersey2-experimental/auth/HttpBearerAuth.mustache create mode 100644 libraries/jersey2-experimental/auth/HttpSignatureAuth.mustache create mode 100644 libraries/jersey2-experimental/auth/OAuth.mustache create mode 100644 libraries/jersey2-experimental/auth/OAuthFlow.mustache diff --git a/libraries/jersey2-experimental/ApiClient.mustache b/libraries/jersey2-experimental/ApiClient.mustache index 618264dc90c..10a976f6d76 100644 --- a/libraries/jersey2-experimental/ApiClient.mustache +++ b/libraries/jersey2-experimental/ApiClient.mustache @@ -23,6 +23,7 @@ import org.glassfish.jersey.media.multipart.MultiPartFeature; import java.io.IOException; import java.io.InputStream; +import java.net.URI; {{^supportJava6}} import java.nio.file.Files; import java.nio.file.StandardCopyOption; @@ -56,6 +57,7 @@ import java.util.regex.Pattern; import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; import {{invokerPackage}}.auth.HttpBearerAuth; +import {{invokerPackage}}.auth.HttpSignatureAuth; import {{invokerPackage}}.auth.ApiKeyAuth; import {{invokerPackage}}.model.AbstractOpenApiSchema; @@ -159,11 +161,26 @@ public class ApiClient { setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); // Setup authentications (key: authentication name, value: authentication). - authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} - authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} - authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} - authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} - authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + authentications = new HashMap(); + {{#authMethods}} + {{#isBasic}} + {{#isBasicBasic}} + authentications.put("{{name}}", new HttpBasicAuth()); + {{/isBasicBasic}} + {{#isBasicBearer}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}")); + {{/isBasicBearer}} + {{#isHttpSignature}} + authentications.put("{{name}}", new HttpSignatureAuth("{{name}}", null, null)); + {{/isHttpSignature}} + {{/isBasic}} + {{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}")); + {{/isApiKey}} + {{#isOAuth}} + authentications.put("{{name}}", new OAuth()); + {{/isOAuth}} + {{/authMethods}} // Prevent the authentications from being modified. authentications = Collections.unmodifiableMap(authentications); @@ -701,6 +718,38 @@ public class ApiClient { return entity; } + /** + * Serialize the given Java object into string according the given + * Content-Type (only JSON, HTTP form is supported for now). + * @param obj Object + * @param formParams Form parameters + * @param contentType Context type + * @return String + * @throws ApiException API exception + */ + public String serializeToString(Object obj, Map formParams, String contentType) throws ApiException { + try { + if (contentType.startsWith("multipart/form-data")) { + throw new ApiException("multipart/form-data not yet supported for serializeToString (http signature authentication)"); + } else if (contentType.startsWith("application/x-www-form-urlencoded")) { + String formString = ""; + for (Entry param : formParams.entrySet()) { + formString = param.getKey() + "=" + URLEncoder.encode(parameterToString(param.getValue()), "UTF-8") + "&"; + } + + if (formString.length() == 0) { // empty string + return formString; + } else { + return formString.substring(0, formString.length() - 1); + } + } else { + return json.getMapper().writeValueAsString(obj); + } + } catch (Exception ex) { + throw new ApiException("Failed to perform serializeToString: " + ex.toString()); + } + } + public AbstractOpenApiSchema deserializeSchemas(Response response, AbstractOpenApiSchema schema) throws ApiException{ Object result = null; @@ -862,7 +911,6 @@ public class ApiClient { * @throws ApiException API exception */ public ApiResponse invokeAPI(String operation, String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType, AbstractOpenApiSchema schema) throws ApiException { - updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); // Not using `.target(targetURL).path(path)` below, // to support (constant) query string in `path`, e.g. "/posts?draft=1" @@ -935,6 +983,14 @@ public class ApiClient { Entity entity = serialize(body, formParams, contentType); + // put all headers in one place + Map allHeaderParams = new HashMap<>(); + allHeaderParams.putAll(defaultHeaderMap); + allHeaderParams.putAll(headerParams); + + // update different parameters (e.g. headers) for authentication + updateParamsForAuth(authNames, queryParams, allHeaderParams, cookieParams, serializeToString(body, formParams, contentType), method, target.getUri()); + Response response = null; try { @@ -1061,12 +1117,17 @@ public class ApiClient { * @param queryParams List of query parameters * @param headerParams Map of header parameters * @param cookieParams Map of cookie parameters + * @param method HTTP method (e.g. POST) + * @param uri HTTP URI */ - protected void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams, Map cookieParams) { + protected void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams, + Map cookieParams, String payload, String method, URI uri) throws ApiException { for (String authName : authNames) { Authentication auth = authentications.get(authName); - if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); - auth.applyToParams(queryParams, headerParams, cookieParams); + if (auth == null) { + throw new RuntimeException("Authentication undefined: " + authName); + } + auth.applyToParams(queryParams, headerParams, cookieParams, payload, method, uri); } } } diff --git a/libraries/jersey2-experimental/JSON.mustache b/libraries/jersey2-experimental/JSON.mustache index b442f0836da..e25b307f7d0 100644 --- a/libraries/jersey2-experimental/JSON.mustache +++ b/libraries/jersey2-experimental/JSON.mustache @@ -62,4 +62,6 @@ public class JSON implements ContextResolver { public ObjectMapper getContext(Class type) { return mapper; } + + public ObjectMapper getMapper() { return mapper; } } diff --git a/libraries/jersey2-experimental/auth/ApiKeyAuth.mustache b/libraries/jersey2-experimental/auth/ApiKeyAuth.mustache new file mode 100644 index 00000000000..1731f936fb8 --- /dev/null +++ b/libraries/jersey2-experimental/auth/ApiKeyAuth.mustache @@ -0,0 +1,68 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import {{invokerPackage}}.ApiException; + +import java.net.URI; +import java.util.Map; +import java.util.List; + +{{>generatedAnnotation}} +public class ApiKeyAuth implements Authentication { + private final String location; + private final String paramName; + + private String apiKey; + private String apiKeyPrefix; + + public ApiKeyAuth(String location, String paramName) { + this.location = location; + this.paramName = paramName; + } + + public String getLocation() { + return location; + } + + public String getParamName() { + return paramName; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + public String getApiKeyPrefix() { + return apiKeyPrefix; + } + + public void setApiKeyPrefix(String apiKeyPrefix) { + this.apiKeyPrefix = apiKeyPrefix; + } + + @Override + public void applyToParams(List queryParams, Map headerParams, Map cookieParams, String payload, String method, URI uri) throws ApiException { + if (apiKey == null) { + return; + } + String value; + if (apiKeyPrefix != null) { + value = apiKeyPrefix + " " + apiKey; + } else { + value = apiKey; + } + if ("query".equals(location)) { + queryParams.add(new Pair(paramName, value)); + } else if ("header".equals(location)) { + headerParams.put(paramName, value); + } else if ("cookie".equals(location)) { + cookieParams.put(paramName, value); + } + } +} diff --git a/libraries/jersey2-experimental/auth/Authentication.mustache b/libraries/jersey2-experimental/auth/Authentication.mustache new file mode 100644 index 00000000000..46d9c1ab6ac --- /dev/null +++ b/libraries/jersey2-experimental/auth/Authentication.mustache @@ -0,0 +1,22 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import {{invokerPackage}}.ApiException; + +import java.net.URI; +import java.util.Map; +import java.util.List; + +public interface Authentication { + /** + * Apply authentication settings to header and query params. + * + * @param queryParams List of query parameters + * @param headerParams Map of header parameters + * @param cookieParams Map of cookie parameters + */ + void applyToParams(List queryParams, Map headerParams, Map cookieParams, String payload, String method, URI uri) throws ApiException; + +} diff --git a/libraries/jersey2-experimental/auth/HttpBasicAuth.mustache b/libraries/jersey2-experimental/auth/HttpBasicAuth.mustache new file mode 100644 index 00000000000..898bb97ee78 --- /dev/null +++ b/libraries/jersey2-experimental/auth/HttpBasicAuth.mustache @@ -0,0 +1,62 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import {{invokerPackage}}.ApiException; + +{{^java8}} +import com.migcomponents.migbase64.Base64; +{{/java8}} +{{#java8}} +import java.util.Base64; +import java.nio.charset.StandardCharsets; +{{/java8}} + +import java.net.URI; +import java.util.Map; +import java.util.List; + +{{^java8}} +import java.io.UnsupportedEncodingException; +{{/java8}} + +{{>generatedAnnotation}} +public class HttpBasicAuth implements Authentication { + private String username; + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public void applyToParams(List queryParams, Map headerParams, Map cookieParams, String payload, String method, URI uri) throws ApiException { + if (username == null && password == null) { + return; + } + String str = (username == null ? "" : username) + ":" + (password == null ? "" : password); +{{^java8}} + try { + headerParams.put("Authorization", "Basic " + Base64.encodeToString(str.getBytes("UTF-8"), false)); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } +{{/java8}} +{{#java8}} + headerParams.put("Authorization", "Basic " + Base64.getEncoder().encodeToString(str.getBytes(StandardCharsets.UTF_8))); +{{/java8}} + } +} diff --git a/libraries/jersey2-experimental/auth/HttpBearerAuth.mustache b/libraries/jersey2-experimental/auth/HttpBearerAuth.mustache new file mode 100644 index 00000000000..110a11ea779 --- /dev/null +++ b/libraries/jersey2-experimental/auth/HttpBearerAuth.mustache @@ -0,0 +1,51 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import {{invokerPackage}}.ApiException; + +import java.net.URI; +import java.util.Map; +import java.util.List; + +{{>generatedAnnotation}} +public class HttpBearerAuth implements Authentication { + private final String scheme; + private String bearerToken; + + public HttpBearerAuth(String scheme) { + this.scheme = scheme; + } + + /** + * Gets the token, which together with the scheme, will be sent as the value of the Authorization header. + * + * @return The bearer token + */ + public String getBearerToken() { + return bearerToken; + } + + /** + * Sets the token, which together with the scheme, will be sent as the value of the Authorization header. + * + * @param bearerToken The bearer token to send in the Authorization header + */ + public void setBearerToken(String bearerToken) { + this.bearerToken = bearerToken; + } + + @Override + public void applyToParams(List queryParams, Map headerParams, Map cookieParams, String payload, String method, URI uri) throws ApiException { + if(bearerToken == null) { + return; + } + + headerParams.put("Authorization", (scheme != null ? upperCaseBearer(scheme) + " " : "") + bearerToken); + } + + private static String upperCaseBearer(String scheme) { + return ("bearer".equalsIgnoreCase(scheme)) ? "Bearer" : scheme; + } +} diff --git a/libraries/jersey2-experimental/auth/HttpSignatureAuth.mustache b/libraries/jersey2-experimental/auth/HttpSignatureAuth.mustache new file mode 100644 index 00000000000..3a856e3bc3c --- /dev/null +++ b/libraries/jersey2-experimental/auth/HttpSignatureAuth.mustache @@ -0,0 +1,115 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import {{invokerPackage}}.ApiException; + +import java.net.URI; +import java.net.URLEncoder; +import java.security.MessageDigest; +import java.security.Key; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Base64; +import java.util.Date; +import java.util.Locale; +import java.util.Map; +import java.util.List; + +import org.tomitribe.auth.signatures.*; + +public class HttpSignatureAuth implements Authentication { + + private Signer signer; + + private String name; + + private Algorithm algorithm; + + private List headers; + + public HttpSignatureAuth(String name, Algorithm algorithm, List headers) { + this.name = name; + this.algorithm = algorithm; + this.headers = headers; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Algorithm getAlgorithm() { + return algorithm; + } + + public void setAlgorithm(Algorithm algorithm) { + this.algorithm = algorithm; + } + + public List getHeaders() { + return headers; + } + + public void setHeaders(List headers) { + this.headers = headers; + } + + public Signer getSigner() { + return signer; + } + + public void setSigner(Signer signer) { + this.signer = signer; + } + + public void setup(Key key) throws ApiException { + if (key == null) { + throw new ApiException("key (java.security.Key) cannot be null"); + } + + signer = new Signer(key, new Signature(name, algorithm, null, headers)); + } + + @Override + public void applyToParams(List queryParams, Map headerParams, Map cookieParams, + String payload, String method, URI uri) throws ApiException { + try { + if (headers.contains("host")) { + headerParams.put("host", uri.getHost()); + } + + if (headers.contains("date")) { + headerParams.put("date", new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US).format(new Date())); + } + + if (headers.contains("digest")) { + headerParams.put("digest", "SHA-256=" + new String(Base64.getEncoder().encode(MessageDigest.getInstance("SHA-256").digest(payload.getBytes())))); + } + + if (signer == null) { + throw new ApiException("Signer cannot be null. Please run the method `setup` to set it up correctly"); + } + + // construct the path with the URL query string + String path = uri.getPath(); + + List urlQueries = new ArrayList(); + for (Pair queryParam : queryParams) { + urlQueries.add(queryParam.getName() + "=" + URLEncoder.encode(queryParam.getValue(), "utf8").replaceAll("\\+", "%20")); + } + + if (!urlQueries.isEmpty()) { + path = path + "?" + String.join("&", urlQueries); + } + + headerParams.put("Authorization", signer.sign(method, path, headerParams).toString()); + } catch (Exception ex) { + throw new ApiException("Failed to create signature in the HTTP request header: " + ex.toString()); + } + } +} diff --git a/libraries/jersey2-experimental/auth/OAuth.mustache b/libraries/jersey2-experimental/auth/OAuth.mustache new file mode 100644 index 00000000000..8622798ad37 --- /dev/null +++ b/libraries/jersey2-experimental/auth/OAuth.mustache @@ -0,0 +1,30 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import {{invokerPackage}}.ApiException; + +import java.net.URI; +import java.util.Map; +import java.util.List; + +{{>generatedAnnotation}} +public class OAuth implements Authentication { + private String accessToken; + + public String getAccessToken() { + return accessToken; + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + @Override + public void applyToParams(List queryParams, Map headerParams, Map cookieParams, String payload, String method, URI uri) throws ApiException { + if (accessToken != null) { + headerParams.put("Authorization", "Bearer " + accessToken); + } + } +} diff --git a/libraries/jersey2-experimental/auth/OAuthFlow.mustache b/libraries/jersey2-experimental/auth/OAuthFlow.mustache new file mode 100644 index 00000000000..002e9572f33 --- /dev/null +++ b/libraries/jersey2-experimental/auth/OAuthFlow.mustache @@ -0,0 +1,7 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +public enum OAuthFlow { + accessCode, implicit, password, application +} diff --git a/libraries/jersey2-experimental/pom.mustache b/libraries/jersey2-experimental/pom.mustache index bf1c3648c20..a71ab263863 100644 --- a/libraries/jersey2-experimental/pom.mustache +++ b/libraries/jersey2-experimental/pom.mustache @@ -63,7 +63,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.12 + 3.0.0-M4 @@ -73,7 +73,7 @@ -Xms512m -Xmx1500m methods - pertest + 10 @@ -142,7 +142,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.6.1 + 3.8.1 {{#supportJava6}} 1.6 @@ -158,6 +158,13 @@ 1.7 {{/java8}} {{/supportJava6}} + true + 128m + 512m + + -Xlint:all + -J-Xss4m + @@ -283,64 +290,67 @@ ${jackson-databind-nullable-version} {{#withXml}} - - - - org.glassfish.jersey.media - jersey-media-jaxb - ${jersey-version} - - + + + org.glassfish.jersey.media + jersey-media-jaxb + ${jersey-version} + {{/withXml}} {{#joda}} - - com.fasterxml.jackson.datatype - jackson-datatype-joda - ${jackson-version} - + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + {{/joda}} {{#java8}} - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - ${jackson-version} - + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + {{/java8}} {{#threetenbp}} - - com.github.joschi.jackson - jackson-datatype-threetenbp - ${threetenbp-version} - + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${threetenbp-version} + {{/threetenbp}} {{^java8}} - - - com.brsanthu - migbase64 - 2.2 - + + + com.brsanthu + migbase64 + 2.2 + {{/java8}} {{#supportJava6}} - - org.apache.commons - commons-lang3 - ${commons_lang3_version} - - - commons-io - commons-io - ${commons_io_version} - + + org.apache.commons + commons-lang3 + ${commons-lang3-version} + + + commons-io + commons-io + ${commons-io-version} + {{/supportJava6}} + + org.tomitribe + tomitribe-http-signatures + ${http-signature-version} + {{#useBeanValidation}} - - - javax.validation - validation-api - 1.1.0.Final - provided - + + + javax.validation + validation-api + 1.1.0.Final + provided + {{/useBeanValidation}} @@ -358,8 +368,8 @@ {{/supportJava6}} {{#supportJava6}} 2.6 - 2.5 - 3.6 + 2.5 + 3.6 {{/supportJava6}} 2.10.3 2.10.3 @@ -368,5 +378,6 @@ 2.9.10 {{/threetenbp}} 4.13 + 1.3 From ef86d38cf1a1143392b405c6c39bab906c95f9c6 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 29 Apr 2020 23:43:21 +0800 Subject: [PATCH 226/370] better docstring for jersey2 client (#6104) --- .../AbstractOpenApiSchema.mustache | 27 ++++++++++++++++- .../jersey2-experimental/ApiResponse.mustache | 15 ++++++++++ libraries/jersey2-experimental/JSON.mustache | 5 ++++ libraries/jersey2-experimental/api.mustache | 30 +++++++++++++++---- .../apiException.mustache | 3 ++ .../jersey2-experimental/oneof_model.mustache | 4 --- 6 files changed, 73 insertions(+), 11 deletions(-) diff --git a/libraries/jersey2-experimental/AbstractOpenApiSchema.mustache b/libraries/jersey2-experimental/AbstractOpenApiSchema.mustache index 607c223aa26..61fddeca43b 100644 --- a/libraries/jersey2-experimental/AbstractOpenApiSchema.mustache +++ b/libraries/jersey2-experimental/AbstractOpenApiSchema.mustache @@ -7,23 +7,48 @@ import java.lang.reflect.Type; import java.util.Map; import javax.ws.rs.core.GenericType; +/** + * Abstract class for oneOf,anyOf schemas defined in OpenAPI spec + */ {{>additionalModelTypeAnnotations}}{{>generatedAnnotation}} public abstract class AbstractOpenApiSchema { + // store the actual instance of the schema/object private Object instance; - public final String schemaType; + // schema type (e.g. oneOf, anyOf) + private final String schemaType; public AbstractOpenApiSchema(String schemaType) { this.schemaType = schemaType; } + /*** + * Get the list of schemas allowed to be stored in this object + * + * @return an instance of the actual schema/object + */ public abstract Map getSchemas(); + /*** + * Get the actual instance + * + * @return an instance of the actual schema/object + */ public Object getActualInstance() {return instance;} + /*** + * Set the actual instance + * + * @param instance the actual instance of the schema/object + */ public void setActualInstance(Object instance) {this.instance = instance;} + /*** + * Get the schema type (e.g. anyOf, oneOf) + * + * @return the schema type + */ public String getSchemaType() { return schemaType; } diff --git a/libraries/jersey2-experimental/ApiResponse.mustache b/libraries/jersey2-experimental/ApiResponse.mustache index a67b11f054c..5dae9dc1fdf 100644 --- a/libraries/jersey2-experimental/ApiResponse.mustache +++ b/libraries/jersey2-experimental/ApiResponse.mustache @@ -44,14 +44,29 @@ public class ApiResponse { this.data = data; } + /** + * Get the status code + * + * @return status code + */ public int getStatusCode() { return statusCode; } + /** + * Get the headers + * + * @return map of headers + */ public Map> getHeaders() { return headers; } + /** + * Get the data + * + * @return data + */ public T getData() { return data; } diff --git a/libraries/jersey2-experimental/JSON.mustache b/libraries/jersey2-experimental/JSON.mustache index e25b307f7d0..dc3d9893e6d 100644 --- a/libraries/jersey2-experimental/JSON.mustache +++ b/libraries/jersey2-experimental/JSON.mustache @@ -63,5 +63,10 @@ public class JSON implements ContextResolver { return mapper; } + /** + * Get the object mapper + * + * @return object mapper + */ public ObjectMapper getMapper() { return mapper; } } diff --git a/libraries/jersey2-experimental/api.mustache b/libraries/jersey2-experimental/api.mustache index a0730135f71..509ae48a50e 100644 --- a/libraries/jersey2-experimental/api.mustache +++ b/libraries/jersey2-experimental/api.mustache @@ -16,8 +16,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -{{/fullJavaUtil}} +{{/fullJavaUtil}} {{>generatedAnnotation}} {{#operations}} public class {{classname}} { @@ -31,13 +31,24 @@ public class {{classname}} { this.apiClient = apiClient; } + /** + * Get the API cilent + * + * @return API client + */ public ApiClient getApiClient() { return apiClient; } + /** + * Set the API cilent + * + * @param apiClient an instance of API client + */ public void setApiClient(ApiClient apiClient) { this.apiClient = apiClient; } + {{#operation}} {{^vendorExtensions.x-group-parameters}} /** @@ -170,7 +181,8 @@ public class {{classname}} { this.{{localVariablePrefix}}{{paramName}} = {{paramName}}; {{/pathParams}} } - {{#allParams}}{{^isPathParam}} + {{#allParams}} + {{^isPathParam}} /** * Set {{paramName}} @@ -181,7 +193,8 @@ public class {{classname}} { this.{{localVariablePrefix}}{{paramName}} = {{paramName}}; return this; } - {{/isPathParam}}{{/allParams}} + {{/isPathParam}} + {{/allParams}} /** * Execute {{operationId}} request @@ -216,9 +229,12 @@ public class {{classname}} { {{/responses}} {{/responses.0}} - {{#isDeprecated}}* @deprecated{{/isDeprecated}} + {{#isDeprecated}} + * @deprecated{{/isDeprecated}} */ - {{#isDeprecated}}@Deprecated{{/isDeprecated}} + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} public ApiResponse<{{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> executeWithHttpInfo() throws ApiException { return {{operationId}}WithHttpInfo({{#allParams}}{{localVariablePrefix}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); } @@ -234,7 +250,9 @@ public class {{classname}} { {{#externalDocs}}* {{description}} * @see {{summary}} Documentation{{/externalDocs}} */ - {{#isDeprecated}}@Deprecated{{/isDeprecated}} + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} public API{{operationId}}Request {{operationId}}({{#pathParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}) throws ApiException { return new API{{operationId}}Request({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}); } diff --git a/libraries/jersey2-experimental/apiException.mustache b/libraries/jersey2-experimental/apiException.mustache index e8952456591..f0079c7bbec 100644 --- a/libraries/jersey2-experimental/apiException.mustache +++ b/libraries/jersey2-experimental/apiException.mustache @@ -9,6 +9,9 @@ import java.util.Map.Entry; import java.util.TreeMap; {{/caseInsensitiveResponseHeaders}} +/** + * API Exception + */ {{>generatedAnnotation}} public class ApiException extends{{#useRuntimeException}} RuntimeException {{/useRuntimeException}}{{^useRuntimeException}} Exception {{/useRuntimeException}}{ private int code = 0; diff --git a/libraries/jersey2-experimental/oneof_model.mustache b/libraries/jersey2-experimental/oneof_model.mustache index 62289f9b2d7..b5d4442e608 100644 --- a/libraries/jersey2-experimental/oneof_model.mustache +++ b/libraries/jersey2-experimental/oneof_model.mustache @@ -26,10 +26,6 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im return {{classname}}.schemas; } - public String getSchemaType() { - return schemaType; - } - @Override public void setActualInstance(Object instance) { {{#oneOf}} From 1897a5b71cc06c4ff1065d0ce7073e78f1e7c88f Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Sat, 2 May 2020 08:31:45 -0700 Subject: [PATCH 227/370] [Java] Enhancements for HTTP message signature (#6090) * Add code comments * Change 'setup' method to setPrivateKey * Add support for configuring digest algorithm * run script in bin directory * format generated code * Revert "format generated code" This reverts commit 3b527784375bcf86cacf75bd0142f63b91c96ff8. --- .../auth/HttpSignatureAuth.mustache | 99 ++++++++++++++++--- 1 file changed, 87 insertions(+), 12 deletions(-) diff --git a/libraries/jersey2-experimental/auth/HttpSignatureAuth.mustache b/libraries/jersey2-experimental/auth/HttpSignatureAuth.mustache index 3a856e3bc3c..e56e0d22910 100644 --- a/libraries/jersey2-experimental/auth/HttpSignatureAuth.mustache +++ b/libraries/jersey2-experimental/auth/HttpSignatureAuth.mustache @@ -19,42 +19,110 @@ import java.util.List; import org.tomitribe.auth.signatures.*; +/** + * A Configuration object for the HTTP message signature security scheme. + */ public class HttpSignatureAuth implements Authentication { private Signer signer; - private String name; + // An opaque string that the server can use to look up the component they need to validate the signature. + private String keyId; + // The HTTP signature algorithm. private Algorithm algorithm; + // The list of HTTP headers that should be included in the HTTP signature. private List headers; - public HttpSignatureAuth(String name, Algorithm algorithm, List headers) { - this.name = name; + // The digest algorithm which is used to calculate a cryptographic digest of the HTTP request body. + private String digestAlgorithm; + + /** + * Construct a new HTTP signature auth configuration object. + * + * @param keyId An opaque string that the server can use to look up the component they need to validate the signature. + * @param algorithm The signature algorithm. + * @param headers The list of HTTP headers that should be included in the HTTP signature. + */ + public HttpSignatureAuth(String keyId, Algorithm algorithm, List headers) { + this.keyId = keyId; this.algorithm = algorithm; this.headers = headers; + this.digestAlgorithm = "SHA-256"; } - public String getName() { - return name; + /** + * Returns the opaque string that the server can use to look up the component they need to validate the signature. + * + * @return The keyId. + */ + public String getKeyId() { + return keyId; } - public void setName(String name) { - this.name = name; + /** + * Set the HTTP signature key id. + * + * @param keyId An opaque string that the server can use to look up the component they need to validate the signature. + */ + public void setKeyId(String keyId) { + this.keyId = keyId; } + /** + * Returns the HTTP signature algorithm which is used to sign HTTP requests. + */ public Algorithm getAlgorithm() { return algorithm; } + /** + * Sets the HTTP signature algorithm which is used to sign HTTP requests. + * + * @param algorithm The HTTP signature algorithm. + */ public void setAlgorithm(Algorithm algorithm) { this.algorithm = algorithm; } + /** + * Returns the digest algorithm which is used to calculate a cryptographic digest of the HTTP request body. + * + * @see java.security.MessageDigest + */ + public String getDigestAlgorithm() { + return digestAlgorithm; + } + + /** + * Sets the digest algorithm which is used to calculate a cryptographic digest of the HTTP request body. + * + * The exact list of supported digest algorithms depends on the installed security providers. + * Every implementation of the Java platform is required to support "MD5", "SHA-1" and "SHA-256". + * Do not use "MD5" and "SHA-1", they are vulnerable to multiple known attacks. + * By default, "SHA-256" is used. + * + * @param digestAlgorithm The digest algorithm. + * + * @see java.security.MessageDigest + */ + public void setDigestAlgorithm(String digestAlgorithm) { + this.digestAlgorithm = digestAlgorithm; + } + + /** + * Returns the list of HTTP headers that should be included in the HTTP signature. + */ public List getHeaders() { return headers; } + /** + * Sets the list of HTTP headers that should be included in the HTTP signature. + * + * @param headers The HTTP headers. + */ public void setHeaders(List headers) { this.headers = headers; } @@ -67,12 +135,17 @@ public class HttpSignatureAuth implements Authentication { this.signer = signer; } - public void setup(Key key) throws ApiException { + /** + * Set the private key used to sign HTTP requests using the HTTP signature scheme. + * + * @param key The private key. + */ + public void setPrivateKey(Key key) throws ApiException { if (key == null) { - throw new ApiException("key (java.security.Key) cannot be null"); + throw new ApiException("Private key (java.security.Key) cannot be null"); } - signer = new Signer(key, new Signature(name, algorithm, null, headers)); + signer = new Signer(key, new Signature(keyId, algorithm, null, headers)); } @Override @@ -88,11 +161,13 @@ public class HttpSignatureAuth implements Authentication { } if (headers.contains("digest")) { - headerParams.put("digest", "SHA-256=" + new String(Base64.getEncoder().encode(MessageDigest.getInstance("SHA-256").digest(payload.getBytes())))); + headerParams.put("digest", + this.digestAlgorithm + "=" + + new String(Base64.getEncoder().encode(MessageDigest.getInstance(this.digestAlgorithm).digest(payload.getBytes())))); } if (signer == null) { - throw new ApiException("Signer cannot be null. Please run the method `setup` to set it up correctly"); + throw new ApiException("Signer cannot be null. Please call the method `setPrivateKey` to set it up correctly"); } // construct the path with the URL query string From ea2c25adf5e325df24600986c4b49f1a30237e33 Mon Sep 17 00:00:00 2001 From: Ukonn Ra <16066720+UkonnRa@users.noreply.github.com> Date: Sun, 3 May 2020 16:06:18 +0800 Subject: [PATCH 228/370] Add async native Java Client (#4721) * Add async native Java Client * UPDATE: Reformat the samples * test java native async in drone.io * update test count Co-authored-by: William Cheng --- libraries/native/api.mustache | 76 +++++++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 13 deletions(-) diff --git a/libraries/native/api.mustache b/libraries/native/api.mustache index 4c4848ca480..23388d36a76 100644 --- a/libraries/native/api.mustache +++ b/libraries/native/api.mustache @@ -28,6 +28,10 @@ import java.util.List; import java.util.Map; {{/fullJavaUtil}} +{{#asyncNative}} +import java.util.concurrent.CompletableFuture; +{{/asyncNative}} + {{>generatedAnnotation}} {{#operations}} public class {{classname}} { @@ -73,14 +77,19 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}} ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { {{#allParams}} - {{#required}} + {{#required}} // verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { - throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + {{#asyncNative}} + return CompletableFuture.failedFuture(new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}")); + {{/asyncNative}} + {{^asyncNative}} + throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + {{/asyncNative}} } - {{/required}} + {{/required}} {{/allParams}} HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); @@ -122,7 +131,14 @@ public class {{classname}} { {{/bodyParam}} localVarRequestBuilder.header("Accept", "application/json"); + {{^asyncNative}} + try { + {{/asyncNative}} + {{#asyncNative}} + {{#bodyParam}} try { + {{/bodyParam}} + {{/asyncNative}} {{#bodyParam}} byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes({{paramName}}); localVarRequestBuilder.method("{{httpMethod}}", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody)); @@ -136,29 +152,63 @@ public class {{classname}} { if (memberVarInterceptor != null) { memberVarInterceptor.accept(localVarRequestBuilder); } - + {{^asyncNative}} HttpResponse localVarResponse = memberVarHttpClient.send( - localVarRequestBuilder.build(), - HttpResponse.BodyHandlers.ofInputStream()); + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); if (memberVarResponseInterceptor != null) { memberVarResponseInterceptor.accept(localVarResponse); } if (localVarResponse.statusCode()/ 100 != 2) { - throw new ApiException(localVarResponse.statusCode(), - "{{operationId}} call received non-success response", - localVarResponse.headers(), - localVarResponse.body() == null ? null : new String(localVarResponse.body().readAllBytes())); + throw new ApiException(localVarResponse.statusCode(), + "{{operationId}} call received non-success response", + localVarResponse.headers(), + localVarResponse.body() == null ? null : new String(localVarResponse.body().readAllBytes())); } - {{#returnType}} return memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference<{{{returnType}}}>() {}); {{/returnType}} + {{/asyncNative}} + {{#asyncNative}} + return memberVarHttpClient.sendAsync( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofString()).thenComposeAsync(localVarResponse -> { + if (localVarResponse.statusCode()/ 100 != 2) { + return CompletableFuture.failedFuture(new ApiException(localVarResponse.statusCode(), + "{{operationId}} call received non-success response", + localVarResponse.headers(), + localVarResponse.body()) + ); + } else { + return CompletableFuture.completedFuture( + {{#returnValue}} + memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference<{{{returnType}}}>() {}) + {{/returnValue}} + {{^returnValue}} + null + {{/returnValue}} + ); + } + }); + {{/asyncNative}} + {{#asyncNative}} + {{#bodyParam}} + } catch (IOException e) { + return CompletableFuture.failedFuture(new ApiException(e)); + } + {{/bodyParam}} + {{/asyncNative}} + {{^asyncNative}} } catch (IOException e) { throw new ApiException(e); - } catch (InterruptedException e) { + } + {{/asyncNative}} + {{^asyncNative}} + catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new ApiException(e); } + {{/asyncNative}} } {{/operation}} } From 78953c6c04d87ce1be4aa34e834bbfdb3674c5d3 Mon Sep 17 00:00:00 2001 From: Luis Ballabeni Date: Tue, 5 May 2020 01:40:22 -0400 Subject: [PATCH 229/370] Fix #6157: Updated native template to fix null async return (#6168) * Fix #6157: Updated native template to fix null async return Should fix issue: https://github.com/OpenAPITools/openapi-generator/issues/6157 * fixed uncaught json exception in java native api gen * cleaning up Co-authored-by: Luis Ballabeni --- libraries/native/api.mustache | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/libraries/native/api.mustache b/libraries/native/api.mustache index 23388d36a76..7d6ed2d4bb7 100644 --- a/libraries/native/api.mustache +++ b/libraries/native/api.mustache @@ -180,14 +180,18 @@ public class {{classname}} { localVarResponse.body()) ); } else { - return CompletableFuture.completedFuture( - {{#returnValue}} - memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference<{{{returnType}}}>() {}) - {{/returnValue}} - {{^returnValue}} - null - {{/returnValue}} - ); + try { + return CompletableFuture.completedFuture( + {{#returnType}} + memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference<{{{returnType}}}>() {}) + {{/returnType}} + {{^returnType}} + null + {{/returnType}} + ); + } catch (IOException e) { + return CompletableFuture.failedFuture(new ApiException(e)); + } } }); {{/asyncNative}} From 8722ed46bb90e715eda336b2d53d2acee9ba4bc6 Mon Sep 17 00:00:00 2001 From: Christophe Bornet Date: Mon, 11 May 2020 09:18:47 +0200 Subject: [PATCH 230/370] Add full OAuth2 support to jersey2-experimental codegen (#6183) * Add full Oauth2 support to Jersey client * Regenerate jersey2-experimental sample * Regenerate all java clients --- StringUtil.mustache | 22 ++ .../jersey2-experimental/ApiClient.mustache | 285 ++++++++++++------ .../jersey2-experimental/auth/OAuth.mustache | 158 +++++++++- libraries/jersey2-experimental/pom.mustache | 7 + 4 files changed, 372 insertions(+), 100 deletions(-) diff --git a/StringUtil.mustache b/StringUtil.mustache index ce52c82384d..e3d5d6e9088 100644 --- a/StringUtil.mustache +++ b/StringUtil.mustache @@ -2,6 +2,9 @@ package {{invokerPackage}}; +import java.util.Collection; +import java.util.Iterator; + {{>generatedAnnotation}} public class StringUtil { /** @@ -47,4 +50,23 @@ public class StringUtil { } return out.toString(); } + + /** + * Join a list of strings with the given separator. + * + * @param list The list of strings + * @param separator The separator + * @return the resulting string + */ + public static String join(Collection list, String separator) { + Iterator iterator = list.iterator(); + StringBuilder out = new StringBuilder(); + if (iterator.hasNext()) { + out.append(iterator.next()); + } + while (iterator.hasNext()) { + out.append(separator).append(iterator.next()); + } + return out.toString(); + } } diff --git a/libraries/jersey2-experimental/ApiClient.mustache b/libraries/jersey2-experimental/ApiClient.mustache index 10a976f6d76..c0b67407f65 100644 --- a/libraries/jersey2-experimental/ApiClient.mustache +++ b/libraries/jersey2-experimental/ApiClient.mustache @@ -11,6 +11,9 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; +{{#hasOAuthMethods}} +import com.github.scribejava.core.model.OAuth2AccessToken; +{{/hasOAuthMethods}} import org.glassfish.jersey.client.ClientConfig; import org.glassfish.jersey.client.ClientProperties; import org.glassfish.jersey.client.HttpUrlConnectorProvider; @@ -43,7 +46,6 @@ import java.util.List; import java.util.Arrays; import java.util.ArrayList; import java.util.Date; -import java.util.TimeZone; import java.net.URLEncoder; @@ -59,11 +61,10 @@ import {{invokerPackage}}.auth.HttpBasicAuth; import {{invokerPackage}}.auth.HttpBearerAuth; import {{invokerPackage}}.auth.HttpSignatureAuth; import {{invokerPackage}}.auth.ApiKeyAuth; -import {{invokerPackage}}.model.AbstractOpenApiSchema; - {{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} +import {{invokerPackage}}.model.AbstractOpenApiSchema; {{>generatedAnnotation}} public class ApiClient { @@ -178,7 +179,7 @@ public class ApiClient { authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}")); {{/isApiKey}} {{#isOAuth}} - authentications.put("{{name}}", new OAuth()); + authentications.put("{{name}}", new OAuth(basePath, "{{tokenUrl}}")); {{/isOAuth}} {{/authMethods}} // Prevent the authentications from being modified. @@ -191,6 +192,7 @@ public class ApiClient { /** * Gets the JSON instance to do JSON serialization and deserialization. + * * @return JSON */ public JSON getJSON() { @@ -212,6 +214,7 @@ public class ApiClient { public ApiClient setBasePath(String basePath) { this.basePath = basePath; + setOauthBasePath(basePath); return this; } @@ -221,6 +224,7 @@ public class ApiClient { public ApiClient setServers(List servers) { this.servers = servers; + updateBasePath(); return this; } @@ -230,6 +234,7 @@ public class ApiClient { public ApiClient setServerIndex(Integer serverIndex) { this.serverIndex = serverIndex; + updateBasePath(); return this; } @@ -239,11 +244,25 @@ public class ApiClient { public ApiClient setServerVariables(Map serverVariables) { this.serverVariables = serverVariables; + updateBasePath(); return this; } + private void updateBasePath() { + setBasePath(servers.get(serverIndex).URL(serverVariables)); + } + + private void setOauthBasePath(String basePath) { + for(Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setBasePath(basePath); + } + } + } + /** * Get authentications (key: authentication name, value: authentication). + * * @return Map of authentication object */ public Map getAuthentications() { @@ -262,13 +281,14 @@ public class ApiClient { /** * Helper method to set username for the first HTTP basic authentication. + * * @param username Username */ - public void setUsername(String username) { + public ApiClient setUsername(String username) { for (Authentication auth : authentications.values()) { if (auth instanceof HttpBasicAuth) { ((HttpBasicAuth) auth).setUsername(username); - return; + return this; } } throw new RuntimeException("No HTTP basic authentication configured!"); @@ -276,13 +296,14 @@ public class ApiClient { /** * Helper method to set password for the first HTTP basic authentication. + * * @param password Password */ - public void setPassword(String password) { + public ApiClient setPassword(String password) { for (Authentication auth : authentications.values()) { if (auth instanceof HttpBasicAuth) { ((HttpBasicAuth) auth).setPassword(password); - return; + return this; } } throw new RuntimeException("No HTTP basic authentication configured!"); @@ -290,13 +311,14 @@ public class ApiClient { /** * Helper method to set API key value for the first API key authentication. + * * @param apiKey API key */ - public void setApiKey(String apiKey) { + public ApiClient setApiKey(String apiKey) { for (Authentication auth : authentications.values()) { if (auth instanceof ApiKeyAuth) { ((ApiKeyAuth) auth).setApiKey(apiKey); - return; + return this; } } throw new RuntimeException("No API key authentication configured!"); @@ -307,29 +329,31 @@ public class ApiClient { * * @param secrets Hash map from authentication name to its secret. */ - public void configureApiKeys(HashMap secrets) { + public ApiClient configureApiKeys(HashMap secrets) { for (Map.Entry authEntry : authentications.entrySet()) { Authentication auth = authEntry.getValue(); if (auth instanceof ApiKeyAuth) { String name = authEntry.getKey(); // respect x-auth-id-alias property - name = authenticationLookup.getOrDefault(name, name); + name = authenticationLookup.containsKey(name) ? authenticationLookup.get(name) : name; if (secrets.containsKey(name)) { ((ApiKeyAuth) auth).setApiKey(secrets.get(name)); } } } + return this; } /** * Helper method to set API key prefix for the first API key authentication. + * * @param apiKeyPrefix API key prefix */ - public void setApiKeyPrefix(String apiKeyPrefix) { + public ApiClient setApiKeyPrefix(String apiKeyPrefix) { for (Authentication auth : authentications.values()) { if (auth instanceof ApiKeyAuth) { ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); - return; + return this; } } throw new RuntimeException("No API key authentication configured!"); @@ -337,28 +361,92 @@ public class ApiClient { /** * Helper method to set bearer token for the first Bearer authentication. + * * @param bearerToken Bearer token */ - public void setBearerToken(String bearerToken) { + public ApiClient setBearerToken(String bearerToken) { for (Authentication auth : authentications.values()) { if (auth instanceof HttpBearerAuth) { ((HttpBearerAuth) auth).setBearerToken(bearerToken); - return; + return this; } } throw new RuntimeException("No Bearer authentication configured!"); } + {{#hasOAuthMethods}} /** * Helper method to set access token for the first OAuth2 authentication. * @param accessToken Access token */ - public void setAccessToken(String accessToken) { + public ApiClient setAccessToken(String accessToken) { for (Authentication auth : authentications.values()) { if (auth instanceof OAuth) { ((OAuth) auth).setAccessToken(accessToken); - return; + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Helper method to set the credentials for the first OAuth2 authentication. + * + * @param clientId the client ID + * @param clientSecret the client secret + */ + public ApiClient setOauthCredentials(String clientId, String clientSecret) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setCredentials(clientId, clientSecret); + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Helper method to set the password flow for the first OAuth2 authentication. + * + * @param username the user name + * @param password the user password + */ + public ApiClient setOauthPasswordFlow(String username, String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).usePasswordFlow(username, password); + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Helper method to set the authorization code flow for the first OAuth2 authentication. + * + * @param code the authorization code + */ + public ApiClient setOauthAuthorizationCodeFlow(String code) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).useAuthorizationCodeFlow(code); + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Helper method to set the scopes for the first OAuth2 authentication. + * + * @param scope the oauth scope + */ + public ApiClient setOauthScope(String scope) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setScope(scope); + return this; } } throw new RuntimeException("No OAuth2 authentication configured!"); @@ -787,9 +875,9 @@ public class ApiClient { } if (matchCounter > 1 && "oneOf".equals(schema.getSchemaType())) {// more than 1 match for oneOf - throw new ApiException("Response body is invalid as it matches more than one schema (" + String.join(", ", matchSchemas) + ") defined in the oneOf model: " + schema.getClass().getName()); + throw new ApiException("Response body is invalid as it matches more than one schema (" + StringUtil.join(matchSchemas, ", ") + ") defined in the oneOf model: " + schema.getClass().getName()); } else if (matchCounter == 0) { // fail to match any in oneOf/anyOf schemas - throw new ApiException("Response body is invalid as it doens't match any schemas (" + String.join(", ", schema.getSchemas().keySet()) + ") defined in the oneOf/anyOf model: " + schema.getClass().getName()); + throw new ApiException("Response body is invalid as it doens't match any schemas (" + StringUtil.join(schema.getSchemas().keySet(), ", ") + ") defined in the oneOf/anyOf model: " + schema.getClass().getName()); } else { // only one matched schema.setActualInstance(result); return schema; @@ -910,29 +998,35 @@ public class ApiClient { * @return The response body in type of string * @throws ApiException API exception */ - public ApiResponse invokeAPI(String operation, String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType, AbstractOpenApiSchema schema) throws ApiException { + public ApiResponse invokeAPI( + String operation, + String path, + String method, + List queryParams, + Object body, + Map headerParams, + Map cookieParams, + Map formParams, + String accept, + String contentType, + String[] authNames, + GenericType returnType, + AbstractOpenApiSchema schema) + throws ApiException { // Not using `.target(targetURL).path(path)` below, // to support (constant) query string in `path`, e.g. "/posts?draft=1" String targetURL; - if (serverIndex != null) { - Integer index; - List serverConfigurations; - Map variables; - - if (operationServers.containsKey(operation)) { - index = operationServerIndex.getOrDefault(operation, serverIndex); - variables = operationServerVariables.getOrDefault(operation, serverVariables); - serverConfigurations = operationServers.get(operation); - } else { - index = serverIndex; - variables = serverVariables; - serverConfigurations = servers; - } + if (operationServers.containsKey(operation)) { + Integer index = operationServerIndex.containsKey(operation) ? operationServerIndex.get(operation) : serverIndex; + Map variables = operationServerVariables.containsKey(operation) ? + operationServerVariables.get(operation) : serverVariables; + List serverConfigurations = operationServers.get(operation); if (index < 0 || index >= serverConfigurations.size()) { - throw new ArrayIndexOutOfBoundsException(String.format( - "Invalid index %d when selecting the host settings. Must be less than %d", index, serverConfigurations.size() - )); + throw new ArrayIndexOutOfBoundsException( + String.format( + "Invalid index %d when selecting the host settings. Must be less than %d", + index, serverConfigurations.size())); } targetURL = serverConfigurations.get(index).URL(variables) + path; } else { @@ -950,13 +1044,6 @@ public class ApiClient { Invocation.Builder invocationBuilder = target.request().accept(accept); - for (Entry entry : headerParams.entrySet()) { - String value = entry.getValue(); - if (value != null) { - invocationBuilder = invocationBuilder.header(entry.getKey(), value); - } - } - for (Entry entry : cookieParams.entrySet()) { String value = entry.getValue(); if (value != null) { @@ -971,63 +1058,63 @@ public class ApiClient { } } - for (Entry entry : defaultHeaderMap.entrySet()) { - String key = entry.getKey(); - if (!headerParams.containsKey(key)) { - String value = entry.getValue(); - if (value != null) { - invocationBuilder = invocationBuilder.header(key, value); - } - } - } - Entity entity = serialize(body, formParams, contentType); // put all headers in one place - Map allHeaderParams = new HashMap<>(); - allHeaderParams.putAll(defaultHeaderMap); + Map allHeaderParams = new HashMap<>(defaultHeaderMap); allHeaderParams.putAll(headerParams); - + // update different parameters (e.g. headers) for authentication - updateParamsForAuth(authNames, queryParams, allHeaderParams, cookieParams, serializeToString(body, formParams, contentType), method, target.getUri()); + updateParamsForAuth( + authNames, + queryParams, + allHeaderParams, + cookieParams, + serializeToString(body, formParams, contentType), + method, + target.getUri()); + + for (Entry entry : allHeaderParams.entrySet()) { + String value = entry.getValue(); + if (value != null) { + invocationBuilder = invocationBuilder.header(entry.getKey(), value); + } + } Response response = null; try { - if ("GET".equals(method)) { - response = invocationBuilder.get(); - } else if ("POST".equals(method)) { - response = invocationBuilder.post(entity); - } else if ("PUT".equals(method)) { - response = invocationBuilder.put(entity); - } else if ("DELETE".equals(method)) { - response = invocationBuilder.method("DELETE", entity); - } else if ("PATCH".equals(method)) { - response = invocationBuilder.method("PATCH", entity); - } else if ("HEAD".equals(method)) { - response = invocationBuilder.head(); - } else if ("OPTIONS".equals(method)) { - response = invocationBuilder.options(); - } else if ("TRACE".equals(method)) { - response = invocationBuilder.trace(); - } else { - throw new ApiException(500, "unknown method type " + method); + response = sendRequest(method, invocationBuilder, entity); + + // If OAuth is used and a status 401 is received, renew the access token and retry the request + if (response.getStatusInfo() == Status.UNAUTHORIZED) { + for (String authName : authNames) { + Authentication authentication = authentications.get(authName); + if (authentication instanceof OAuth) { + OAuth2AccessToken accessToken = ((OAuth) authentication).renewAccessToken(); + if (accessToken != null) { + invocationBuilder.header("Authorization", null); + invocationBuilder.header("Authorization", "Bearer " + accessToken.getAccessToken()); + response = sendRequest(method, invocationBuilder, entity); + } + break; + } + } } int statusCode = response.getStatusInfo().getStatusCode(); Map> responseHeaders = buildResponseHeaders(response); - if (response.getStatus() == Status.NO_CONTENT.getStatusCode()) { - return new ApiResponse<{{#supportJava6}}T{{/supportJava6}}>(statusCode, responseHeaders); + if (response.getStatusInfo() == Status.NO_CONTENT) { + return new ApiResponse(statusCode, responseHeaders); } else if (response.getStatusInfo().getFamily() == Status.Family.SUCCESSFUL) { - if (returnType == null) - return new ApiResponse<{{#supportJava6}}T{{/supportJava6}}>(statusCode, responseHeaders); - else - if (schema == null) { - return new ApiResponse<>(statusCode, responseHeaders, deserialize(response, returnType)); - } else { // oneOf/anyOf - return new ApiResponse<>(statusCode, responseHeaders, (T)deserializeSchemas(response, schema)); - } + if (returnType == null) return new ApiResponse(statusCode, responseHeaders); + else if (schema == null) { + return new ApiResponse(statusCode, responseHeaders, deserialize(response, returnType)); + } else { // oneOf/anyOf + return new ApiResponse( + statusCode, responseHeaders, (T) deserializeSchemas(response, schema)); + } } else { String message = "error"; String respBody = null; @@ -1040,20 +1127,34 @@ public class ApiClient { } } throw new ApiException( - response.getStatus(), - message, - buildResponseHeaders(response), - respBody); + response.getStatus(), message, buildResponseHeaders(response), respBody); } } finally { try { response.close(); } catch (Exception e) { - // it's not critical, since the response object is local in method invokeAPI; that's fine, just continue + // it's not critical, since the response object is local in method invokeAPI; that's fine, + // just continue } } } + private Response sendRequest(String method, Invocation.Builder invocationBuilder, Entity entity) { + Response response; + if ("POST".equals(method)) { + response = invocationBuilder.post(entity); + } else if ("PUT".equals(method)) { + response = invocationBuilder.put(entity); + } else if ("DELETE".equals(method)) { + response = invocationBuilder.method("DELETE", entity); + } else if ("PATCH".equals(method)) { + response = invocationBuilder.method("PATCH", entity); + } else { + response = invocationBuilder.method(method); + } + return response; + } + /** * @deprecated Add qualified name of the operation as a first parameter. */ diff --git a/libraries/jersey2-experimental/auth/OAuth.mustache b/libraries/jersey2-experimental/auth/OAuth.mustache index 8622798ad37..d18b41b0e4c 100644 --- a/libraries/jersey2-experimental/auth/OAuth.mustache +++ b/libraries/jersey2-experimental/auth/OAuth.mustache @@ -4,27 +4,169 @@ package {{invokerPackage}}.auth; import {{invokerPackage}}.Pair; import {{invokerPackage}}.ApiException; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.exceptions.OAuthException; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth.OAuth20Service; +import javax.ws.rs.core.UriBuilder; +import java.io.IOException; +import java.net.MalformedURLException; import java.net.URI; -import java.util.Map; import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.logging.Level; +import java.util.logging.Logger; {{>generatedAnnotation}} public class OAuth implements Authentication { - private String accessToken; + private static final Logger log = Logger.getLogger(OAuth.class.getName()); - public String getAccessToken() { - return accessToken; + private String tokenUrl; + private String absoluteTokenUrl; + private OAuthFlow flow = OAuthFlow.application; + private OAuth20Service service; + private DefaultApi20 authApi; + private String scope; + private String username; + private String password; + private String code; + private volatile OAuth2AccessToken accessToken; + + public OAuth(String basePath, String tokenUrl) { + this.tokenUrl = tokenUrl; + this.absoluteTokenUrl = createAbsoluteTokenUrl(basePath, tokenUrl); + authApi = new DefaultApi20() { + @Override + public String getAccessTokenEndpoint() { + return absoluteTokenUrl; + } + + @Override + protected String getAuthorizationBaseUrl() { + throw new UnsupportedOperationException("Shouldn't get there !"); + } + }; } - public void setAccessToken(String accessToken) { - this.accessToken = accessToken; + private static String createAbsoluteTokenUrl(String basePath, String tokenUrl) { + if (!URI.create(tokenUrl).isAbsolute()) { + try { + return UriBuilder.fromPath(basePath).path(tokenUrl).build().toURL().toString(); + } catch (MalformedURLException e) { + log.log(Level.SEVERE, "Couldn't create absolute token URL", e); + } + } + return tokenUrl; } @Override - public void applyToParams(List queryParams, Map headerParams, Map cookieParams, String payload, String method, URI uri) throws ApiException { + public void applyToParams( + List queryParams, + Map headerParams, + Map cookieParams, + String payload, + String method, + URI uri) + throws ApiException { + + if (accessToken == null) { + obtainAccessToken(null); + } + if (accessToken != null) { + headerParams.put("Authorization", "Bearer " + accessToken.getAccessToken()); + } + } + + public OAuth2AccessToken renewAccessToken() throws ApiException { + String refreshToken = null; if (accessToken != null) { - headerParams.put("Authorization", "Bearer " + accessToken); + refreshToken = accessToken.getRefreshToken(); + accessToken = null; + } + return obtainAccessToken(refreshToken); + } + + public synchronized OAuth2AccessToken obtainAccessToken(String refreshToken) throws ApiException { + if (service == null) { + return null; + } + try { + if (refreshToken != null) { + return service.refreshAccessToken(refreshToken); + } + } catch (OAuthException | InterruptedException | ExecutionException | IOException e) { + log.log(Level.FINE, "Refreshing the access token using the refresh token failed", e); + } + try { + switch (flow) { + case password: + if (username != null && password != null) { + accessToken = service.getAccessTokenPasswordGrant(username, password, scope); + } + break; + case accessCode: + if (code != null) { + accessToken = service.getAccessToken(code); + code = null; + } + break; + case application: + accessToken = service.getAccessTokenClientCredentialsGrant(scope); + } + } catch (OAuthException | InterruptedException | ExecutionException | IOException e) { + throw new ApiException(e); } + return accessToken; + } + + public OAuth2AccessToken getAccessToken() { + return accessToken; + } + + public OAuth setAccessToken(OAuth2AccessToken accessToken) { + this.accessToken = accessToken; + return this; + } + + public OAuth setAccessToken(String accessToken) { + this.accessToken = new OAuth2AccessToken(accessToken); + return this; + } + + public OAuth setScope(String scope) { + this.scope = scope; + return this; + } + + public OAuth setCredentials(String clientId, String clientSecret) { + service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .build(authApi); + return this; + } + + public OAuth usePasswordFlow(String username, String password) { + this.flow = OAuthFlow.password; + this.username = username; + this.password = password; + return this; + } + + public OAuth useAuthorizationCodeFlow(String code) { + this.flow = OAuthFlow.accessCode; + this.code = code; + return this; + } + + public OAuth setFlow(OAuthFlow flow) { + this.flow = flow; + return this; + } + + public void setBasePath(String basePath) { + this.absoluteTokenUrl = createAbsoluteTokenUrl(basePath, tokenUrl); } } diff --git a/libraries/jersey2-experimental/pom.mustache b/libraries/jersey2-experimental/pom.mustache index a71ab263863..ce5855067d5 100644 --- a/libraries/jersey2-experimental/pom.mustache +++ b/libraries/jersey2-experimental/pom.mustache @@ -343,6 +343,13 @@ tomitribe-http-signatures ${http-signature-version} + {{#hasOAuthMethods}} + + com.github.scribejava + scribejava-apis + 6.9.0 + + {{/hasOAuthMethods}} {{#useBeanValidation}} From 24385d0b30908bbff43cc52f8376f88f1435143a Mon Sep 17 00:00:00 2001 From: William Cheng Date: Tue, 12 May 2020 18:27:33 +0800 Subject: [PATCH 231/370] [Java][jersey2] replace jersey2 with jersey2-experimental (#6251) * replace jersey2 with jersey2-experimental * better handling of oauth * add jersey2 java8 samples * add dependency to test pom * fix test, update doc --- .../jersey2-experimental/ApiClient.mustache | 1234 ----------------- .../jersey2-experimental/ApiResponse.mustache | 73 - libraries/jersey2-experimental/JSON.mustache | 72 - libraries/jersey2-experimental/api.mustache | 262 ---- .../apiException.mustache | 99 -- .../jersey2-experimental/api_doc.mustache | 121 -- .../jersey2-experimental/api_test.mustache | 51 - .../build.gradle.mustache | 170 --- .../jersey2-experimental/build.sbt.mustache | 38 - libraries/jersey2-experimental/pom.mustache | 390 ------ .../AbstractOpenApiSchema.mustache | 0 libraries/jersey2/ApiClient.mustache | 406 ++++-- libraries/jersey2/ApiResponse.mustache | 15 + libraries/jersey2/JSON.mustache | 11 +- .../anyof_model.mustache | 0 libraries/jersey2/api.mustache | 39 +- libraries/jersey2/apiException.mustache | 3 + libraries/jersey2/api_test.mustache | 12 +- .../auth/ApiKeyAuth.mustache | 0 .../auth/Authentication.mustache | 0 .../auth/HttpBasicAuth.mustache | 0 .../auth/HttpBearerAuth.mustache | 0 .../auth/HttpSignatureAuth.mustache | 0 .../auth/OAuth.mustache | 0 .../auth/OAuthFlow.mustache | 0 .../model.mustache | 0 .../oneof_model.mustache | 0 .../pojo.mustache | 0 libraries/jersey2/pom.mustache | 123 +- 29 files changed, 450 insertions(+), 2669 deletions(-) delete mode 100644 libraries/jersey2-experimental/ApiClient.mustache delete mode 100644 libraries/jersey2-experimental/ApiResponse.mustache delete mode 100644 libraries/jersey2-experimental/JSON.mustache delete mode 100644 libraries/jersey2-experimental/api.mustache delete mode 100644 libraries/jersey2-experimental/apiException.mustache delete mode 100644 libraries/jersey2-experimental/api_doc.mustache delete mode 100644 libraries/jersey2-experimental/api_test.mustache delete mode 100644 libraries/jersey2-experimental/build.gradle.mustache delete mode 100644 libraries/jersey2-experimental/build.sbt.mustache delete mode 100644 libraries/jersey2-experimental/pom.mustache rename libraries/{jersey2-experimental => jersey2}/AbstractOpenApiSchema.mustache (100%) rename libraries/{jersey2-experimental => jersey2}/anyof_model.mustache (100%) rename libraries/{jersey2-experimental => jersey2}/auth/ApiKeyAuth.mustache (100%) rename libraries/{jersey2-experimental => jersey2}/auth/Authentication.mustache (100%) rename libraries/{jersey2-experimental => jersey2}/auth/HttpBasicAuth.mustache (100%) rename libraries/{jersey2-experimental => jersey2}/auth/HttpBearerAuth.mustache (100%) rename libraries/{jersey2-experimental => jersey2}/auth/HttpSignatureAuth.mustache (100%) rename libraries/{jersey2-experimental => jersey2}/auth/OAuth.mustache (100%) rename libraries/{jersey2-experimental => jersey2}/auth/OAuthFlow.mustache (100%) rename libraries/{jersey2-experimental => jersey2}/model.mustache (100%) rename libraries/{jersey2-experimental => jersey2}/oneof_model.mustache (100%) rename libraries/{jersey2-experimental => jersey2}/pojo.mustache (100%) diff --git a/libraries/jersey2-experimental/ApiClient.mustache b/libraries/jersey2-experimental/ApiClient.mustache deleted file mode 100644 index c0b67407f65..00000000000 --- a/libraries/jersey2-experimental/ApiClient.mustache +++ /dev/null @@ -1,1234 +0,0 @@ -package {{invokerPackage}}; - -import javax.ws.rs.client.Client; -import javax.ws.rs.client.ClientBuilder; -import javax.ws.rs.client.Entity; -import javax.ws.rs.client.Invocation; -import javax.ws.rs.client.WebTarget; -import javax.ws.rs.core.Form; -import javax.ws.rs.core.GenericType; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; - -{{#hasOAuthMethods}} -import com.github.scribejava.core.model.OAuth2AccessToken; -{{/hasOAuthMethods}} -import org.glassfish.jersey.client.ClientConfig; -import org.glassfish.jersey.client.ClientProperties; -import org.glassfish.jersey.client.HttpUrlConnectorProvider; -import org.glassfish.jersey.jackson.JacksonFeature; -import org.glassfish.jersey.media.multipart.FormDataBodyPart; -import org.glassfish.jersey.media.multipart.FormDataContentDisposition; -import org.glassfish.jersey.media.multipart.MultiPart; -import org.glassfish.jersey.media.multipart.MultiPartFeature; - -import java.io.IOException; -import java.io.InputStream; - -import java.net.URI; -{{^supportJava6}} -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; -import org.glassfish.jersey.logging.LoggingFeature; -{{/supportJava6}} -{{#supportJava6}} -import org.apache.commons.io.FileUtils; -import org.glassfish.jersey.filter.LoggingFilter; -{{/supportJava6}} -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.Map.Entry; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Arrays; -import java.util.ArrayList; -import java.util.Date; - -import java.net.URLEncoder; - -import java.io.File; -import java.io.UnsupportedEncodingException; - -import java.text.DateFormat; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import {{invokerPackage}}.auth.Authentication; -import {{invokerPackage}}.auth.HttpBasicAuth; -import {{invokerPackage}}.auth.HttpBearerAuth; -import {{invokerPackage}}.auth.HttpSignatureAuth; -import {{invokerPackage}}.auth.ApiKeyAuth; -{{#hasOAuthMethods}} -import {{invokerPackage}}.auth.OAuth; -{{/hasOAuthMethods}} -import {{invokerPackage}}.model.AbstractOpenApiSchema; - -{{>generatedAnnotation}} -public class ApiClient { - protected Map defaultHeaderMap = new HashMap(); - protected Map defaultCookieMap = new HashMap(); - protected String basePath = "{{{basePath}}}"; - protected List servers = new ArrayList({{#servers}}{{#-first}}Arrays.asList( -{{/-first}} new ServerConfiguration( - "{{{url}}}", - "{{{description}}}{{^description}}No description provided{{/description}}", - new HashMap(){{#variables}}{{#-first}} {{ -{{/-first}} put("{{{name}}}", new ServerVariable( - "{{{description}}}{{^description}}No description provided{{/description}}", - "{{{defaultValue}}}", - new HashSet( - {{#enumValues}} - {{#-first}} - Arrays.asList( - {{/-first}} - "{{{.}}}"{{^-last}},{{/-last}} - {{#-last}} - ) - {{/-last}} - {{/enumValues}} - ) - )); - {{#-last}} - }}{{/-last}}{{/variables}} - ){{^-last}},{{/-last}} - {{#-last}} - ){{/-last}}{{/servers}}); - protected Integer serverIndex = 0; - protected Map serverVariables = null; - protected Map> operationServers = new HashMap>() {{ - {{#apiInfo}} - {{#apis}} - {{#operations}} - {{#operation}} - {{#servers}} - {{#-first}} - put("{{{classname}}}.{{{operationId}}}", new ArrayList(Arrays.asList( - {{/-first}} - new ServerConfiguration( - "{{{url}}}", - "{{{description}}}{{^description}}No description provided{{/description}}", - new HashMap(){{#variables}}{{#-first}} {{ -{{/-first}} put("{{{name}}}", new ServerVariable( - "{{{description}}}{{^description}}No description provided{{/description}}", - "{{{defaultValue}}}", - new HashSet( - {{#enumValues}} - {{#-first}} - Arrays.asList( - {{/-first}} - "{{{.}}}"{{^-last}},{{/-last}} - {{#-last}} - ) - {{/-last}} - {{/enumValues}} - ) - )); - {{#-last}} - }}{{/-last}}{{/variables}} - ){{^-last}},{{/-last}} - {{#-last}} - )));{{/-last}} - {{/servers}} - {{/operation}} - {{/operations}} - {{/apis}} - {{/apiInfo}} - }}; - protected Map operationServerIndex = new HashMap(); - protected Map> operationServerVariables = new HashMap>(); - protected boolean debugging = false; - protected int connectionTimeout = 0; - private int readTimeout = 0; - - protected Client httpClient; - protected JSON json; - protected String tempFolderPath = null; - - protected Map authentications; - protected Map authenticationLookup; - - protected DateFormat dateFormat; - - public ApiClient() { - json = new JSON(); - httpClient = buildHttpClient(debugging); - - this.dateFormat = new RFC3339DateFormat(); - - // Set default User-Agent. - setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); - - // Setup authentications (key: authentication name, value: authentication). - authentications = new HashMap(); - {{#authMethods}} - {{#isBasic}} - {{#isBasicBasic}} - authentications.put("{{name}}", new HttpBasicAuth()); - {{/isBasicBasic}} - {{#isBasicBearer}} - authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}")); - {{/isBasicBearer}} - {{#isHttpSignature}} - authentications.put("{{name}}", new HttpSignatureAuth("{{name}}", null, null)); - {{/isHttpSignature}} - {{/isBasic}} - {{#isApiKey}} - authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}")); - {{/isApiKey}} - {{#isOAuth}} - authentications.put("{{name}}", new OAuth(basePath, "{{tokenUrl}}")); - {{/isOAuth}} - {{/authMethods}} - // Prevent the authentications from being modified. - authentications = Collections.unmodifiableMap(authentications); - - // Setup authentication lookup (key: authentication alias, value: authentication name) - authenticationLookup = new HashMap();{{#authMethods}}{{#vendorExtensions.x-auth-id-alias}} - authenticationLookup.put("{{name}}", "{{.}}");{{/vendorExtensions.x-auth-id-alias}}{{/authMethods}} - } - - /** - * Gets the JSON instance to do JSON serialization and deserialization. - * - * @return JSON - */ - public JSON getJSON() { - return json; - } - - public Client getHttpClient() { - return httpClient; - } - - public ApiClient setHttpClient(Client httpClient) { - this.httpClient = httpClient; - return this; - } - - public String getBasePath() { - return basePath; - } - - public ApiClient setBasePath(String basePath) { - this.basePath = basePath; - setOauthBasePath(basePath); - return this; - } - - public List getServers() { - return servers; - } - - public ApiClient setServers(List servers) { - this.servers = servers; - updateBasePath(); - return this; - } - - public Integer getServerIndex() { - return serverIndex; - } - - public ApiClient setServerIndex(Integer serverIndex) { - this.serverIndex = serverIndex; - updateBasePath(); - return this; - } - - public Map getServerVariables() { - return serverVariables; - } - - public ApiClient setServerVariables(Map serverVariables) { - this.serverVariables = serverVariables; - updateBasePath(); - return this; - } - - private void updateBasePath() { - setBasePath(servers.get(serverIndex).URL(serverVariables)); - } - - private void setOauthBasePath(String basePath) { - for(Authentication auth : authentications.values()) { - if (auth instanceof OAuth) { - ((OAuth) auth).setBasePath(basePath); - } - } - } - - /** - * Get authentications (key: authentication name, value: authentication). - * - * @return Map of authentication object - */ - public Map getAuthentications() { - return authentications; - } - - /** - * Get authentication for the given name. - * - * @param authName The authentication name - * @return The authentication, null if not found - */ - public Authentication getAuthentication(String authName) { - return authentications.get(authName); - } - - /** - * Helper method to set username for the first HTTP basic authentication. - * - * @param username Username - */ - public ApiClient setUsername(String username) { - for (Authentication auth : authentications.values()) { - if (auth instanceof HttpBasicAuth) { - ((HttpBasicAuth) auth).setUsername(username); - return this; - } - } - throw new RuntimeException("No HTTP basic authentication configured!"); - } - - /** - * Helper method to set password for the first HTTP basic authentication. - * - * @param password Password - */ - public ApiClient setPassword(String password) { - for (Authentication auth : authentications.values()) { - if (auth instanceof HttpBasicAuth) { - ((HttpBasicAuth) auth).setPassword(password); - return this; - } - } - throw new RuntimeException("No HTTP basic authentication configured!"); - } - - /** - * Helper method to set API key value for the first API key authentication. - * - * @param apiKey API key - */ - public ApiClient setApiKey(String apiKey) { - for (Authentication auth : authentications.values()) { - if (auth instanceof ApiKeyAuth) { - ((ApiKeyAuth) auth).setApiKey(apiKey); - return this; - } - } - throw new RuntimeException("No API key authentication configured!"); - } - - /** - * Helper method to configure authentications which respects aliases of API keys. - * - * @param secrets Hash map from authentication name to its secret. - */ - public ApiClient configureApiKeys(HashMap secrets) { - for (Map.Entry authEntry : authentications.entrySet()) { - Authentication auth = authEntry.getValue(); - if (auth instanceof ApiKeyAuth) { - String name = authEntry.getKey(); - // respect x-auth-id-alias property - name = authenticationLookup.containsKey(name) ? authenticationLookup.get(name) : name; - if (secrets.containsKey(name)) { - ((ApiKeyAuth) auth).setApiKey(secrets.get(name)); - } - } - } - return this; - } - - /** - * Helper method to set API key prefix for the first API key authentication. - * - * @param apiKeyPrefix API key prefix - */ - public ApiClient setApiKeyPrefix(String apiKeyPrefix) { - for (Authentication auth : authentications.values()) { - if (auth instanceof ApiKeyAuth) { - ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); - return this; - } - } - throw new RuntimeException("No API key authentication configured!"); - } - - /** - * Helper method to set bearer token for the first Bearer authentication. - * - * @param bearerToken Bearer token - */ - public ApiClient setBearerToken(String bearerToken) { - for (Authentication auth : authentications.values()) { - if (auth instanceof HttpBearerAuth) { - ((HttpBearerAuth) auth).setBearerToken(bearerToken); - return this; - } - } - throw new RuntimeException("No Bearer authentication configured!"); - } - - - {{#hasOAuthMethods}} - /** - * Helper method to set access token for the first OAuth2 authentication. - * @param accessToken Access token - */ - public ApiClient setAccessToken(String accessToken) { - for (Authentication auth : authentications.values()) { - if (auth instanceof OAuth) { - ((OAuth) auth).setAccessToken(accessToken); - return this; - } - } - throw new RuntimeException("No OAuth2 authentication configured!"); - } - - /** - * Helper method to set the credentials for the first OAuth2 authentication. - * - * @param clientId the client ID - * @param clientSecret the client secret - */ - public ApiClient setOauthCredentials(String clientId, String clientSecret) { - for (Authentication auth : authentications.values()) { - if (auth instanceof OAuth) { - ((OAuth) auth).setCredentials(clientId, clientSecret); - return this; - } - } - throw new RuntimeException("No OAuth2 authentication configured!"); - } - - /** - * Helper method to set the password flow for the first OAuth2 authentication. - * - * @param username the user name - * @param password the user password - */ - public ApiClient setOauthPasswordFlow(String username, String password) { - for (Authentication auth : authentications.values()) { - if (auth instanceof OAuth) { - ((OAuth) auth).usePasswordFlow(username, password); - return this; - } - } - throw new RuntimeException("No OAuth2 authentication configured!"); - } - - /** - * Helper method to set the authorization code flow for the first OAuth2 authentication. - * - * @param code the authorization code - */ - public ApiClient setOauthAuthorizationCodeFlow(String code) { - for (Authentication auth : authentications.values()) { - if (auth instanceof OAuth) { - ((OAuth) auth).useAuthorizationCodeFlow(code); - return this; - } - } - throw new RuntimeException("No OAuth2 authentication configured!"); - } - - /** - * Helper method to set the scopes for the first OAuth2 authentication. - * - * @param scope the oauth scope - */ - public ApiClient setOauthScope(String scope) { - for (Authentication auth : authentications.values()) { - if (auth instanceof OAuth) { - ((OAuth) auth).setScope(scope); - return this; - } - } - throw new RuntimeException("No OAuth2 authentication configured!"); - } - - {{/hasOAuthMethods}} - /** - * Set the User-Agent header's value (by adding to the default header map). - * @param userAgent Http user agent - * @return API client - */ - public ApiClient setUserAgent(String userAgent) { - addDefaultHeader("User-Agent", userAgent); - return this; - } - - /** - * Add a default header. - * - * @param key The header's key - * @param value The header's value - * @return API client - */ - public ApiClient addDefaultHeader(String key, String value) { - defaultHeaderMap.put(key, value); - return this; - } - - /** - * Add a default cookie. - * - * @param key The cookie's key - * @param value The cookie's value - * @return API client - */ - public ApiClient addDefaultCookie(String key, String value) { - defaultCookieMap.put(key, value); - return this; - } - - /** - * Check that whether debugging is enabled for this API client. - * @return True if debugging is switched on - */ - public boolean isDebugging() { - return debugging; - } - - /** - * Enable/disable debugging for this API client. - * - * @param debugging To enable (true) or disable (false) debugging - * @return API client - */ - public ApiClient setDebugging(boolean debugging) { - this.debugging = debugging; - // Rebuild HTTP Client according to the new "debugging" value. - this.httpClient = buildHttpClient(debugging); - return this; - } - - /** - * The path of temporary folder used to store downloaded files from endpoints - * with file response. The default value is null, i.e. using - * the system's default tempopary folder. - * - * @return Temp folder path - */ - public String getTempFolderPath() { - return tempFolderPath; - } - - /** - * Set temp folder path - * @param tempFolderPath Temp folder path - * @return API client - */ - public ApiClient setTempFolderPath(String tempFolderPath) { - this.tempFolderPath = tempFolderPath; - return this; - } - - /** - * Connect timeout (in milliseconds). - * @return Connection timeout - */ - public int getConnectTimeout() { - return connectionTimeout; - } - - /** - * Set the connect timeout (in milliseconds). - * A value of 0 means no timeout, otherwise values must be between 1 and - * {@link Integer#MAX_VALUE}. - * @param connectionTimeout Connection timeout in milliseconds - * @return API client - */ - public ApiClient setConnectTimeout(int connectionTimeout) { - this.connectionTimeout = connectionTimeout; - httpClient.property(ClientProperties.CONNECT_TIMEOUT, connectionTimeout); - return this; - } - - /** - * read timeout (in milliseconds). - * @return Read timeout - */ - public int getReadTimeout() { - return readTimeout; - } - - /** - * Set the read timeout (in milliseconds). - * A value of 0 means no timeout, otherwise values must be between 1 and - * {@link Integer#MAX_VALUE}. - * @param readTimeout Read timeout in milliseconds - * @return API client - */ - public ApiClient setReadTimeout(int readTimeout) { - this.readTimeout = readTimeout; - httpClient.property(ClientProperties.READ_TIMEOUT, readTimeout); - return this; - } - - /** - * Get the date format used to parse/format date parameters. - * @return Date format - */ - public DateFormat getDateFormat() { - return dateFormat; - } - - /** - * Set the date format used to parse/format date parameters. - * @param dateFormat Date format - * @return API client - */ - public ApiClient setDateFormat(DateFormat dateFormat) { - this.dateFormat = dateFormat; - // also set the date format for model (de)serialization with Date properties - this.json.setDateFormat((DateFormat) dateFormat.clone()); - return this; - } - - /** - * Parse the given string into Date object. - * @param str String - * @return Date - */ - public Date parseDate(String str) { - try { - return dateFormat.parse(str); - } catch (java.text.ParseException e) { - throw new RuntimeException(e); - } - } - - /** - * Format the given Date object into string. - * @param date Date - * @return Date in string format - */ - public String formatDate(Date date) { - return dateFormat.format(date); - } - - /** - * Format the given parameter object into string. - * @param param Object - * @return Object in string format - */ - public String parameterToString(Object param) { - if (param == null) { - return ""; - } else if (param instanceof Date) { - return formatDate((Date) param); - } else if (param instanceof Collection) { - StringBuilder b = new StringBuilder(); - for(Object o : (Collection)param) { - if(b.length() > 0) { - b.append(','); - } - b.append(String.valueOf(o)); - } - return b.toString(); - } else { - return String.valueOf(param); - } - } - - /* - * Format to {@code Pair} objects. - * @param collectionFormat Collection format - * @param name Name - * @param value Value - * @return List of pairs - */ - public List parameterToPairs(String collectionFormat, String name, Object value){ - List params = new ArrayList(); - - // preconditions - if (name == null || name.isEmpty() || value == null) return params; - - Collection valueCollection; - if (value instanceof Collection) { - valueCollection = (Collection) value; - } else { - params.add(new Pair(name, parameterToString(value))); - return params; - } - - if (valueCollection.isEmpty()){ - return params; - } - - // get the collection format (default: csv) - String format = (collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat); - - // create the params based on the collection format - if ("multi".equals(format)) { - for (Object item : valueCollection) { - params.add(new Pair(name, parameterToString(item))); - } - - return params; - } - - String delimiter = ","; - - if ("csv".equals(format)) { - delimiter = ","; - } else if ("ssv".equals(format)) { - delimiter = " "; - } else if ("tsv".equals(format)) { - delimiter = "\t"; - } else if ("pipes".equals(format)) { - delimiter = "|"; - } - - StringBuilder sb = new StringBuilder() ; - for (Object item : valueCollection) { - sb.append(delimiter); - sb.append(parameterToString(item)); - } - - params.add(new Pair(name, sb.substring(1))); - - return params; - } - - /** - * Check if the given MIME is a JSON MIME. - * JSON MIME examples: - * application/json - * application/json; charset=UTF8 - * APPLICATION/JSON - * application/vnd.company+json - * "* / *" is also default to JSON - * @param mime MIME - * @return True if the MIME type is JSON - */ - public boolean isJsonMime(String mime) { - String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$"; - return mime != null && (mime.matches(jsonMime) || mime.equals("*/*")); - } - - /** - * Select the Accept header's value from the given accepts array: - * if JSON exists in the given array, use it; - * otherwise use all of them (joining into a string) - * - * @param accepts The accepts array to select from - * @return The Accept header to use. If the given array is empty, - * null will be returned (not to set the Accept header explicitly). - */ - public String selectHeaderAccept(String[] accepts) { - if (accepts.length == 0) { - return null; - } - for (String accept : accepts) { - if (isJsonMime(accept)) { - return accept; - } - } - return StringUtil.join(accepts, ","); - } - - /** - * Select the Content-Type header's value from the given array: - * if JSON exists in the given array, use it; - * otherwise use the first one of the array. - * - * @param contentTypes The Content-Type array to select from - * @return The Content-Type header to use. If the given array is empty, - * JSON will be used. - */ - public String selectHeaderContentType(String[] contentTypes) { - if (contentTypes.length == 0) { - return "application/json"; - } - for (String contentType : contentTypes) { - if (isJsonMime(contentType)) { - return contentType; - } - } - return contentTypes[0]; - } - - /** - * Escape the given string to be used as URL query value. - * @param str String - * @return Escaped string - */ - public String escapeString(String str) { - try { - return URLEncoder.encode(str, "utf8").replaceAll("\\+", "%20"); - } catch (UnsupportedEncodingException e) { - return str; - } - } - - /** - * Serialize the given Java object into string entity according the given - * Content-Type (only JSON is supported for now). - * @param obj Object - * @param formParams Form parameters - * @param contentType Context type - * @return Entity - * @throws ApiException API exception - */ - public Entity serialize(Object obj, Map formParams, String contentType) throws ApiException { - Entity entity; - if (contentType.startsWith("multipart/form-data")) { - MultiPart multiPart = new MultiPart(); - for (Entry param: formParams.entrySet()) { - if (param.getValue() instanceof File) { - File file = (File) param.getValue(); - FormDataContentDisposition contentDisp = FormDataContentDisposition.name(param.getKey()) - .fileName(file.getName()).size(file.length()).build(); - multiPart.bodyPart(new FormDataBodyPart(contentDisp, file, MediaType.APPLICATION_OCTET_STREAM_TYPE)); - } else { - FormDataContentDisposition contentDisp = FormDataContentDisposition.name(param.getKey()).build(); - multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(param.getValue()))); - } - } - entity = Entity.entity(multiPart, MediaType.MULTIPART_FORM_DATA_TYPE); - } else if (contentType.startsWith("application/x-www-form-urlencoded")) { - Form form = new Form(); - for (Entry param: formParams.entrySet()) { - form.param(param.getKey(), parameterToString(param.getValue())); - } - entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE); - } else { - // We let jersey handle the serialization - entity = Entity.entity(obj == null ? Entity.text("") : obj, contentType); - } - return entity; - } - - /** - * Serialize the given Java object into string according the given - * Content-Type (only JSON, HTTP form is supported for now). - * @param obj Object - * @param formParams Form parameters - * @param contentType Context type - * @return String - * @throws ApiException API exception - */ - public String serializeToString(Object obj, Map formParams, String contentType) throws ApiException { - try { - if (contentType.startsWith("multipart/form-data")) { - throw new ApiException("multipart/form-data not yet supported for serializeToString (http signature authentication)"); - } else if (contentType.startsWith("application/x-www-form-urlencoded")) { - String formString = ""; - for (Entry param : formParams.entrySet()) { - formString = param.getKey() + "=" + URLEncoder.encode(parameterToString(param.getValue()), "UTF-8") + "&"; - } - - if (formString.length() == 0) { // empty string - return formString; - } else { - return formString.substring(0, formString.length() - 1); - } - } else { - return json.getMapper().writeValueAsString(obj); - } - } catch (Exception ex) { - throw new ApiException("Failed to perform serializeToString: " + ex.toString()); - } - } - - public AbstractOpenApiSchema deserializeSchemas(Response response, AbstractOpenApiSchema schema) throws ApiException{ - - Object result = null; - int matchCounter = 0; - ArrayList matchSchemas = new ArrayList<>(); - - for (Map.Entry entry : schema.getSchemas().entrySet()) { - String schemaName = entry.getKey(); - GenericType schemaType = entry.getValue(); - - if (schemaType instanceof GenericType) { // model - try { - Object deserializedObject = deserialize(response, schemaType); - if (deserializedObject != null) { - result = deserializedObject; - matchCounter++; - - if ("anyOf".equals(schema.getSchemaType())) { - break; - } else if ("oneOf".equals(schema.getSchemaType())) { - matchSchemas.add(schemaName); - } else { - throw new ApiException("Unknowe type found while expecting anyOf/oneOf:" + schema.getSchemaType()); - } - } else { - // failed to deserialize the response in the schema provided, proceed to the next one if any - } - } catch (Exception ex) { - // failed to deserialize, do nothing and try next one (schema) - } - } else {// unknown type - throw new ApiException(schemaType.getClass() + " is not a GenericType and cannot be handled properly in deserialization."); - } - - } - - if (matchCounter > 1 && "oneOf".equals(schema.getSchemaType())) {// more than 1 match for oneOf - throw new ApiException("Response body is invalid as it matches more than one schema (" + StringUtil.join(matchSchemas, ", ") + ") defined in the oneOf model: " + schema.getClass().getName()); - } else if (matchCounter == 0) { // fail to match any in oneOf/anyOf schemas - throw new ApiException("Response body is invalid as it doens't match any schemas (" + StringUtil.join(schema.getSchemas().keySet(), ", ") + ") defined in the oneOf/anyOf model: " + schema.getClass().getName()); - } else { // only one matched - schema.setActualInstance(result); - return schema; - } - - } - - - - /** - * Deserialize response body to Java object according to the Content-Type. - * @param Type - * @param response Response - * @param returnType Return type - * @return Deserialize object - * @throws ApiException API exception - */ - @SuppressWarnings("unchecked") - public T deserialize(Response response, GenericType returnType) throws ApiException { - if (response == null || returnType == null) { - return null; - } - - if ("byte[]".equals(returnType.toString())) { - // Handle binary response (byte array). - return (T) response.readEntity(byte[].class); - } else if (returnType.getRawType() == File.class) { - // Handle file downloading. - T file = (T) downloadFileFromResponse(response); - return file; - } - - String contentType = null; - List contentTypes = response.getHeaders().get("Content-Type"); - if (contentTypes != null && !contentTypes.isEmpty()) - contentType = String.valueOf(contentTypes.get(0)); - - // read the entity stream multiple times - response.bufferEntity(); - - return response.readEntity(returnType); - } - - /** - * Download file from the given response. - * @param response Response - * @return File - * @throws ApiException If fail to read file content from response and write to disk - */ - public File downloadFileFromResponse(Response response) throws ApiException { - try { - File file = prepareDownloadFile(response); -{{^supportJava6}} - Files.copy(response.readEntity(InputStream.class), file.toPath(), StandardCopyOption.REPLACE_EXISTING); -{{/supportJava6}} -{{#supportJava6}} - // Java6 falls back to commons.io for file copying - FileUtils.copyToFile(response.readEntity(InputStream.class), file); -{{/supportJava6}} - return file; - } catch (IOException e) { - throw new ApiException(e); - } - } - - public File prepareDownloadFile(Response response) throws IOException { - String filename = null; - String contentDisposition = (String) response.getHeaders().getFirst("Content-Disposition"); - if (contentDisposition != null && !"".equals(contentDisposition)) { - // Get filename from the Content-Disposition header. - Pattern pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?"); - Matcher matcher = pattern.matcher(contentDisposition); - if (matcher.find()) - filename = matcher.group(1); - } - - String prefix; - String suffix = null; - if (filename == null) { - prefix = "download-"; - suffix = ""; - } else { - int pos = filename.lastIndexOf('.'); - if (pos == -1) { - prefix = filename + "-"; - } else { - prefix = filename.substring(0, pos) + "-"; - suffix = filename.substring(pos); - } - // File.createTempFile requires the prefix to be at least three characters long - if (prefix.length() < 3) - prefix = "download-"; - } - - if (tempFolderPath == null) - return File.createTempFile(prefix, suffix); - else - return File.createTempFile(prefix, suffix, new File(tempFolderPath)); - } - - /** - * Invoke API by sending HTTP request with the given options. - * - * @param Type - * @param operation The qualified name of the operation - * @param path The sub-path of the HTTP URL - * @param method The request method, one of "GET", "POST", "PUT", "HEAD" and "DELETE" - * @param queryParams The query parameters - * @param body The request body object - * @param headerParams The header parameters - * @param cookieParams The cookie parameters - * @param formParams The form parameters - * @param accept The request's Accept header - * @param contentType The request's Content-Type header - * @param authNames The authentications to apply - * @param returnType The return type into which to deserialize the response - * @param schema An instance of the response that uses oneOf/anyOf - * @return The response body in type of string - * @throws ApiException API exception - */ - public ApiResponse invokeAPI( - String operation, - String path, - String method, - List queryParams, - Object body, - Map headerParams, - Map cookieParams, - Map formParams, - String accept, - String contentType, - String[] authNames, - GenericType returnType, - AbstractOpenApiSchema schema) - throws ApiException { - - // Not using `.target(targetURL).path(path)` below, - // to support (constant) query string in `path`, e.g. "/posts?draft=1" - String targetURL; - if (operationServers.containsKey(operation)) { - Integer index = operationServerIndex.containsKey(operation) ? operationServerIndex.get(operation) : serverIndex; - Map variables = operationServerVariables.containsKey(operation) ? - operationServerVariables.get(operation) : serverVariables; - List serverConfigurations = operationServers.get(operation); - if (index < 0 || index >= serverConfigurations.size()) { - throw new ArrayIndexOutOfBoundsException( - String.format( - "Invalid index %d when selecting the host settings. Must be less than %d", - index, serverConfigurations.size())); - } - targetURL = serverConfigurations.get(index).URL(variables) + path; - } else { - targetURL = this.basePath + path; - } - WebTarget target = httpClient.target(targetURL); - - if (queryParams != null) { - for (Pair queryParam : queryParams) { - if (queryParam.getValue() != null) { - target = target.queryParam(queryParam.getName(), escapeString(queryParam.getValue())); - } - } - } - - Invocation.Builder invocationBuilder = target.request().accept(accept); - - for (Entry entry : cookieParams.entrySet()) { - String value = entry.getValue(); - if (value != null) { - invocationBuilder = invocationBuilder.cookie(entry.getKey(), value); - } - } - - for (Entry entry : defaultCookieMap.entrySet()) { - String value = entry.getValue(); - if (value != null) { - invocationBuilder = invocationBuilder.cookie(entry.getKey(), value); - } - } - - Entity entity = serialize(body, formParams, contentType); - - // put all headers in one place - Map allHeaderParams = new HashMap<>(defaultHeaderMap); - allHeaderParams.putAll(headerParams); - - // update different parameters (e.g. headers) for authentication - updateParamsForAuth( - authNames, - queryParams, - allHeaderParams, - cookieParams, - serializeToString(body, formParams, contentType), - method, - target.getUri()); - - for (Entry entry : allHeaderParams.entrySet()) { - String value = entry.getValue(); - if (value != null) { - invocationBuilder = invocationBuilder.header(entry.getKey(), value); - } - } - - Response response = null; - - try { - response = sendRequest(method, invocationBuilder, entity); - - // If OAuth is used and a status 401 is received, renew the access token and retry the request - if (response.getStatusInfo() == Status.UNAUTHORIZED) { - for (String authName : authNames) { - Authentication authentication = authentications.get(authName); - if (authentication instanceof OAuth) { - OAuth2AccessToken accessToken = ((OAuth) authentication).renewAccessToken(); - if (accessToken != null) { - invocationBuilder.header("Authorization", null); - invocationBuilder.header("Authorization", "Bearer " + accessToken.getAccessToken()); - response = sendRequest(method, invocationBuilder, entity); - } - break; - } - } - } - - int statusCode = response.getStatusInfo().getStatusCode(); - Map> responseHeaders = buildResponseHeaders(response); - - if (response.getStatusInfo() == Status.NO_CONTENT) { - return new ApiResponse(statusCode, responseHeaders); - } else if (response.getStatusInfo().getFamily() == Status.Family.SUCCESSFUL) { - if (returnType == null) return new ApiResponse(statusCode, responseHeaders); - else if (schema == null) { - return new ApiResponse(statusCode, responseHeaders, deserialize(response, returnType)); - } else { // oneOf/anyOf - return new ApiResponse( - statusCode, responseHeaders, (T) deserializeSchemas(response, schema)); - } - } else { - String message = "error"; - String respBody = null; - if (response.hasEntity()) { - try { - respBody = String.valueOf(response.readEntity(String.class)); - message = respBody; - } catch (RuntimeException e) { - // e.printStackTrace(); - } - } - throw new ApiException( - response.getStatus(), message, buildResponseHeaders(response), respBody); - } - } finally { - try { - response.close(); - } catch (Exception e) { - // it's not critical, since the response object is local in method invokeAPI; that's fine, - // just continue - } - } - } - - private Response sendRequest(String method, Invocation.Builder invocationBuilder, Entity entity) { - Response response; - if ("POST".equals(method)) { - response = invocationBuilder.post(entity); - } else if ("PUT".equals(method)) { - response = invocationBuilder.put(entity); - } else if ("DELETE".equals(method)) { - response = invocationBuilder.method("DELETE", entity); - } else if ("PATCH".equals(method)) { - response = invocationBuilder.method("PATCH", entity); - } else { - response = invocationBuilder.method(method); - } - return response; - } - - /** - * @deprecated Add qualified name of the operation as a first parameter. - */ - @Deprecated - public ApiResponse invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType, AbstractOpenApiSchema schema) throws ApiException { - return invokeAPI(null, path, method, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType, schema); - } - - /** - * Build the Client used to make HTTP requests. - * @param debugging Debug setting - * @return Client - */ - protected Client buildHttpClient(boolean debugging) { - final ClientConfig clientConfig = new ClientConfig(); - clientConfig.register(MultiPartFeature.class); - clientConfig.register(json); - clientConfig.register(JacksonFeature.class); - clientConfig.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true); - // turn off compliance validation to be able to send payloads with DELETE calls - clientConfig.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true); - if (debugging) { -{{^supportJava6}} - clientConfig.register(new LoggingFeature(java.util.logging.Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME), java.util.logging.Level.INFO, LoggingFeature.Verbosity.PAYLOAD_ANY, 1024*50 /* Log payloads up to 50K */)); - clientConfig.property(LoggingFeature.LOGGING_FEATURE_VERBOSITY, LoggingFeature.Verbosity.PAYLOAD_ANY); - // Set logger to ALL - java.util.logging.Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME).setLevel(java.util.logging.Level.ALL); -{{/supportJava6}} -{{#supportJava6}} - clientConfig.register(new LoggingFilter(java.util.logging.Logger.getLogger(LoggingFilter.class.getName()), true)); -{{/supportJava6}} - } else { - // suppress warnings for payloads with DELETE calls: - java.util.logging.Logger.getLogger("org.glassfish.jersey.client").setLevel(java.util.logging.Level.SEVERE); - } - performAdditionalClientConfiguration(clientConfig); - return ClientBuilder.newClient(clientConfig); - } - - protected void performAdditionalClientConfiguration(ClientConfig clientConfig) { - // No-op extension point - } - - protected Map> buildResponseHeaders(Response response) { - Map> responseHeaders = new HashMap>(); - for (Entry> entry: response.getHeaders().entrySet()) { - List values = entry.getValue(); - List headers = new ArrayList(); - for (Object o : values) { - headers.add(String.valueOf(o)); - } - responseHeaders.put(entry.getKey(), headers); - } - return responseHeaders; - } - - /** - * Update query and header parameters based on authentication settings. - * - * @param authNames The authentications to apply - * @param queryParams List of query parameters - * @param headerParams Map of header parameters - * @param cookieParams Map of cookie parameters - * @param method HTTP method (e.g. POST) - * @param uri HTTP URI - */ - protected void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams, - Map cookieParams, String payload, String method, URI uri) throws ApiException { - for (String authName : authNames) { - Authentication auth = authentications.get(authName); - if (auth == null) { - throw new RuntimeException("Authentication undefined: " + authName); - } - auth.applyToParams(queryParams, headerParams, cookieParams, payload, method, uri); - } - } -} diff --git a/libraries/jersey2-experimental/ApiResponse.mustache b/libraries/jersey2-experimental/ApiResponse.mustache deleted file mode 100644 index 5dae9dc1fdf..00000000000 --- a/libraries/jersey2-experimental/ApiResponse.mustache +++ /dev/null @@ -1,73 +0,0 @@ -{{>licenseInfo}} - -package {{invokerPackage}}; - -import java.util.List; -import java.util.Map; -{{#caseInsensitiveResponseHeaders}} -import java.util.Map.Entry; -import java.util.TreeMap; -{{/caseInsensitiveResponseHeaders}} - -/** - * API response returned by API call. - * - * @param The type of data that is deserialized from response body - */ -public class ApiResponse { - private final int statusCode; - private final Map> headers; - private final T data; - - /** - * @param statusCode The status code of HTTP response - * @param headers The headers of HTTP response - */ - public ApiResponse(int statusCode, Map> headers) { - this(statusCode, headers, null); - } - - /** - * @param statusCode The status code of HTTP response - * @param headers The headers of HTTP response - * @param data The object deserialized from response bod - */ - public ApiResponse(int statusCode, Map> headers, T data) { - this.statusCode = statusCode; - {{#caseInsensitiveResponseHeaders}} - Map> responseHeaders = new TreeMap>(String.CASE_INSENSITIVE_ORDER); - for(Entry> entry : headers.entrySet()){ - responseHeaders.put(entry.getKey().toLowerCase(), entry.getValue()); - } - {{/caseInsensitiveResponseHeaders}} - this.headers = {{#caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}; - this.data = data; - } - - /** - * Get the status code - * - * @return status code - */ - public int getStatusCode() { - return statusCode; - } - - /** - * Get the headers - * - * @return map of headers - */ - public Map> getHeaders() { - return headers; - } - - /** - * Get the data - * - * @return data - */ - public T getData() { - return data; - } -} diff --git a/libraries/jersey2-experimental/JSON.mustache b/libraries/jersey2-experimental/JSON.mustache deleted file mode 100644 index dc3d9893e6d..00000000000 --- a/libraries/jersey2-experimental/JSON.mustache +++ /dev/null @@ -1,72 +0,0 @@ -package {{invokerPackage}}; - -{{#threetenbp}} -import org.threeten.bp.*; -{{/threetenbp}} -import com.fasterxml.jackson.annotation.*; -import com.fasterxml.jackson.databind.*; -import org.openapitools.jackson.nullable.JsonNullableModule; -{{#java8}} -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -{{/java8}} -{{#joda}} -import com.fasterxml.jackson.datatype.joda.JodaModule; -{{/joda}} -{{#threetenbp}} -import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; -{{/threetenbp}} - -import java.text.DateFormat; - -import javax.ws.rs.ext.ContextResolver; - -{{>generatedAnnotation}} -public class JSON implements ContextResolver { - private ObjectMapper mapper; - - public JSON() { - mapper = new ObjectMapper(); - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); - mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true); - mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); - mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); - mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); - mapper.setDateFormat(new RFC3339DateFormat()); - {{#java8}} - mapper.registerModule(new JavaTimeModule()); - {{/java8}} - {{#joda}} - mapper.registerModule(new JodaModule()); - {{/joda}} - {{#threetenbp}} - ThreeTenModule module = new ThreeTenModule(); - module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); - module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); - module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); - mapper.registerModule(module); - {{/threetenbp}} - JsonNullableModule jnm = new JsonNullableModule(); - mapper.registerModule(jnm); - } - - /** - * Set the date format for JSON (de)serialization with Date properties. - * @param dateFormat Date format - */ - public void setDateFormat(DateFormat dateFormat) { - mapper.setDateFormat(dateFormat); - } - - @Override - public ObjectMapper getContext(Class type) { - return mapper; - } - - /** - * Get the object mapper - * - * @return object mapper - */ - public ObjectMapper getMapper() { return mapper; } -} diff --git a/libraries/jersey2-experimental/api.mustache b/libraries/jersey2-experimental/api.mustache deleted file mode 100644 index 509ae48a50e..00000000000 --- a/libraries/jersey2-experimental/api.mustache +++ /dev/null @@ -1,262 +0,0 @@ -package {{package}}; - -import {{invokerPackage}}.ApiException; -import {{invokerPackage}}.ApiClient; -import {{invokerPackage}}.ApiResponse; -import {{invokerPackage}}.Configuration; -import {{invokerPackage}}.Pair; - -import javax.ws.rs.core.GenericType; - -{{#imports}}import {{import}}; -{{/imports}} - -{{^fullJavaUtil}} -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -{{/fullJavaUtil}} -{{>generatedAnnotation}} -{{#operations}} -public class {{classname}} { - private ApiClient apiClient; - - public {{classname}}() { - this(Configuration.getDefaultApiClient()); - } - - public {{classname}}(ApiClient apiClient) { - this.apiClient = apiClient; - } - - /** - * Get the API cilent - * - * @return API client - */ - public ApiClient getApiClient() { - return apiClient; - } - - /** - * Set the API cilent - * - * @param apiClient an instance of API client - */ - public void setApiClient(ApiClient apiClient) { - this.apiClient = apiClient; - } - - {{#operation}} - {{^vendorExtensions.x-group-parameters}} - /** - * {{summary}} - * {{notes}} - {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} - {{/allParams}} - {{#returnType}} - * @return {{returnType}} - {{/returnType}} - * @throws ApiException if fails to make API call - {{#responses.0}} - * @http.response.details - - - {{#responses}} - - {{/responses}} -
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
- {{/responses.0}} - {{#isDeprecated}} - * @deprecated - {{/isDeprecated}} - {{#externalDocs}} - * {{description}} - * @see {{summary}} Documentation - {{/externalDocs}} - */ - {{#isDeprecated}} - @Deprecated - {{/isDeprecated}} - public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { - {{#returnType}}return {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#returnType}}.getData(){{/returnType}}; - } - {{/vendorExtensions.x-group-parameters}} - - {{^vendorExtensions.x-group-parameters}} - /** - * {{summary}} - * {{notes}} - {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} - {{/allParams}} - * @return ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> - * @throws ApiException if fails to make API call - {{#responses.0}} - * @http.response.details - - - {{#responses}} - - {{/responses}} -
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
- {{/responses.0}} - {{#isDeprecated}} - * @deprecated - {{/isDeprecated}} - {{#externalDocs}} - * {{description}} - * @see {{summary}} Documentation - {{/externalDocs}} - */ - {{#isDeprecated}} - @Deprecated - {{/isDeprecated}} - public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { - Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; - {{#allParams}}{{#required}} - // verify the required parameter '{{paramName}}' is set - if ({{paramName}} == null) { - throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); - } - {{/required}}{{/allParams}} - // create path and map variables - String localVarPath = "{{{path}}}"{{#pathParams}} - .replaceAll("\\{" + "{{baseName}}" + "\\}", apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; - - // query params - {{javaUtilPrefix}}List localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); - {{javaUtilPrefix}}Map localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); - {{javaUtilPrefix}}Map localVarCookieParams = new {{javaUtilPrefix}}HashMap(); - {{javaUtilPrefix}}Map localVarFormParams = new {{javaUtilPrefix}}HashMap(); - - {{#queryParams}} - localVarQueryParams.addAll(apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); - {{/queryParams}} - - {{#headerParams}}if ({{paramName}} != null) - localVarHeaderParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); - {{/headerParams}} - - {{#cookieParams}}if ({{paramName}} != null) - localVarCookieParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); - {{/cookieParams}} - - {{#formParams}}if ({{paramName}} != null) - localVarFormParams.put("{{baseName}}", {{paramName}}); - {{/formParams}} - - final String[] localVarAccepts = { - {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} - }; - final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); - - final String[] localVarContentTypes = { - {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} - }; - final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); - - String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; - - {{#returnType}} - GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {}; - - {{/returnType}} - return apiClient.invokeAPI("{{classname}}.{{operationId}}", localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, - localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, - localVarAuthNames, {{#returnType}}localVarReturnType{{/returnType}}{{^returnType}}null{{/returnType}}, {{#vendorExtensions.x-java-return-type-one-of}}new {{{returnType}}}(){{/vendorExtensions.x-java-return-type-one-of}}{{^vendorExtensions.x-java-return-type-one-of}}{{#vendorExtensions.x-java-return-type-any-of}}new {{{returnType}}}(){{/vendorExtensions.x-java-return-type-any-of}}{{^vendorExtensions.x-java-return-type-any-of}}null{{/vendorExtensions.x-java-return-type-any-of}}{{/vendorExtensions.x-java-return-type-one-of}}); - } - {{#vendorExtensions.x-group-parameters}} - - public class API{{operationId}}Request { - {{#allParams}} - private {{#isRequired}}final {{/isRequired}}{{{dataType}}} {{localVariablePrefix}}{{paramName}}; - {{/allParams}} - - private API{{operationId}}Request({{#pathParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}) { - {{#pathParams}} - this.{{localVariablePrefix}}{{paramName}} = {{paramName}}; - {{/pathParams}} - } - {{#allParams}} - {{^isPathParam}} - - /** - * Set {{paramName}} - * @param {{paramName}} {{description}} ({{^required}}optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}{{/required}}{{#required}}required{{/required}}) - * @return API{{operationId}}Request - */ - public API{{operationId}}Request {{paramName}}({{{dataType}}} {{paramName}}) { - this.{{localVariablePrefix}}{{paramName}} = {{paramName}}; - return this; - } - {{/isPathParam}} - {{/allParams}} - - /** - * Execute {{operationId}} request - {{#returnType}}* @return {{.}}{{/returnType}} - * @throws ApiException if fails to make API call - {{#responses.0}} - * @http.response.details - - - {{#responses}} - - {{/responses}} -
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
- {{/responses.0}} - {{#isDeprecated}}* @deprecated{{/isDeprecated}} - */ - {{#isDeprecated}}@Deprecated{{/isDeprecated}} - public {{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}void{{/returnType}} execute() throws ApiException { - {{#returnType}}return {{/returnType}}this.executeWithHttpInfo().getData(); - } - - /** - * Execute {{operationId}} request with HTTP info returned - * @return ApiResponse<{{#returnType}}{{.}}{{/returnType}}{{^returnType}}Void{{/returnType}}> - * @throws ApiException if fails to make API call - {{#responses.0}} - * @http.response.details - - - {{#responses}} - - {{/responses}} -
Status Code Description Response Headers
{{code}} {{message}} {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}}
- {{/responses.0}} - {{#isDeprecated}} - * @deprecated{{/isDeprecated}} - */ - {{#isDeprecated}} - @Deprecated - {{/isDeprecated}} - public ApiResponse<{{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> executeWithHttpInfo() throws ApiException { - return {{operationId}}WithHttpInfo({{#allParams}}{{localVariablePrefix}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); - } - } - - /** - * {{summary}} - * {{notes}}{{#pathParams}} - * @param {{paramName}} {{description}} (required){{/pathParams}} - * @return {{operationId}}Request - * @throws ApiException if fails to make API call - {{#isDeprecated}}* @deprecated{{/isDeprecated}} - {{#externalDocs}}* {{description}} - * @see {{summary}} Documentation{{/externalDocs}} - */ - {{#isDeprecated}} - @Deprecated - {{/isDeprecated}} - public API{{operationId}}Request {{operationId}}({{#pathParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}) throws ApiException { - return new API{{operationId}}Request({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}); - } - {{/vendorExtensions.x-group-parameters}} - {{/operation}} -} -{{/operations}} diff --git a/libraries/jersey2-experimental/apiException.mustache b/libraries/jersey2-experimental/apiException.mustache deleted file mode 100644 index f0079c7bbec..00000000000 --- a/libraries/jersey2-experimental/apiException.mustache +++ /dev/null @@ -1,99 +0,0 @@ -{{>licenseInfo}} - -package {{invokerPackage}}; - -import java.util.Map; -import java.util.List; -{{#caseInsensitiveResponseHeaders}} -import java.util.Map.Entry; -import java.util.TreeMap; -{{/caseInsensitiveResponseHeaders}} - -/** - * API Exception - */ -{{>generatedAnnotation}} -public class ApiException extends{{#useRuntimeException}} RuntimeException {{/useRuntimeException}}{{^useRuntimeException}} Exception {{/useRuntimeException}}{ - private int code = 0; - private Map> responseHeaders = null; - private String responseBody = null; - - public ApiException() {} - - public ApiException(Throwable throwable) { - super(throwable); - } - - public ApiException(String message) { - super(message); - } - - public ApiException(String message, Throwable throwable, int code, Map> responseHeaders, String responseBody) { - super(message, throwable); - this.code = code; - {{#caseInsensitiveResponseHeaders}} - Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER); - for(Entry> entry : responseHeaders.entrySet()){ - headers.put(entry.getKey().toLowerCase(), entry.getValue()); - } - {{/caseInsensitiveResponseHeaders}} - this.responseHeaders = {{#caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}; - this.responseBody = responseBody; - } - - public ApiException(String message, int code, Map> responseHeaders, String responseBody) { - this(message, (Throwable) null, code, responseHeaders, responseBody); - } - - public ApiException(String message, Throwable throwable, int code, Map> responseHeaders) { - this(message, throwable, code, responseHeaders, null); - } - - public ApiException(int code, Map> responseHeaders, String responseBody) { - this((String) null, (Throwable) null, code, responseHeaders, responseBody); - } - - public ApiException(int code, String message) { - super(message); - this.code = code; - } - - public ApiException(int code, String message, Map> responseHeaders, String responseBody) { - this(code, message); - {{#caseInsensitiveResponseHeaders}} - Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER); - for(Entry> entry : responseHeaders.entrySet()){ - headers.put(entry.getKey().toLowerCase(), entry.getValue()); - } - {{/caseInsensitiveResponseHeaders}} - this.responseHeaders = {{#caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}; - this.responseBody = responseBody; - } - - /** - * Get the HTTP status code. - * - * @return HTTP status code - */ - public int getCode() { - return code; - } - - /** - * Get the HTTP response headers. - * - * @return A map of list of string - */ - public Map> getResponseHeaders() { - return responseHeaders; - } - - /** - * Get the HTTP response body. - * - * @return Response body in the form of string - */ - public String getResponseBody() { - return responseBody; - } -} diff --git a/libraries/jersey2-experimental/api_doc.mustache b/libraries/jersey2-experimental/api_doc.mustache deleted file mode 100644 index f162d1cc974..00000000000 --- a/libraries/jersey2-experimental/api_doc.mustache +++ /dev/null @@ -1,121 +0,0 @@ -# {{classname}}{{#description}} - -{{description}}{{/description}} - -All URIs are relative to *{{basePath}}* - -Method | HTTP request | Description -------------- | ------------- | ------------- -{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} -{{/operation}}{{/operations}} - -{{#operations}} -{{#operation}} - -## {{operationId}} - -{{^vendorExtensions.x-group-parameters}} -> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) -{{/vendorExtensions.x-group-parameters}} -{{#vendorExtensions.x-group-parameters}} -> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}){{#allParams}}{{^isPathParam}}.{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}}.execute(); -{{/vendorExtensions.x-group-parameters}} - -{{summary}}{{#notes}} - -{{{unescapedNotes}}}{{/notes}} - -### Example - -```java -// Import classes: -import {{{invokerPackage}}}.ApiClient; -import {{{invokerPackage}}}.ApiException; -import {{{invokerPackage}}}.Configuration;{{#hasAuthMethods}} -import {{{invokerPackage}}}.auth.*;{{/hasAuthMethods}} -import {{{invokerPackage}}}.models.*; -import {{{package}}}.{{{classname}}}; - -public class Example { - public static void main(String[] args) { - ApiClient defaultClient = Configuration.getDefaultApiClient(); - defaultClient.setBasePath("{{{basePath}}}"); - {{#hasAuthMethods}} - {{#authMethods}}{{#isBasic}}{{#isBasicBasic}} - // Configure HTTP basic authorization: {{{name}}} - HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); - {{{name}}}.setUsername("YOUR USERNAME"); - {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasicBasic}}{{#isBasicBearer}} - // Configure HTTP bearer authorization: {{{name}}} - HttpBearerAuth {{{name}}} = (HttpBearerAuth) defaultClient.getAuthentication("{{{name}}}"); - {{{name}}}.setBearerToken("BEARER TOKEN");{{/isBasicBearer}}{{/isBasic}}{{#isApiKey}} - // Configure API key authorization: {{{name}}} - ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); - {{{name}}}.setApiKey("YOUR API KEY"); - // Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null) - //{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} - // Configure OAuth2 access token for authorization: {{{name}}} - OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); - {{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}} - {{/authMethods}} - {{/hasAuthMethods}} - - {{{classname}}} apiInstance = new {{{classname}}}(defaultClient); - {{#allParams}} - {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} - {{/allParams}} - try { - {{^vendorExtensions.x-group-parameters}} - {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); - {{/vendorExtensions.x-group-parameters}} - {{#vendorExtensions.x-group-parameters}} - {{#returnType}}{{{returnType}}} result = {{/returnType}}api.{{operationId}}({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}){{#allParams}}{{^isPathParam}} - .{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}} - .execute(); - {{/vendorExtensions.x-group-parameters}} - {{#returnType}} - System.out.println(result); - {{/returnType}} - } catch (ApiException e) { - System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); - System.err.println("Status code: " + e.getCode()); - System.err.println("Reason: " + e.getResponseBody()); - System.err.println("Response headers: " + e.getResponseHeaders()); - e.printStackTrace(); - } - } -} -``` - -### Parameters - -{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} -Name | Type | Description | Notes -------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} -{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{^isContainer}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} -{{/allParams}} - -### Return type - -{{#returnType}}{{#returnTypeIsPrimitive}}**{{returnType}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{returnType}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}null (empty response body){{/returnType}} - -### Authorization - -{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{name}}](../README.md#{{name}}){{^-last}}, {{/-last}}{{/authMethods}} - -### HTTP request headers - -- **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} -- **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} - -{{#responses.0}} -### HTTP response details -| Status code | Description | Response headers | -|-------------|-------------|------------------| -{{#responses}} -| **{{code}}** | {{message}} | {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}} | -{{/responses}} -{{/responses.0}} - -{{/operation}} -{{/operations}} diff --git a/libraries/jersey2-experimental/api_test.mustache b/libraries/jersey2-experimental/api_test.mustache deleted file mode 100644 index 5ee6e494084..00000000000 --- a/libraries/jersey2-experimental/api_test.mustache +++ /dev/null @@ -1,51 +0,0 @@ -{{>licenseInfo}} - -package {{package}}; - -import {{invokerPackage}}.ApiException; -{{#imports}}import {{import}}; -{{/imports}} -import org.junit.Test; -import org.junit.Ignore; -import org.junit.Assert; - -{{^fullJavaUtil}} -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -{{/fullJavaUtil}} - -/** - * API tests for {{classname}} - */ -public class {{classname}}Test { - - private final {{classname}} api = new {{classname}}(); - - {{#operations}}{{#operation}} - /** - * {{summary}} - * - * {{notes}} - * - * @throws ApiException - * if the Api call fails - */ - @Test - public void {{operationId}}Test() throws ApiException { - {{#allParams}} - //{{{dataType}}} {{paramName}} = null; - {{/allParams}} - {{^vendorExtensions.x-group-parameters}} - //{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); - {{/vendorExtensions.x-group-parameters}} - {{#vendorExtensions.x-group-parameters}} - //{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}){{#allParams}}{{^isPathParam}} - // .{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}} - // .execute(); - {{/vendorExtensions.x-group-parameters}} - // TODO: test validations - } - {{/operation}}{{/operations}} -} diff --git a/libraries/jersey2-experimental/build.gradle.mustache b/libraries/jersey2-experimental/build.gradle.mustache deleted file mode 100644 index cdb451adb34..00000000000 --- a/libraries/jersey2-experimental/build.gradle.mustache +++ /dev/null @@ -1,170 +0,0 @@ -apply plugin: 'idea' -apply plugin: 'eclipse' - -group = '{{groupId}}' -version = '{{artifactVersion}}' - -buildscript { - repositories { - maven { url "https://repo1.maven.org/maven2" } - jcenter() - } - dependencies { - classpath 'com.android.tools.build:gradle:2.3.+' - classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' - } -} - -repositories { - jcenter() -} - - -if(hasProperty('target') && target == 'android') { - - apply plugin: 'com.android.library' - apply plugin: 'com.github.dcendents.android-maven' - - android { - compileSdkVersion 25 - buildToolsVersion '25.0.2' - defaultConfig { - minSdkVersion 14 - targetSdkVersion 25 - } - compileOptions { - {{#supportJava6}} - sourceCompatibility JavaVersion.VERSION_1_6 - targetCompatibility JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - {{/java8}} - {{^java8}} - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - {{/java8}} - {{/supportJava6}} - } - - // Rename the aar correctly - libraryVariants.all { variant -> - variant.outputs.each { output -> - def outputFile = output.outputFile - if (outputFile != null && outputFile.name.endsWith('.aar')) { - def fileName = "${project.name}-${variant.baseName}-${version}.aar" - output.outputFile = new File(outputFile.parent, fileName) - } - } - } - - dependencies { - provided 'javax.annotation:jsr250-api:1.0' - } - } - - afterEvaluate { - android.libraryVariants.all { variant -> - def task = project.tasks.create "jar${variant.name.capitalize()}", Jar - task.description = "Create jar artifact for ${variant.name}" - task.dependsOn variant.javaCompile - task.from variant.javaCompile.destinationDir - task.destinationDir = project.file("${project.buildDir}/outputs/jar") - task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" - artifacts.add('archives', task); - } - } - - task sourcesJar(type: Jar) { - from android.sourceSets.main.java.srcDirs - classifier = 'sources' - } - - artifacts { - archives sourcesJar - } - -} else { - - apply plugin: 'java' - apply plugin: 'maven' - {{#supportJava6}} - sourceCompatibility = JavaVersion.VERSION_1_6 - targetCompatibility = JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - {{/java8}} - {{^java8}} - sourceCompatibility = JavaVersion.VERSION_1_7 - targetCompatibility = JavaVersion.VERSION_1_7 - {{/java8}} - {{/supportJava6}} - - install { - repositories.mavenInstaller { - pom.artifactId = '{{artifactId}}' - } - } - - task execute(type:JavaExec) { - main = System.getProperty('mainClass') - classpath = sourceSets.main.runtimeClasspath - } -} - -ext { - swagger_annotations_version = "1.5.22" - jackson_version = "2.10.3" - jackson_databind_version = "2.10.3" - jackson_databind_nullable_version = "0.2.1" - {{#supportJava6}} - jersey_version = "2.6" - commons_io_version=2.5 - commons_lang3_version=3.6 - {{/supportJava6}} - {{^supportJava6}} - jersey_version = "2.27" - {{/supportJava6}} - junit_version = "4.13" - {{#threetenbp}} - threetenbp_version = "2.9.10" - {{/threetenbp}} -} - -dependencies { - compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "com.google.code.findbugs:jsr305:3.0.2" - compile "org.glassfish.jersey.core:jersey-client:$jersey_version" - compile "org.glassfish.jersey.media:jersey-media-multipart:$jersey_version" - compile "org.glassfish.jersey.media:jersey-media-json-jackson:$jersey_version" - compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" - compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" - {{#joda}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" - {{/joda}} - {{#java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" - {{/java8}} - {{#supportJava6}} - compile "commons-io:commons-io:$commons_io_version" - compile "org.apache.commons:commons-lang3:$commons_lang3_version" - {{/supportJava6}} - {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$threetenbp_version" - {{/threetenbp}} - {{^java8}} - compile "com.brsanthu:migbase64:2.2" - {{/java8}} - testCompile "junit:junit:$junit_version" -} - -javadoc { - options.tags = [ "http.response.details:a:Http Response Details" ] -} diff --git a/libraries/jersey2-experimental/build.sbt.mustache b/libraries/jersey2-experimental/build.sbt.mustache deleted file mode 100644 index abb91ecdc99..00000000000 --- a/libraries/jersey2-experimental/build.sbt.mustache +++ /dev/null @@ -1,38 +0,0 @@ -lazy val root = (project in file(".")). - settings( - organization := "{{groupId}}", - name := "{{artifactId}}", - version := "{{artifactVersion}}", - scalaVersion := "2.11.4", - scalacOptions ++= Seq("-feature"), - javacOptions in compile ++= Seq("-Xlint:deprecation"), - publishArtifact in (Compile, packageDoc) := false, - resolvers += Resolver.mavenLocal, - libraryDependencies ++= Seq( - "io.swagger" % "swagger-annotations" % "1.5.22", - "org.glassfish.jersey.core" % "jersey-client" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, - "org.glassfish.jersey.media" % "jersey-media-multipart" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, - "org.glassfish.jersey.media" % "jersey-media-json-jackson" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", - {{#joda}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.10" % "compile", - {{/joda}} - {{#java8}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.10" % "compile", - {{/java8}} - {{#threetenbp}} - "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", - {{/threetenbp}} - {{^java8}} - "com.brsanthu" % "migbase64" % "2.2", - {{/java8}} - {{#supportJava6}} - "org.apache.commons" % "commons-lang3" % "3.6", - "commons-io" % "commons-io" % "2.5", - {{/supportJava6}} - "junit" % "junit" % "4.13" % "test", - "com.novocode" % "junit-interface" % "0.10" % "test" - ) - ) diff --git a/libraries/jersey2-experimental/pom.mustache b/libraries/jersey2-experimental/pom.mustache deleted file mode 100644 index ce5855067d5..00000000000 --- a/libraries/jersey2-experimental/pom.mustache +++ /dev/null @@ -1,390 +0,0 @@ - - 4.0.0 - {{groupId}} - {{artifactId}} - jar - {{artifactId}} - {{artifactVersion}} - {{artifactUrl}} - {{artifactDescription}} - - {{scmConnection}} - {{scmDeveloperConnection}} - {{scmUrl}} - -{{#parentOverridden}} - - {{{parentGroupId}}} - {{{parentArtifactId}}} - {{{parentVersion}}} - -{{/parentOverridden}} - - - - {{licenseName}} - {{licenseUrl}} - repo - - - - - - {{developerName}} - {{developerEmail}} - {{developerOrganization}} - {{developerOrganizationUrl}} - - - - - - - org.apache.maven.plugins - maven-enforcer-plugin - 3.0.0-M1 - - - enforce-maven - - enforce - - - - - 2.2.0 - - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 3.0.0-M4 - - - - loggerPath - conf/log4j.properties - - - -Xms512m -Xmx1500m - methods - 10 - - - - maven-dependency-plugin - - - package - - copy-dependencies - - - ${project.build.directory}/lib - - - - - - - - org.apache.maven.plugins - maven-jar-plugin - 2.6 - - - - jar - test-jar - - - - - - - - - org.codehaus.mojo - build-helper-maven-plugin - 1.10 - - - add_sources - generate-sources - - add-source - - - - src/main/java - - - - - add_test_sources - generate-test-sources - - add-test-source - - - - src/test/java - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - {{#supportJava6}} - 1.6 - 1.6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} - 1.8 - 1.8 - {{/java8}} - {{^java8}} - 1.7 - 1.7 - {{/java8}} - {{/supportJava6}} - true - 128m - 512m - - -Xlint:all - -J-Xss4m - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 3.1.1 - - - attach-javadocs - - jar - - - - - none - - - http.response.details - a - Http Response Details: - - - - - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - - attach-sources - - jar-no-fork - - - - - - - - - - sign-artifacts - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.5 - - - sign-artifacts - verify - - sign - - - - - - - - - - - - io.swagger - swagger-annotations - ${swagger-annotations-version} - - - - - com.google.code.findbugs - jsr305 - 3.0.2 - - - - - org.glassfish.jersey.core - jersey-client - ${jersey-version} - - {{^supportJava6}} - - org.glassfish.jersey.inject - jersey-hk2 - ${jersey-version} - - {{/supportJava6}} - - org.glassfish.jersey.media - jersey-media-multipart - ${jersey-version} - - - org.glassfish.jersey.media - jersey-media-json-jackson - ${jersey-version} - - - - - com.fasterxml.jackson.core - jackson-core - ${jackson-version} - - - com.fasterxml.jackson.core - jackson-annotations - ${jackson-version} - - - com.fasterxml.jackson.core - jackson-databind - ${jackson-databind-version} - - - org.openapitools - jackson-databind-nullable - ${jackson-databind-nullable-version} - - {{#withXml}} - - - org.glassfish.jersey.media - jersey-media-jaxb - ${jersey-version} - - {{/withXml}} - {{#joda}} - - com.fasterxml.jackson.datatype - jackson-datatype-joda - ${jackson-version} - - {{/joda}} - {{#java8}} - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - ${jackson-version} - - {{/java8}} - {{#threetenbp}} - - com.github.joschi.jackson - jackson-datatype-threetenbp - ${threetenbp-version} - - {{/threetenbp}} - {{^java8}} - - - com.brsanthu - migbase64 - 2.2 - - {{/java8}} - {{#supportJava6}} - - org.apache.commons - commons-lang3 - ${commons-lang3-version} - - - commons-io - commons-io - ${commons-io-version} - - {{/supportJava6}} - - org.tomitribe - tomitribe-http-signatures - ${http-signature-version} - - {{#hasOAuthMethods}} - - com.github.scribejava - scribejava-apis - 6.9.0 - - {{/hasOAuthMethods}} - {{#useBeanValidation}} - - - javax.validation - validation-api - 1.1.0.Final - provided - - {{/useBeanValidation}} - - - junit - junit - ${junit-version} - test - - - - UTF-8 - 1.6.1 - {{^supportJava6}} - 2.30.1 - {{/supportJava6}} - {{#supportJava6}} - 2.6 - 2.5 - 3.6 - {{/supportJava6}} - 2.10.3 - 2.10.3 - 0.2.1 - {{#threetenbp}} - 2.9.10 - {{/threetenbp}} - 4.13 - 1.3 - - diff --git a/libraries/jersey2-experimental/AbstractOpenApiSchema.mustache b/libraries/jersey2/AbstractOpenApiSchema.mustache similarity index 100% rename from libraries/jersey2-experimental/AbstractOpenApiSchema.mustache rename to libraries/jersey2/AbstractOpenApiSchema.mustache diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 0111a24c4da..bcd9bb66bd9 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -11,6 +11,9 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; +{{#hasOAuthMethods}} +import com.github.scribejava.core.model.OAuth2AccessToken; +{{/hasOAuthMethods}} import org.glassfish.jersey.client.ClientConfig; import org.glassfish.jersey.client.ClientProperties; import org.glassfish.jersey.client.HttpUrlConnectorProvider; @@ -23,6 +26,7 @@ import org.glassfish.jersey.media.multipart.MultiPartFeature; import java.io.IOException; import java.io.InputStream; +import java.net.URI; {{^supportJava6}} import java.nio.file.Files; import java.nio.file.StandardCopyOption; @@ -42,7 +46,6 @@ import java.util.List; import java.util.Arrays; import java.util.ArrayList; import java.util.Date; -import java.util.TimeZone; import java.net.URLEncoder; @@ -56,11 +59,12 @@ import java.util.regex.Pattern; import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; import {{invokerPackage}}.auth.HttpBearerAuth; +import {{invokerPackage}}.auth.HttpSignatureAuth; import {{invokerPackage}}.auth.ApiKeyAuth; - {{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} +import {{invokerPackage}}.model.AbstractOpenApiSchema; {{>generatedAnnotation}} public class ApiClient { @@ -158,11 +162,26 @@ public class ApiClient { setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); // Setup authentications (key: authentication name, value: authentication). - authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} - authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} - authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} - authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} - authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + authentications = new HashMap(); + {{#authMethods}} + {{#isBasic}} + {{#isBasicBasic}} + authentications.put("{{name}}", new HttpBasicAuth()); + {{/isBasicBasic}} + {{#isBasicBearer}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}")); + {{/isBasicBearer}} + {{#isHttpSignature}} + authentications.put("{{name}}", new HttpSignatureAuth("{{name}}", null, null)); + {{/isHttpSignature}} + {{/isBasic}} + {{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}")); + {{/isApiKey}} + {{#isOAuth}} + authentications.put("{{name}}", new OAuth(basePath, "{{tokenUrl}}")); + {{/isOAuth}} + {{/authMethods}} // Prevent the authentications from being modified. authentications = Collections.unmodifiableMap(authentications); @@ -173,6 +192,7 @@ public class ApiClient { /** * Gets the JSON instance to do JSON serialization and deserialization. + * * @return JSON */ public JSON getJSON() { @@ -194,6 +214,9 @@ public class ApiClient { public ApiClient setBasePath(String basePath) { this.basePath = basePath; + {{#hasOAuthMethods}} + setOauthBasePath(basePath); + {{/hasOAuthMethods}} return this; } @@ -203,6 +226,7 @@ public class ApiClient { public ApiClient setServers(List servers) { this.servers = servers; + updateBasePath(); return this; } @@ -212,6 +236,7 @@ public class ApiClient { public ApiClient setServerIndex(Integer serverIndex) { this.serverIndex = serverIndex; + updateBasePath(); return this; } @@ -221,11 +246,27 @@ public class ApiClient { public ApiClient setServerVariables(Map serverVariables) { this.serverVariables = serverVariables; + updateBasePath(); return this; } + private void updateBasePath() { + setBasePath(servers.get(serverIndex).URL(serverVariables)); + } + + {{#hasOAuthMethods}} + private void setOauthBasePath(String basePath) { + for(Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setBasePath(basePath); + } + } + } + + {{/hasOAuthMethods}} /** * Get authentications (key: authentication name, value: authentication). + * * @return Map of authentication object */ public Map getAuthentications() { @@ -244,13 +285,14 @@ public class ApiClient { /** * Helper method to set username for the first HTTP basic authentication. + * * @param username Username */ - public void setUsername(String username) { + public ApiClient setUsername(String username) { for (Authentication auth : authentications.values()) { if (auth instanceof HttpBasicAuth) { ((HttpBasicAuth) auth).setUsername(username); - return; + return this; } } throw new RuntimeException("No HTTP basic authentication configured!"); @@ -258,13 +300,14 @@ public class ApiClient { /** * Helper method to set password for the first HTTP basic authentication. + * * @param password Password */ - public void setPassword(String password) { + public ApiClient setPassword(String password) { for (Authentication auth : authentications.values()) { if (auth instanceof HttpBasicAuth) { ((HttpBasicAuth) auth).setPassword(password); - return; + return this; } } throw new RuntimeException("No HTTP basic authentication configured!"); @@ -272,13 +315,14 @@ public class ApiClient { /** * Helper method to set API key value for the first API key authentication. + * * @param apiKey API key */ - public void setApiKey(String apiKey) { + public ApiClient setApiKey(String apiKey) { for (Authentication auth : authentications.values()) { if (auth instanceof ApiKeyAuth) { ((ApiKeyAuth) auth).setApiKey(apiKey); - return; + return this; } } throw new RuntimeException("No API key authentication configured!"); @@ -289,29 +333,31 @@ public class ApiClient { * * @param secrets Hash map from authentication name to its secret. */ - public void configureApiKeys(HashMap secrets) { + public ApiClient configureApiKeys(HashMap secrets) { for (Map.Entry authEntry : authentications.entrySet()) { Authentication auth = authEntry.getValue(); if (auth instanceof ApiKeyAuth) { String name = authEntry.getKey(); // respect x-auth-id-alias property - name = authenticationLookup.getOrDefault(name, name); + name = authenticationLookup.containsKey(name) ? authenticationLookup.get(name) : name; if (secrets.containsKey(name)) { ((ApiKeyAuth) auth).setApiKey(secrets.get(name)); } } } + return this; } /** * Helper method to set API key prefix for the first API key authentication. + * * @param apiKeyPrefix API key prefix */ - public void setApiKeyPrefix(String apiKeyPrefix) { + public ApiClient setApiKeyPrefix(String apiKeyPrefix) { for (Authentication auth : authentications.values()) { if (auth instanceof ApiKeyAuth) { ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); - return; + return this; } } throw new RuntimeException("No API key authentication configured!"); @@ -319,28 +365,92 @@ public class ApiClient { /** * Helper method to set bearer token for the first Bearer authentication. + * * @param bearerToken Bearer token */ - public void setBearerToken(String bearerToken) { + public ApiClient setBearerToken(String bearerToken) { for (Authentication auth : authentications.values()) { if (auth instanceof HttpBearerAuth) { ((HttpBearerAuth) auth).setBearerToken(bearerToken); - return; + return this; } } throw new RuntimeException("No Bearer authentication configured!"); } + {{#hasOAuthMethods}} /** * Helper method to set access token for the first OAuth2 authentication. * @param accessToken Access token */ - public void setAccessToken(String accessToken) { + public ApiClient setAccessToken(String accessToken) { for (Authentication auth : authentications.values()) { if (auth instanceof OAuth) { ((OAuth) auth).setAccessToken(accessToken); - return; + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Helper method to set the credentials for the first OAuth2 authentication. + * + * @param clientId the client ID + * @param clientSecret the client secret + */ + public ApiClient setOauthCredentials(String clientId, String clientSecret) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setCredentials(clientId, clientSecret); + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Helper method to set the password flow for the first OAuth2 authentication. + * + * @param username the user name + * @param password the user password + */ + public ApiClient setOauthPasswordFlow(String username, String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).usePasswordFlow(username, password); + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Helper method to set the authorization code flow for the first OAuth2 authentication. + * + * @param code the authorization code + */ + public ApiClient setOauthAuthorizationCodeFlow(String code) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).useAuthorizationCodeFlow(code); + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Helper method to set the scopes for the first OAuth2 authentication. + * + * @param scope the oauth scope + */ + public ApiClient setOauthScope(String scope) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setScope(scope); + return this; } } throw new RuntimeException("No OAuth2 authentication configured!"); @@ -700,6 +810,87 @@ public class ApiClient { return entity; } + /** + * Serialize the given Java object into string according the given + * Content-Type (only JSON, HTTP form is supported for now). + * @param obj Object + * @param formParams Form parameters + * @param contentType Context type + * @return String + * @throws ApiException API exception + */ + public String serializeToString(Object obj, Map formParams, String contentType) throws ApiException { + try { + if (contentType.startsWith("multipart/form-data")) { + throw new ApiException("multipart/form-data not yet supported for serializeToString (http signature authentication)"); + } else if (contentType.startsWith("application/x-www-form-urlencoded")) { + String formString = ""; + for (Entry param : formParams.entrySet()) { + formString = param.getKey() + "=" + URLEncoder.encode(parameterToString(param.getValue()), "UTF-8") + "&"; + } + + if (formString.length() == 0) { // empty string + return formString; + } else { + return formString.substring(0, formString.length() - 1); + } + } else { + return json.getMapper().writeValueAsString(obj); + } + } catch (Exception ex) { + throw new ApiException("Failed to perform serializeToString: " + ex.toString()); + } + } + + public AbstractOpenApiSchema deserializeSchemas(Response response, AbstractOpenApiSchema schema) throws ApiException{ + + Object result = null; + int matchCounter = 0; + ArrayList matchSchemas = new ArrayList<>(); + + for (Map.Entry entry : schema.getSchemas().entrySet()) { + String schemaName = entry.getKey(); + GenericType schemaType = entry.getValue(); + + if (schemaType instanceof GenericType) { // model + try { + Object deserializedObject = deserialize(response, schemaType); + if (deserializedObject != null) { + result = deserializedObject; + matchCounter++; + + if ("anyOf".equals(schema.getSchemaType())) { + break; + } else if ("oneOf".equals(schema.getSchemaType())) { + matchSchemas.add(schemaName); + } else { + throw new ApiException("Unknowe type found while expecting anyOf/oneOf:" + schema.getSchemaType()); + } + } else { + // failed to deserialize the response in the schema provided, proceed to the next one if any + } + } catch (Exception ex) { + // failed to deserialize, do nothing and try next one (schema) + } + } else {// unknown type + throw new ApiException(schemaType.getClass() + " is not a GenericType and cannot be handled properly in deserialization."); + } + + } + + if (matchCounter > 1 && "oneOf".equals(schema.getSchemaType())) {// more than 1 match for oneOf + throw new ApiException("Response body is invalid as it matches more than one schema (" + StringUtil.join(matchSchemas, ", ") + ") defined in the oneOf model: " + schema.getClass().getName()); + } else if (matchCounter == 0) { // fail to match any in oneOf/anyOf schemas + throw new ApiException("Response body is invalid as it doens't match any schemas (" + StringUtil.join(schema.getSchemas().keySet(), ", ") + ") defined in the oneOf/anyOf model: " + schema.getClass().getName()); + } else { // only one matched + schema.setActualInstance(result); + return schema; + } + + } + + + /** * Deserialize response body to Java object according to the Content-Type. * @param Type @@ -728,6 +919,9 @@ public class ApiClient { if (contentTypes != null && !contentTypes.isEmpty()) contentType = String.valueOf(contentTypes.get(0)); + // read the entity stream multiple times + response.bufferEntity(); + return response.readEntity(returnType); } @@ -804,33 +998,39 @@ public class ApiClient { * @param contentType The request's Content-Type header * @param authNames The authentications to apply * @param returnType The return type into which to deserialize the response + * @param schema An instance of the response that uses oneOf/anyOf * @return The response body in type of string * @throws ApiException API exception */ - public ApiResponse invokeAPI(String operation, String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { - updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); + public ApiResponse invokeAPI( + String operation, + String path, + String method, + List queryParams, + Object body, + Map headerParams, + Map cookieParams, + Map formParams, + String accept, + String contentType, + String[] authNames, + GenericType returnType, + AbstractOpenApiSchema schema) + throws ApiException { // Not using `.target(targetURL).path(path)` below, // to support (constant) query string in `path`, e.g. "/posts?draft=1" String targetURL; - if (serverIndex != null) { - Integer index; - List serverConfigurations; - Map variables; - - if (operationServers.containsKey(operation)) { - index = operationServerIndex.getOrDefault(operation, serverIndex); - variables = operationServerVariables.getOrDefault(operation, serverVariables); - serverConfigurations = operationServers.get(operation); - } else { - index = serverIndex; - variables = serverVariables; - serverConfigurations = servers; - } + if (operationServers.containsKey(operation)) { + Integer index = operationServerIndex.containsKey(operation) ? operationServerIndex.get(operation) : serverIndex; + Map variables = operationServerVariables.containsKey(operation) ? + operationServerVariables.get(operation) : serverVariables; + List serverConfigurations = operationServers.get(operation); if (index < 0 || index >= serverConfigurations.size()) { - throw new ArrayIndexOutOfBoundsException(String.format( - "Invalid index %d when selecting the host settings. Must be less than %d", index, serverConfigurations.size() - )); + throw new ArrayIndexOutOfBoundsException( + String.format( + "Invalid index %d when selecting the host settings. Must be less than %d", + index, serverConfigurations.size())); } targetURL = serverConfigurations.get(index).URL(variables) + path; } else { @@ -848,13 +1048,6 @@ public class ApiClient { Invocation.Builder invocationBuilder = target.request().accept(accept); - for (Entry entry : headerParams.entrySet()) { - String value = entry.getValue(); - if (value != null) { - invocationBuilder = invocationBuilder.header(entry.getKey(), value); - } - } - for (Entry entry : cookieParams.entrySet()) { String value = entry.getValue(); if (value != null) { @@ -869,51 +1062,65 @@ public class ApiClient { } } - for (Entry entry : defaultHeaderMap.entrySet()) { - String key = entry.getKey(); - if (!headerParams.containsKey(key)) { - String value = entry.getValue(); - if (value != null) { - invocationBuilder = invocationBuilder.header(key, value); - } + Entity entity = serialize(body, formParams, contentType); + + // put all headers in one place + Map allHeaderParams = new HashMap<>(defaultHeaderMap); + allHeaderParams.putAll(headerParams); + + // update different parameters (e.g. headers) for authentication + updateParamsForAuth( + authNames, + queryParams, + allHeaderParams, + cookieParams, + serializeToString(body, formParams, contentType), + method, + target.getUri()); + + for (Entry entry : allHeaderParams.entrySet()) { + String value = entry.getValue(); + if (value != null) { + invocationBuilder = invocationBuilder.header(entry.getKey(), value); } } - Entity entity = serialize(body, formParams, contentType); - Response response = null; try { - if ("GET".equals(method)) { - response = invocationBuilder.get(); - } else if ("POST".equals(method)) { - response = invocationBuilder.post(entity); - } else if ("PUT".equals(method)) { - response = invocationBuilder.put(entity); - } else if ("DELETE".equals(method)) { - response = invocationBuilder.method("DELETE", entity); - } else if ("PATCH".equals(method)) { - response = invocationBuilder.method("PATCH", entity); - } else if ("HEAD".equals(method)) { - response = invocationBuilder.head(); - } else if ("OPTIONS".equals(method)) { - response = invocationBuilder.options(); - } else if ("TRACE".equals(method)) { - response = invocationBuilder.trace(); - } else { - throw new ApiException(500, "unknown method type " + method); + response = sendRequest(method, invocationBuilder, entity); + + {{#hasOAuthMethods}} + // If OAuth is used and a status 401 is received, renew the access token and retry the request + if (response.getStatusInfo() == Status.UNAUTHORIZED) { + for (String authName : authNames) { + Authentication authentication = authentications.get(authName); + if (authentication instanceof OAuth) { + OAuth2AccessToken accessToken = ((OAuth) authentication).renewAccessToken(); + if (accessToken != null) { + invocationBuilder.header("Authorization", null); + invocationBuilder.header("Authorization", "Bearer " + accessToken.getAccessToken()); + response = sendRequest(method, invocationBuilder, entity); + } + break; + } + } } + {{/hasOAuthMethods}} int statusCode = response.getStatusInfo().getStatusCode(); Map> responseHeaders = buildResponseHeaders(response); - if (response.getStatus() == Status.NO_CONTENT.getStatusCode()) { - return new ApiResponse<{{#supportJava6}}T{{/supportJava6}}>(statusCode, responseHeaders); + if (response.getStatusInfo() == Status.NO_CONTENT) { + return new ApiResponse(statusCode, responseHeaders); } else if (response.getStatusInfo().getFamily() == Status.Family.SUCCESSFUL) { - if (returnType == null) - return new ApiResponse<{{#supportJava6}}T{{/supportJava6}}>(statusCode, responseHeaders); - else - return new ApiResponse<{{#supportJava6}}T{{/supportJava6}}>(statusCode, responseHeaders, deserialize(response, returnType)); + if (returnType == null) return new ApiResponse(statusCode, responseHeaders); + else if (schema == null) { + return new ApiResponse(statusCode, responseHeaders, deserialize(response, returnType)); + } else { // oneOf/anyOf + return new ApiResponse( + statusCode, responseHeaders, (T) deserializeSchemas(response, schema)); + } } else { String message = "error"; String respBody = null; @@ -926,26 +1133,40 @@ public class ApiClient { } } throw new ApiException( - response.getStatus(), - message, - buildResponseHeaders(response), - respBody); + response.getStatus(), message, buildResponseHeaders(response), respBody); } } finally { try { response.close(); } catch (Exception e) { - // it's not critical, since the response object is local in method invokeAPI; that's fine, just continue + // it's not critical, since the response object is local in method invokeAPI; that's fine, + // just continue } } } + private Response sendRequest(String method, Invocation.Builder invocationBuilder, Entity entity) { + Response response; + if ("POST".equals(method)) { + response = invocationBuilder.post(entity); + } else if ("PUT".equals(method)) { + response = invocationBuilder.put(entity); + } else if ("DELETE".equals(method)) { + response = invocationBuilder.method("DELETE", entity); + } else if ("PATCH".equals(method)) { + response = invocationBuilder.method("PATCH", entity); + } else { + response = invocationBuilder.method(method); + } + return response; + } + /** * @deprecated Add qualified name of the operation as a first parameter. */ @Deprecated - public ApiResponse invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { - return invokeAPI(null, path, method, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType); + public ApiResponse invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType, AbstractOpenApiSchema schema) throws ApiException { + return invokeAPI(null, path, method, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType, schema); } /** @@ -1003,12 +1224,17 @@ public class ApiClient { * @param queryParams List of query parameters * @param headerParams Map of header parameters * @param cookieParams Map of cookie parameters + * @param method HTTP method (e.g. POST) + * @param uri HTTP URI */ - protected void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams, Map cookieParams) { + protected void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams, + Map cookieParams, String payload, String method, URI uri) throws ApiException { for (String authName : authNames) { Authentication auth = authentications.get(authName); - if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); - auth.applyToParams(queryParams, headerParams, cookieParams); + if (auth == null) { + throw new RuntimeException("Authentication undefined: " + authName); + } + auth.applyToParams(queryParams, headerParams, cookieParams, payload, method, uri); } } } diff --git a/libraries/jersey2/ApiResponse.mustache b/libraries/jersey2/ApiResponse.mustache index a67b11f054c..5dae9dc1fdf 100644 --- a/libraries/jersey2/ApiResponse.mustache +++ b/libraries/jersey2/ApiResponse.mustache @@ -44,14 +44,29 @@ public class ApiResponse { this.data = data; } + /** + * Get the status code + * + * @return status code + */ public int getStatusCode() { return statusCode; } + /** + * Get the headers + * + * @return map of headers + */ public Map> getHeaders() { return headers; } + /** + * Get the data + * + * @return data + */ public T getData() { return data; } diff --git a/libraries/jersey2/JSON.mustache b/libraries/jersey2/JSON.mustache index 56ea77278f7..dc3d9893e6d 100644 --- a/libraries/jersey2/JSON.mustache +++ b/libraries/jersey2/JSON.mustache @@ -27,8 +27,8 @@ public class JSON implements ContextResolver { public JSON() { mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true); mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); @@ -62,4 +62,11 @@ public class JSON implements ContextResolver { public ObjectMapper getContext(Class type) { return mapper; } + + /** + * Get the object mapper + * + * @return object mapper + */ + public ObjectMapper getMapper() { return mapper; } } diff --git a/libraries/jersey2-experimental/anyof_model.mustache b/libraries/jersey2/anyof_model.mustache similarity index 100% rename from libraries/jersey2-experimental/anyof_model.mustache rename to libraries/jersey2/anyof_model.mustache diff --git a/libraries/jersey2/api.mustache b/libraries/jersey2/api.mustache index 4a2e61afe8e..509ae48a50e 100644 --- a/libraries/jersey2/api.mustache +++ b/libraries/jersey2/api.mustache @@ -16,8 +16,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -{{/fullJavaUtil}} +{{/fullJavaUtil}} {{>generatedAnnotation}} {{#operations}} public class {{classname}} { @@ -31,13 +31,24 @@ public class {{classname}} { this.apiClient = apiClient; } + /** + * Get the API cilent + * + * @return API client + */ public ApiClient getApiClient() { return apiClient; } + /** + * Set the API cilent + * + * @param apiClient an instance of API client + */ public void setApiClient(ApiClient apiClient) { this.apiClient = apiClient; } + {{#operation}} {{^vendorExtensions.x-group-parameters}} /** @@ -150,8 +161,13 @@ public class {{classname}} { String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; - {{#returnType}}GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {};{{/returnType}} - return apiClient.invokeAPI("{{classname}}.{{operationId}}", localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, {{#returnType}}localVarReturnType{{/returnType}}{{^returnType}}null{{/returnType}}); + {{#returnType}} + GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {}; + + {{/returnType}} + return apiClient.invokeAPI("{{classname}}.{{operationId}}", localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, + localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, + localVarAuthNames, {{#returnType}}localVarReturnType{{/returnType}}{{^returnType}}null{{/returnType}}, {{#vendorExtensions.x-java-return-type-one-of}}new {{{returnType}}}(){{/vendorExtensions.x-java-return-type-one-of}}{{^vendorExtensions.x-java-return-type-one-of}}{{#vendorExtensions.x-java-return-type-any-of}}new {{{returnType}}}(){{/vendorExtensions.x-java-return-type-any-of}}{{^vendorExtensions.x-java-return-type-any-of}}null{{/vendorExtensions.x-java-return-type-any-of}}{{/vendorExtensions.x-java-return-type-one-of}}); } {{#vendorExtensions.x-group-parameters}} @@ -165,7 +181,8 @@ public class {{classname}} { this.{{localVariablePrefix}}{{paramName}} = {{paramName}}; {{/pathParams}} } - {{#allParams}}{{^isPathParam}} + {{#allParams}} + {{^isPathParam}} /** * Set {{paramName}} @@ -176,7 +193,8 @@ public class {{classname}} { this.{{localVariablePrefix}}{{paramName}} = {{paramName}}; return this; } - {{/isPathParam}}{{/allParams}} + {{/isPathParam}} + {{/allParams}} /** * Execute {{operationId}} request @@ -211,9 +229,12 @@ public class {{classname}} { {{/responses}} {{/responses.0}} - {{#isDeprecated}}* @deprecated{{/isDeprecated}} + {{#isDeprecated}} + * @deprecated{{/isDeprecated}} */ - {{#isDeprecated}}@Deprecated{{/isDeprecated}} + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} public ApiResponse<{{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> executeWithHttpInfo() throws ApiException { return {{operationId}}WithHttpInfo({{#allParams}}{{localVariablePrefix}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); } @@ -229,7 +250,9 @@ public class {{classname}} { {{#externalDocs}}* {{description}} * @see {{summary}} Documentation{{/externalDocs}} */ - {{#isDeprecated}}@Deprecated{{/isDeprecated}} + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} public API{{operationId}}Request {{operationId}}({{#pathParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}) throws ApiException { return new API{{operationId}}Request({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}); } diff --git a/libraries/jersey2/apiException.mustache b/libraries/jersey2/apiException.mustache index e8952456591..f0079c7bbec 100644 --- a/libraries/jersey2/apiException.mustache +++ b/libraries/jersey2/apiException.mustache @@ -9,6 +9,9 @@ import java.util.Map.Entry; import java.util.TreeMap; {{/caseInsensitiveResponseHeaders}} +/** + * API Exception + */ {{>generatedAnnotation}} public class ApiException extends{{#useRuntimeException}} RuntimeException {{/useRuntimeException}}{{^useRuntimeException}} Exception {{/useRuntimeException}}{ private int code = 0; diff --git a/libraries/jersey2/api_test.mustache b/libraries/jersey2/api_test.mustache index 21e0f97d639..5ee6e494084 100644 --- a/libraries/jersey2/api_test.mustache +++ b/libraries/jersey2/api_test.mustache @@ -7,6 +7,7 @@ import {{invokerPackage}}.ApiException; {{/imports}} import org.junit.Test; import org.junit.Ignore; +import org.junit.Assert; {{^fullJavaUtil}} import java.util.ArrayList; @@ -18,7 +19,6 @@ import java.util.Map; /** * API tests for {{classname}} */ -@Ignore public class {{classname}}Test { private final {{classname}} api = new {{classname}}(); @@ -35,15 +35,15 @@ public class {{classname}}Test { @Test public void {{operationId}}Test() throws ApiException { {{#allParams}} - {{{dataType}}} {{paramName}} = null; + //{{{dataType}}} {{paramName}} = null; {{/allParams}} {{^vendorExtensions.x-group-parameters}} - {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + //{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); {{/vendorExtensions.x-group-parameters}} {{#vendorExtensions.x-group-parameters}} - {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}){{#allParams}}{{^isPathParam}} - .{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}} - .execute(); + //{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}){{#allParams}}{{^isPathParam}} + // .{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}} + // .execute(); {{/vendorExtensions.x-group-parameters}} // TODO: test validations } diff --git a/libraries/jersey2-experimental/auth/ApiKeyAuth.mustache b/libraries/jersey2/auth/ApiKeyAuth.mustache similarity index 100% rename from libraries/jersey2-experimental/auth/ApiKeyAuth.mustache rename to libraries/jersey2/auth/ApiKeyAuth.mustache diff --git a/libraries/jersey2-experimental/auth/Authentication.mustache b/libraries/jersey2/auth/Authentication.mustache similarity index 100% rename from libraries/jersey2-experimental/auth/Authentication.mustache rename to libraries/jersey2/auth/Authentication.mustache diff --git a/libraries/jersey2-experimental/auth/HttpBasicAuth.mustache b/libraries/jersey2/auth/HttpBasicAuth.mustache similarity index 100% rename from libraries/jersey2-experimental/auth/HttpBasicAuth.mustache rename to libraries/jersey2/auth/HttpBasicAuth.mustache diff --git a/libraries/jersey2-experimental/auth/HttpBearerAuth.mustache b/libraries/jersey2/auth/HttpBearerAuth.mustache similarity index 100% rename from libraries/jersey2-experimental/auth/HttpBearerAuth.mustache rename to libraries/jersey2/auth/HttpBearerAuth.mustache diff --git a/libraries/jersey2-experimental/auth/HttpSignatureAuth.mustache b/libraries/jersey2/auth/HttpSignatureAuth.mustache similarity index 100% rename from libraries/jersey2-experimental/auth/HttpSignatureAuth.mustache rename to libraries/jersey2/auth/HttpSignatureAuth.mustache diff --git a/libraries/jersey2-experimental/auth/OAuth.mustache b/libraries/jersey2/auth/OAuth.mustache similarity index 100% rename from libraries/jersey2-experimental/auth/OAuth.mustache rename to libraries/jersey2/auth/OAuth.mustache diff --git a/libraries/jersey2-experimental/auth/OAuthFlow.mustache b/libraries/jersey2/auth/OAuthFlow.mustache similarity index 100% rename from libraries/jersey2-experimental/auth/OAuthFlow.mustache rename to libraries/jersey2/auth/OAuthFlow.mustache diff --git a/libraries/jersey2-experimental/model.mustache b/libraries/jersey2/model.mustache similarity index 100% rename from libraries/jersey2-experimental/model.mustache rename to libraries/jersey2/model.mustache diff --git a/libraries/jersey2-experimental/oneof_model.mustache b/libraries/jersey2/oneof_model.mustache similarity index 100% rename from libraries/jersey2-experimental/oneof_model.mustache rename to libraries/jersey2/oneof_model.mustache diff --git a/libraries/jersey2-experimental/pojo.mustache b/libraries/jersey2/pojo.mustache similarity index 100% rename from libraries/jersey2-experimental/pojo.mustache rename to libraries/jersey2/pojo.mustache diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index d999ffaf0fa..ce5855067d5 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -63,7 +63,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.12 + 3.0.0-M4 @@ -73,7 +73,7 @@ -Xms512m -Xmx1500m methods - pertest + 10 @@ -142,7 +142,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.6.1 + 3.8.1 {{#supportJava6}} 1.6 @@ -158,6 +158,13 @@ 1.7 {{/java8}} {{/supportJava6}} + true + 128m + 512m + + -Xlint:all + -J-Xss4m + @@ -283,64 +290,74 @@ ${jackson-databind-nullable-version} {{#withXml}} - - - - org.glassfish.jersey.media - jersey-media-jaxb - ${jersey-version} - - + + + org.glassfish.jersey.media + jersey-media-jaxb + ${jersey-version} + {{/withXml}} {{#joda}} - - com.fasterxml.jackson.datatype - jackson-datatype-joda - ${jackson-version} - + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + {{/joda}} {{#java8}} - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - ${jackson-version} - + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + {{/java8}} {{#threetenbp}} - - com.github.joschi.jackson - jackson-datatype-threetenbp - ${threetenbp-version} - + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${threetenbp-version} + {{/threetenbp}} {{^java8}} - - - com.brsanthu - migbase64 - 2.2 - + + + com.brsanthu + migbase64 + 2.2 + {{/java8}} {{#supportJava6}} - - org.apache.commons - commons-lang3 - ${commons_lang3_version} - - - commons-io - commons-io - ${commons_io_version} - + + org.apache.commons + commons-lang3 + ${commons-lang3-version} + + + commons-io + commons-io + ${commons-io-version} + {{/supportJava6}} + + org.tomitribe + tomitribe-http-signatures + ${http-signature-version} + + {{#hasOAuthMethods}} + + com.github.scribejava + scribejava-apis + 6.9.0 + + {{/hasOAuthMethods}} {{#useBeanValidation}} - - - javax.validation - validation-api - 1.1.0.Final - provided - + + + javax.validation + validation-api + 1.1.0.Final + provided + {{/useBeanValidation}} @@ -354,12 +371,12 @@ UTF-8 1.6.1 {{^supportJava6}} - 2.27 + 2.30.1 {{/supportJava6}} {{#supportJava6}} 2.6 - 2.5 - 3.6 + 2.5 + 3.6 {{/supportJava6}} 2.10.3 2.10.3 @@ -367,7 +384,7 @@ {{#threetenbp}} 2.9.10 {{/threetenbp}} - 1.0.0 4.13 + 1.3 From 5070e94f4d5a3c6874bb6fec8e68d6eed4db3a8c Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 13 May 2020 00:46:53 +0800 Subject: [PATCH 232/370] add null type support to oneof/anyof java jersey2 (#6269) --- .../jersey2/AbstractOpenApiSchema.mustache | 19 ++++++++++++++++- libraries/jersey2/ApiClient.mustache | 9 ++++++++ libraries/jersey2/anyof_model.mustache | 21 ++++++++++++++++++- libraries/jersey2/oneof_model.mustache | 11 +++++++++- 4 files changed, 57 insertions(+), 3 deletions(-) diff --git a/libraries/jersey2/AbstractOpenApiSchema.mustache b/libraries/jersey2/AbstractOpenApiSchema.mustache index 61fddeca43b..cdba3be8455 100644 --- a/libraries/jersey2/AbstractOpenApiSchema.mustache +++ b/libraries/jersey2/AbstractOpenApiSchema.mustache @@ -16,11 +16,15 @@ public abstract class AbstractOpenApiSchema { // store the actual instance of the schema/object private Object instance; + // is nullable + private Boolean isNullable; + // schema type (e.g. oneOf, anyOf) private final String schemaType; - public AbstractOpenApiSchema(String schemaType) { + public AbstractOpenApiSchema(String schemaType, Boolean isNullable) { this.schemaType = schemaType; + this.isNullable = isNullable; } /*** @@ -52,4 +56,17 @@ public abstract class AbstractOpenApiSchema { public String getSchemaType() { return schemaType; } + + /*** + * Is nullalble + * + * @return true if it's nullable + */ + public Boolean isNullable() { + if (Boolean.TRUE.equals(isNullable)) { + return Boolean.TRUE; + } else { + return Boolean.FALSE; + } + } } diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index bcd9bb66bd9..87f6c5f1016 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -848,6 +848,15 @@ public class ApiClient { int matchCounter = 0; ArrayList matchSchemas = new ArrayList<>(); + if (schema.isNullable()) { + response.bufferEntity(); + if ("{}".equals(String.valueOf(response.readEntity(String.class))) || + "".equals(String.valueOf(response.readEntity(String.class)))) { + // schema is nullable and the response body is {} or empty string + return schema; + } + } + for (Map.Entry entry : schema.getSchemas().entrySet()) { String schemaName = entry.getKey(); GenericType schemaType = entry.getValue(); diff --git a/libraries/jersey2/anyof_model.mustache b/libraries/jersey2/anyof_model.mustache index a3702d221ad..0ce4e381f4a 100644 --- a/libraries/jersey2/anyof_model.mustache +++ b/libraries/jersey2/anyof_model.mustache @@ -11,7 +11,7 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im public final static Map schemas = new HashMap(); public {{classname}}() { - super("anyOf"); + super("anyOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); } static { @@ -25,4 +25,23 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im public Map getSchemas() { return {{classname}}.schemas; } + + @Override + public void setActualInstance(Object instance) { + {{#isNulalble}} + if (instance == null) { + super.setActualInstance(instance); + return; + } + + {{/isNulalble}} + {{#anyOf}} + if (instance instanceof {{{.}}}) { + super.setActualInstance(instance); + return; + } + + {{/anyOf}} + throw new RuntimeException("Invalid instance type. Must be {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}"); + } } diff --git a/libraries/jersey2/oneof_model.mustache b/libraries/jersey2/oneof_model.mustache index b5d4442e608..ffd739dfdd8 100644 --- a/libraries/jersey2/oneof_model.mustache +++ b/libraries/jersey2/oneof_model.mustache @@ -11,7 +11,7 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im public final static Map schemas = new HashMap(); public {{classname}}() { - super("oneOf"); + super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); } static { @@ -28,6 +28,13 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im @Override public void setActualInstance(Object instance) { + {{#isNulalble}} + if (instance == null) { + super.setActualInstance(instance); + return; + } + + {{/isNulalble}} {{#oneOf}} if (instance instanceof {{{.}}}) { super.setActualInstance(instance); @@ -38,4 +45,6 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im throw new RuntimeException("Invalid instance type. Must be {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}"); } + + } From ceefec29eb265a07039a7baabfb8ea1fa7858435 Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Tue, 12 May 2020 23:01:42 -0700 Subject: [PATCH 233/370] Mustache template should use invokerPackage tag to generate import (#6277) --- libraries/jersey2/AbstractOpenApiSchema.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/jersey2/AbstractOpenApiSchema.mustache b/libraries/jersey2/AbstractOpenApiSchema.mustache index cdba3be8455..c924650e6c0 100644 --- a/libraries/jersey2/AbstractOpenApiSchema.mustache +++ b/libraries/jersey2/AbstractOpenApiSchema.mustache @@ -2,7 +2,7 @@ package {{invokerPackage}}.model; -import org.openapitools.client.ApiException; +import {{invokerPackage}}.ApiException; import java.lang.reflect.Type; import java.util.Map; import javax.ws.rs.core.GenericType; From cbf2e181baf478ab4a2a0b3f6a7a94a5bd3a1201 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Sat, 16 May 2020 23:56:31 +0800 Subject: [PATCH 234/370] [Java] update jackson databind versions (#6328) * update databind version * update gradle build --- build.gradle.mustache | 2 +- libraries/google-api-client/build.gradle.mustache | 2 +- libraries/google-api-client/build.sbt.mustache | 2 +- libraries/google-api-client/pom.mustache | 4 ++-- libraries/jersey2/build.gradle.mustache | 2 +- libraries/jersey2/build.sbt.mustache | 6 +++--- libraries/jersey2/pom.mustache | 4 ++-- libraries/resteasy/build.gradle.mustache | 4 ++-- libraries/resteasy/build.sbt.mustache | 6 +++--- libraries/resteasy/pom.mustache | 4 ++-- libraries/resttemplate/build.gradle.mustache | 4 ++-- libraries/resttemplate/pom.mustache | 4 ++-- libraries/retrofit2/build.gradle.mustache | 6 +++--- libraries/retrofit2/build.sbt.mustache | 12 ++++++------ libraries/retrofit2/pom.mustache | 4 ++-- libraries/vertx/build.gradle.mustache | 4 ++-- libraries/vertx/pom.mustache | 4 ++-- 17 files changed, 37 insertions(+), 37 deletions(-) diff --git a/build.gradle.mustache b/build.gradle.mustache index c1bf968dbac..38ece474ad8 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -137,7 +137,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" jackson_version = "2.10.3" - jackson_databind_version = "2.10.3" + jackson_databind_version = "2.10.4" jackson_databind_nullable_version = "0.2.1" {{#threetenbp}} jackson_threetenbp_version = "2.9.10" diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache index 0089f90de78..f6a517fbb92 100644 --- a/libraries/google-api-client/build.gradle.mustache +++ b/libraries/google-api-client/build.gradle.mustache @@ -121,7 +121,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" jackson_version = "2.10.1" - jackson_databind_version = "2.10.1" + jackson_databind_version = "2.10.4" jackson_databind_nullable_version = "0.2.1" google_api_client_version = "1.23.0" jersey_common_version = "2.25.1" diff --git a/libraries/google-api-client/build.sbt.mustache b/libraries/google-api-client/build.sbt.mustache index 7d958dfadfb..516fe0eb90e 100644 --- a/libraries/google-api-client/build.sbt.mustache +++ b/libraries/google-api-client/build.sbt.mustache @@ -14,7 +14,7 @@ lazy val root = (project in file(".")). "org.glassfish.jersey.core" % "jersey-common" % "2.25.1", "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.4" % "compile", {{#withXml}} "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.9.10" % "compile", {{/withXml}} diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index 4d6a8c5e161..2412ba208ec 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -309,8 +309,8 @@ 1.5.22 1.30.2 2.25.1 - 2.10.3 - 2.10.3 + 2.10.4 + 2.10.4 0.2.1 {{#joda}} 2.9.9 diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index cdb451adb34..633cd317963 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -120,7 +120,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" jackson_version = "2.10.3" - jackson_databind_version = "2.10.3" + jackson_databind_version = "2.10.4" jackson_databind_nullable_version = "0.2.1" {{#supportJava6}} jersey_version = "2.6" diff --git a/libraries/jersey2/build.sbt.mustache b/libraries/jersey2/build.sbt.mustache index abb91ecdc99..d3dd1b5c50a 100644 --- a/libraries/jersey2/build.sbt.mustache +++ b/libraries/jersey2/build.sbt.mustache @@ -13,9 +13,9 @@ lazy val root = (project in file(".")). "org.glassfish.jersey.core" % "jersey-client" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, "org.glassfish.jersey.media" % "jersey-media-multipart" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, "org.glassfish.jersey.media" % "jersey-media-json-jackson" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.4" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.4" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.4" % "compile", {{#joda}} "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.10" % "compile", {{/joda}} diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index ce5855067d5..99e6822fd13 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -378,8 +378,8 @@ 2.5 3.6 {{/supportJava6}} - 2.10.3 - 2.10.3 + 2.10.4 + 2.10.4 0.2.1 {{#threetenbp}} 2.9.10 diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index 89c6fb24ee4..a3973d45951 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -119,8 +119,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.10.3" - jackson_databind_version = "2.10.3" + jackson_version = "2.10.4" + jackson_databind_version = "2.10.4" jackson_databind_nullable_version = "0.2.1" threetenbp_version = "2.9.10" resteasy_version = "3.1.3.Final" diff --git a/libraries/resteasy/build.sbt.mustache b/libraries/resteasy/build.sbt.mustache index 351c072616f..d265cf2a630 100644 --- a/libraries/resteasy/build.sbt.mustache +++ b/libraries/resteasy/build.sbt.mustache @@ -13,9 +13,9 @@ lazy val root = (project in file(".")). "org.jboss.resteasy" % "resteasy-client" % "3.1.3.Final" % "compile", "org.jboss.resteasy" % "resteasy-multipart-provider" % "3.1.3.Final" % "compile", "org.jboss.resteasy" % "resteasy-jackson2-provider" % "3.1.3.Final" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.4" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.4" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.4" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", {{#java8}} "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.10" % "compile", diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index 714f4299b74..d09da29b472 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -297,8 +297,8 @@ UTF-8 1.5.22 3.1.3.Final - 2.10.3 - 2.10.3 + 2.10.4 + 2.10.4 0.2.1 2.9.10 {{^java8}} diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index c61825adbb9..4eb1e7d212e 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -120,8 +120,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.10.3" - jackson_databind_version = "2.10.3" + jackson_version = "2.10.4" + jackson_databind_version = "2.10.4" jackson_databind_nullable_version = "0.2.1" spring_web_version = "4.3.9.RELEASE" jodatime_version = "2.9.9" diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache index c9f02fffca4..708e02dffc1 100644 --- a/libraries/resttemplate/pom.mustache +++ b/libraries/resttemplate/pom.mustache @@ -312,8 +312,8 @@ UTF-8 1.5.22 4.3.9.RELEASE - 2.10.3 - 2.10.3 + 2.10.4 + 2.10.4 0.2.1 {{#joda}} 2.9.9 diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index 82f7974062b..6a7b8e8cca8 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -127,12 +127,12 @@ ext { play_version = "2.4.11" {{/play24}} {{#play25}} - jackson_version = "2.10.1" + jackson_version = "2.10.4" play_version = "2.5.14" {{/play25}} {{#play26}} - jackson_version = "2.10.3" - jackson_databind_version = "2.10.3" + jackson_version = "2.10.4" + jackson_databind_version = "2.10.4" jackson_databind_nullable_version = "0.2.1" play_version = "2.6.7" {{/play26}} diff --git a/libraries/retrofit2/build.sbt.mustache b/libraries/retrofit2/build.sbt.mustache index f7b7ce464d5..4c85b1411d2 100644 --- a/libraries/retrofit2/build.sbt.mustache +++ b/libraries/retrofit2/build.sbt.mustache @@ -23,16 +23,16 @@ lazy val root = (project in file(".")). {{/play24}} {{#play25}} "com.typesafe.play" % "play-java-ws_2.11" % "2.5.15" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.4" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.4" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.4" % "compile", {{/play25}} {{#play26}} "com.typesafe.play" % "play-ahc-ws_2.12" % "2.6.7" % "compile", "javax.validation" % "validation-api" % "1.1.0.Final" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10.3" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.4" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.4" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.4" % "compile", {{/play26}} "com.squareup.retrofit2" % "converter-jackson" % "2.3.0" % "compile", {{/usePlayWS}} diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index 06f19bcb034..61bacc3bb7c 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -384,11 +384,11 @@ 2.4.11 {{/play24}} {{#play25}} - 2.10.3 + 2.10.4 2.5.15 {{/play25}} {{#play26}} - 2.10.3 + 2.10.4 2.6.7 {{/play26}} 0.2.1 diff --git a/libraries/vertx/build.gradle.mustache b/libraries/vertx/build.gradle.mustache index 02760c59149..5287bc16166 100644 --- a/libraries/vertx/build.gradle.mustache +++ b/libraries/vertx/build.gradle.mustache @@ -28,8 +28,8 @@ task execute(type:JavaExec) { ext { swagger_annotations_version = "1.5.21" - jackson_version = "2.10.3" - jackson_databind_version = "2.10.3" + jackson_version = "2.10.4" + jackson_databind_version = "2.10.4" vertx_version = "3.4.2" junit_version = "4.13" } diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache index b3539c9fd77..587a6e76cc4 100644 --- a/libraries/vertx/pom.mustache +++ b/libraries/vertx/pom.mustache @@ -292,8 +292,8 @@ UTF-8 3.4.2 1.5.22 - 2.10.3 - 2.10.3 + 2.10.4 + 2.10.4 0.2.1 4.13 From 2c75e70e82a5a2df86fa611a2cb98a78f821d023 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Sun, 17 May 2020 17:59:57 +0800 Subject: [PATCH 235/370] fix gradle in some java clients (#6339) --- libraries/jersey2/build.gradle.mustache | 8 ++++++++ libraries/jersey2/build.sbt.mustache | 4 ++++ libraries/jersey2/pom.mustache | 5 ++++- libraries/vertx/build.gradle.mustache | 2 ++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index 633cd317963..90843185f55 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -134,6 +134,10 @@ ext { {{#threetenbp}} threetenbp_version = "2.9.10" {{/threetenbp}} + {{#hasOAuthMethods}} + scribejava_apis_version = "6.9.0" + {{/hasOAuthMethods}} + tomitribe_http_signatures_version = "1.3" } dependencies { @@ -152,6 +156,10 @@ dependencies { {{#java8}} compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} + {{#hasOAuthMethods}} + compile "com.github.scribejava:scribejava-apis:$scribejava_apis_version" + {{/hasOAuthMethods}} + compile "org.tomitribe:tomitribe-http-signatures:$tomitribe_http_signatures_version" {{#supportJava6}} compile "commons-io:commons-io:$commons_io_version" compile "org.apache.commons:commons-lang3:$commons_lang3_version" diff --git a/libraries/jersey2/build.sbt.mustache b/libraries/jersey2/build.sbt.mustache index d3dd1b5c50a..e179fc9054a 100644 --- a/libraries/jersey2/build.sbt.mustache +++ b/libraries/jersey2/build.sbt.mustache @@ -25,6 +25,10 @@ lazy val root = (project in file(".")). {{#threetenbp}} "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", {{/threetenbp}} + {{#hasOAuthMethods}} + "com.github.scribejava" % "scribejava-apis" % "6.9.0" % "compile", + {{/hasOAuthMethods}} + "org.tomitribe" % "tomitribe-http-signatures" % "1.3" % "compile", {{^java8}} "com.brsanthu" % "migbase64" % "2.2", {{/java8}} diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 99e6822fd13..9030427467c 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -347,7 +347,7 @@ com.github.scribejava scribejava-apis - 6.9.0 + ${scribejava-apis-version} {{/hasOAuthMethods}} {{#useBeanValidation}} @@ -386,5 +386,8 @@ {{/threetenbp}} 4.13 1.3 + {{#hasOAuthMethods}} + 6.9.0 + {{/hasOAuthMethods}} diff --git a/libraries/vertx/build.gradle.mustache b/libraries/vertx/build.gradle.mustache index 5287bc16166..c6c76b8e8b8 100644 --- a/libraries/vertx/build.gradle.mustache +++ b/libraries/vertx/build.gradle.mustache @@ -32,6 +32,7 @@ ext { jackson_databind_version = "2.10.4" vertx_version = "3.4.2" junit_version = "4.13" + jackson_databind_nullable_version = "0.2.1" } dependencies { @@ -51,6 +52,7 @@ dependencies { {{#threetenbp}} compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_version" {{/threetenbp}} + compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" testCompile "junit:junit:$junit_version" testCompile "io.vertx:vertx-unit:$vertx_version" } From d4c250d6450efc0be1d2197a4fead0b872499983 Mon Sep 17 00:00:00 2001 From: Slavek Kabrda Date: Sun, 17 May 2020 17:44:54 +0200 Subject: [PATCH 236/370] [Java][jersey2] Allow setting serverIndex to null (#6321) --- libraries/jersey2/ApiClient.mustache | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 87f6c5f1016..41db79fc8e5 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -251,7 +251,9 @@ public class ApiClient { } private void updateBasePath() { - setBasePath(servers.get(serverIndex).URL(serverVariables)); + if (serverIndex != null) { + setBasePath(servers.get(serverIndex).URL(serverVariables)); + } } {{#hasOAuthMethods}} @@ -1030,7 +1032,7 @@ public class ApiClient { // Not using `.target(targetURL).path(path)` below, // to support (constant) query string in `path`, e.g. "/posts?draft=1" String targetURL; - if (operationServers.containsKey(operation)) { + if (serverIndex != null && operationServers.containsKey(operation)) { Integer index = operationServerIndex.containsKey(operation) ? operationServerIndex.get(operation) : serverIndex; Map variables = operationServerVariables.containsKey(operation) ? operationServerVariables.get(operation) : serverVariables; From 324875cf2230d8b30737231ff4036f58af8f954c Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Wed, 20 May 2020 00:51:08 -0700 Subject: [PATCH 237/370] [Java] Upgrade http signature library to version 1.4 (#6370) * Mustache template should use invokerPackage tag to generate import * upgrade to http signature library version 1.4 * Use updated HTTP signature library * Run sample scripts * Add code samples in README file for HTTP signature * fix java imports * Update http-signature version --- README.mustache | 19 ++++- .../jersey2/auth/HttpSignatureAuth.mustache | 73 +++++++++++++++++-- libraries/jersey2/pom.mustache | 2 +- 3 files changed, 86 insertions(+), 8 deletions(-) diff --git a/README.mustache b/README.mustache index 917f873d5dc..85fd77af642 100644 --- a/README.mustache +++ b/README.mustache @@ -104,7 +104,24 @@ public class {{{classname}}}Example { //{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} // Configure OAuth2 access token for authorization: {{{name}}} OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); - {{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}} + {{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}}{{#isHttpSignature}} + // Configure HTTP signature authorization: {{{name}}} + HttpSignatureAuth {{{name}}} = (HttpSignatureAuth) defaultClient.getAuthentication("{{{name}}}"); + // All the HTTP signature parameters below should be customized to your environment. + // Configure the keyId + {{{name}}}.setKeyId("YOUR KEY ID"); + // Configure the signature algorithm + {{{name}}}.setSigningAlgorithm(SigningAlgorithm.HS2019); + // Configure the specific cryptographic algorithm + {{{name}}}.setAlgorithm(Algorithm.ECDSA_SHA256); + // Configure the cryptographic algorithm parameters, if applicable + {{{name}}}.setAlgorithmParameterSpec(null); + // Set the cryptographic digest algorithm. + {{{name}}}.setDigestAlgorithm("SHA-256"); + // Set the HTTP headers that should be included in the HTTP signature. + {{{name}}}.setHeaders(Arrays.asList("date", "host")); + // Set the private key used to sign the HTTP messages + {{{name}}}.setPrivateKey();{{/isHttpSignature}} {{/authMethods}} {{/hasAuthMethods}} diff --git a/libraries/jersey2/auth/HttpSignatureAuth.mustache b/libraries/jersey2/auth/HttpSignatureAuth.mustache index e56e0d22910..75adbdbba3f 100644 --- a/libraries/jersey2/auth/HttpSignatureAuth.mustache +++ b/libraries/jersey2/auth/HttpSignatureAuth.mustache @@ -16,8 +16,12 @@ import java.util.Date; import java.util.Locale; import java.util.Map; import java.util.List; +import java.security.spec.AlgorithmParameterSpec; -import org.tomitribe.auth.signatures.*; +import org.tomitribe.auth.signatures.Algorithm; +import org.tomitribe.auth.signatures.Signer; +import org.tomitribe.auth.signatures.Signature; +import org.tomitribe.auth.signatures.SigningAlgorithm; /** * A Configuration object for the HTTP message signature security scheme. @@ -30,8 +34,14 @@ public class HttpSignatureAuth implements Authentication { private String keyId; // The HTTP signature algorithm. + private SigningAlgorithm signingAlgorithm; + + // The HTTP cryptographic algorithm. private Algorithm algorithm; + // The cryptographic parameters. + private AlgorithmParameterSpec parameterSpec; + // The list of HTTP headers that should be included in the HTTP signature. private List headers; @@ -42,14 +52,23 @@ public class HttpSignatureAuth implements Authentication { * Construct a new HTTP signature auth configuration object. * * @param keyId An opaque string that the server can use to look up the component they need to validate the signature. - * @param algorithm The signature algorithm. + * @param signingAlgorithm The signature algorithm. + * @param algorithm The cryptographic algorithm. + * @param digestAlgorithm The digest algorithm. * @param headers The list of HTTP headers that should be included in the HTTP signature. */ - public HttpSignatureAuth(String keyId, Algorithm algorithm, List headers) { + public HttpSignatureAuth(String keyId, + SigningAlgorithm signingAlgorithm, + Algorithm algorithm, + String digestAlgorithm, + AlgorithmParameterSpec parameterSpec, + List headers) { this.keyId = keyId; + this.signingAlgorithm = signingAlgorithm; this.algorithm = algorithm; + this.parameterSpec = parameterSpec; + this.digestAlgorithm = digestAlgorithm; this.headers = headers; - this.digestAlgorithm = "SHA-256"; } /** @@ -73,12 +92,28 @@ public class HttpSignatureAuth implements Authentication { /** * Returns the HTTP signature algorithm which is used to sign HTTP requests. */ + public SigningAlgorithm getSigningAlgorithm() { + return signingAlgorithm; + } + + /** + * Sets the HTTP signature algorithm which is used to sign HTTP requests. + * + * @param signingAlgorithm The HTTP signature algorithm. + */ + public void setSigningAlgorithm(SigningAlgorithm signingAlgorithm) { + this.signingAlgorithm = signingAlgorithm; + } + + /** + * Returns the HTTP cryptographic algorithm which is used to sign HTTP requests. + */ public Algorithm getAlgorithm() { return algorithm; } /** - * Sets the HTTP signature algorithm which is used to sign HTTP requests. + * Sets the HTTP cryptographic algorithm which is used to sign HTTP requests. * * @param algorithm The HTTP signature algorithm. */ @@ -86,6 +121,22 @@ public class HttpSignatureAuth implements Authentication { this.algorithm = algorithm; } + /** + * Returns the cryptographic parameters which are used to sign HTTP requests. + */ + public AlgorithmParameterSpec getAlgorithmParameterSpec() { + return parameterSpec; + } + + /** + * Sets the cryptographic parameters which are used to sign HTTP requests. + * + * @param parameterSpec The cryptographic parameters. + */ + public void setAlgorithmParameterSpec(AlgorithmParameterSpec parameterSpec) { + this.parameterSpec = parameterSpec; + } + /** * Returns the digest algorithm which is used to calculate a cryptographic digest of the HTTP request body. * @@ -127,10 +178,20 @@ public class HttpSignatureAuth implements Authentication { this.headers = headers; } + /** + * Returns the signer instance used to sign HTTP messages. + * + * @returrn the signer instance. + */ public Signer getSigner() { return signer; } + /** + * Sets the signer instance used to sign HTTP messages. + * + * @param signer The signer instance to set. + */ public void setSigner(Signer signer) { this.signer = signer; } @@ -145,7 +206,7 @@ public class HttpSignatureAuth implements Authentication { throw new ApiException("Private key (java.security.Key) cannot be null"); } - signer = new Signer(key, new Signature(keyId, algorithm, null, headers)); + signer = new Signer(key, new Signature(keyId, signingAlgorithm, algorithm, parameterSpec, null, headers)); } @Override diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 9030427467c..707c3128484 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -385,7 +385,7 @@ 2.9.10 {{/threetenbp}} 4.13 - 1.3 + 1.4 {{#hasOAuthMethods}} 6.9.0 {{/hasOAuthMethods}} From 5cff579ee93e2b41a66c5ff4cf9d0ec9cdc7c9a4 Mon Sep 17 00:00:00 2001 From: Diogo Nunes Date: Wed, 20 May 2020 17:46:34 +0100 Subject: [PATCH 238/370] Use webclient exceptions in java webclient client (#6304) --- libraries/webclient/api.mustache | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libraries/webclient/api.mustache b/libraries/webclient/api.mustache index b852e87ec4e..7b3c23d59b4 100644 --- a/libraries/webclient/api.mustache +++ b/libraries/webclient/api.mustache @@ -15,10 +15,9 @@ import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestClientException; -import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.util.UriComponentsBuilder; import org.springframework.core.ParameterizedTypeReference; +import org.springframework.web.reactive.function.client.WebClientResponseException; import org.springframework.core.io.FileSystemResource; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -56,19 +55,19 @@ public class {{classname}} { {{#responses}} *

{{code}}{{#message}} - {{message}}{{/message}} {{/responses}}{{#allParams}} * @param {{paramName}} {{description}}{{^description}}The {{paramName}} parameter{{/description}} {{/allParams}}{{#returnType}} * @return {{returnType}} -{{/returnType}} * @throws RestClientException if an error occurs while attempting to invoke the API +{{/returnType}} * @throws WebClientResponseException if an error occurs while attempting to invoke the API {{#externalDocs}} * {{description}} * @see {{summary}} Documentation {{/externalDocs}} */ - public {{#returnType}}{{#isListContainer}}Flux<{{{returnBaseType}}}>{{/isListContainer}}{{^isListContainer}}Mono<{{{returnType}}}>{{/isListContainer}} {{/returnType}}{{^returnType}}Mono {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { + public {{#returnType}}{{#isListContainer}}Flux<{{{returnBaseType}}}>{{/isListContainer}}{{^isListContainer}}Mono<{{{returnType}}}>{{/isListContainer}} {{/returnType}}{{^returnType}}Mono {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws WebClientResponseException { Object postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}} {{#required}} // verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { - throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + throw new WebClientResponseException("Missing the required parameter '{{paramName}}' when calling {{operationId}}", HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.getReasonPhrase(), null, null, null); } {{/required}} {{/allParams}} From 613af35e9e8ce385763b440d3b4ea1b5e63ea6e4 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 22 May 2020 12:57:44 +0800 Subject: [PATCH 239/370] Add helper methods to determine if the spec has certain authentication defined (#6347) * better import, add security methods * add helper method to determine auth type when adding supporting files * better docstrings * fix boolean return * update tests * Revert "update tests" This reverts commit 29cfc8ad663234ee20c73ac7be9c4dd2235ac34f. * add test in shippable * rename variables * check if auth files are needed * update tests * revert check * set java8 to true * fix auth check * better npe handling * reoder methods * undo changes to shippable.yml --- libraries/jersey2/build.gradle.mustache | 4 ++++ libraries/jersey2/build.sbt.mustache | 2 ++ libraries/jersey2/pom.mustache | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index 90843185f55..270585b5b28 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -137,7 +137,9 @@ ext { {{#hasOAuthMethods}} scribejava_apis_version = "6.9.0" {{/hasOAuthMethods}} + {{#hasHttpBasicMethods}} tomitribe_http_signatures_version = "1.3" + {{/hasHttpBasicMethods}} } dependencies { @@ -159,7 +161,9 @@ dependencies { {{#hasOAuthMethods}} compile "com.github.scribejava:scribejava-apis:$scribejava_apis_version" {{/hasOAuthMethods}} + {{#hasHttpBasicMethods}} compile "org.tomitribe:tomitribe-http-signatures:$tomitribe_http_signatures_version" + {{/hasHttpBasicMethods}} {{#supportJava6}} compile "commons-io:commons-io:$commons_io_version" compile "org.apache.commons:commons-lang3:$commons_lang3_version" diff --git a/libraries/jersey2/build.sbt.mustache b/libraries/jersey2/build.sbt.mustache index e179fc9054a..4cb53ac02e2 100644 --- a/libraries/jersey2/build.sbt.mustache +++ b/libraries/jersey2/build.sbt.mustache @@ -28,7 +28,9 @@ lazy val root = (project in file(".")). {{#hasOAuthMethods}} "com.github.scribejava" % "scribejava-apis" % "6.9.0" % "compile", {{/hasOAuthMethods}} + {{#hasHttpBasicMethods}} "org.tomitribe" % "tomitribe-http-signatures" % "1.3" % "compile", + {{/hasHttpBasicMethods}} {{^java8}} "com.brsanthu" % "migbase64" % "2.2", {{/java8}} diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 707c3128484..d186a51fb98 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -338,11 +338,13 @@ ${commons-io-version} {{/supportJava6}} + {{#hasHttpBasicMethods}} org.tomitribe tomitribe-http-signatures ${http-signature-version} + {{/hasHttpBasicMethods}} {{#hasOAuthMethods}} com.github.scribejava @@ -385,7 +387,9 @@ 2.9.10 {{/threetenbp}} 4.13 + {{#hasHttpBasicMethods}} 1.4 + {{/hasHttpBasicMethods}} {{#hasOAuthMethods}} 6.9.0 {{/hasOAuthMethods}} From e0d4ae70ded47c53407342124638877457e20d9e Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Fri, 22 May 2020 08:54:05 -0700 Subject: [PATCH 240/370] [Java-jersey2] Add new ApiClient constructor with auth objects (#6393) * Mustache template should use invokerPackage tag to generate import * Add new constructor for Java ApiClient * Add constructor with auth map --- libraries/jersey2/ApiClient.mustache | 46 +++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 41db79fc8e5..66fe2735584 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -152,7 +152,19 @@ public class ApiClient { protected DateFormat dateFormat; + /** + * Constructs a new ApiClient with default parameters. + */ public ApiClient() { + this(null); + } + + /** + * Constructs a new ApiClient with the specified authentication parameters. + * + * @param authMap A hash map containing authentication parameters. + */ + public ApiClient(Map authMap) { json = new JSON(); httpClient = buildHttpClient(debugging); @@ -163,23 +175,47 @@ public class ApiClient { // Setup authentications (key: authentication name, value: authentication). authentications = new HashMap(); + Authentication auth = null; {{#authMethods}} + if (authMap != null) { + auth = authMap.get("{{name}}"); + } {{#isBasic}} {{#isBasicBasic}} - authentications.put("{{name}}", new HttpBasicAuth()); + if (auth instanceof HttpBasicAuth) { + authentications.put("{{name}}", auth); + } else { + authentications.put("{{name}}", new HttpBasicAuth()); + } {{/isBasicBasic}} {{#isBasicBearer}} - authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}")); + if (auth instanceof HttpBearerAuth) { + authentications.put("{{name}}", auth); + } else { + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}")); + } {{/isBasicBearer}} {{#isHttpSignature}} - authentications.put("{{name}}", new HttpSignatureAuth("{{name}}", null, null)); + if (auth instanceof HttpSignatureAuth) { + authentications.put("{{name}}", auth); + } else { + authentications.put("{{name}}", null); + } {{/isHttpSignature}} {{/isBasic}} {{#isApiKey}} - authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}")); + if (auth instanceof ApiKeyAuth) { + authentications.put("{{name}}", auth); + } else { + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}")); + } {{/isApiKey}} {{#isOAuth}} - authentications.put("{{name}}", new OAuth(basePath, "{{tokenUrl}}")); + if (auth instanceof OAuth) { + authentications.put("{{name}}", auth); + } else { + authentications.put("{{name}}", new OAuth(basePath, "{{tokenUrl}}")); + } {{/isOAuth}} {{/authMethods}} // Prevent the authentications from being modified. From ce872e0e2808d0439af2617600bb57aac987315b Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Sat, 23 May 2020 00:35:01 -0700 Subject: [PATCH 241/370] [Java] Fix mustache tag in pom template for HTTP signature (#6404) * Mustache template should use invokerPackage tag to generate import * Fix tag for http signature in pom.xml --- libraries/jersey2/pom.mustache | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index d186a51fb98..873fb95968d 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -338,13 +338,13 @@ ${commons-io-version} {{/supportJava6}} - {{#hasHttpBasicMethods}} + {{#hasHttpSignatureMethods}} org.tomitribe tomitribe-http-signatures ${http-signature-version} - {{/hasHttpBasicMethods}} + {{/hasHttpSignatureMethods}} {{#hasOAuthMethods}} com.github.scribejava @@ -387,9 +387,9 @@ 2.9.10 {{/threetenbp}} 4.13 - {{#hasHttpBasicMethods}} + {{#hasHttpSignatureMethods}} 1.4 - {{/hasHttpBasicMethods}} + {{/hasHttpSignatureMethods}} {{#hasOAuthMethods}} 6.9.0 {{/hasOAuthMethods}} From c3cb6fbd91363a5fb6d45d2b216c61826817754e Mon Sep 17 00:00:00 2001 From: Jon Freedman Date: Sat, 23 May 2020 11:36:03 +0100 Subject: [PATCH 242/370] [Java] Generate valid code if no Authentication implementations present (#5788) * generate valid code if no Authentication implementations present resurrects https://github.com/OpenAPITools/openapi-generator/pull/2861 * remove what I assume are human generated test cases * need to iterate over authMethods in order to pull out name * fix another test * update more tests * rename hasTokenAuthMethods to hasApiKeyAuthMethods * remove duplicate methods, fix hasHttpBearerMethods check * update templates * update windows java-petstore files * update windows java-petstore files * re-generate * re-generate * restore samples.ci tests * restore samples.ci tests --- ApiClient.mustache | 43 ++++-- libraries/resttemplate/ApiClient.mustache | 174 ++++++++++++---------- 2 files changed, 124 insertions(+), 93 deletions(-) diff --git a/ApiClient.mustache b/ApiClient.mustache index 8b71c1551e3..b2e3b198651 100644 --- a/ApiClient.mustache +++ b/ApiClient.mustache @@ -53,9 +53,15 @@ import java.io.UnsupportedEncodingException; import java.text.DateFormat; import {{invokerPackage}}.auth.Authentication; +{{#hasHttpBasicMethods}} import {{invokerPackage}}.auth.HttpBasicAuth; +{{/hasHttpBasicMethods}} +{{#hasHttpBearerMethods}} import {{invokerPackage}}.auth.HttpBearerAuth; +{{/hasHttpBearerMethods}} +{{#hasApiKeyMethods}} import {{invokerPackage}}.auth.ApiKeyAuth; +{{/hasApiKeyMethods}} {{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} @@ -267,6 +273,24 @@ public class ApiClient { return authentications.get(authName); } + {{#hasHttpBearerMethods}} + /** + * Helper method to set access token for the first Bearer authentication. + * @param bearerToken Bearer token + */ + public void setBearerToken(String bearerToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBearerAuth) { + ((HttpBearerAuth) auth).setBearerToken(bearerToken); + return; + } + } + throw new RuntimeException("No Bearer authentication configured!"); + } + + {{/hasHttpBearerMethods}} + + {{#hasHttpBasicMethods}} /** * Helper method to set username for the first HTTP basic authentication. * @param username Username @@ -295,6 +319,9 @@ public class ApiClient { throw new RuntimeException("No HTTP basic authentication configured!"); } + {{/hasHttpBasicMethods}} + + {{#hasApiKeyMethods}} /** * Helper method to set API key value for the first API key authentication. * @param apiKey the API key @@ -323,6 +350,8 @@ public class ApiClient { throw new RuntimeException("No API key authentication configured!"); } + {{/hasApiKeyMethods}} + {{#hasOAuthMethods}} /** * Helper method to set access token for the first OAuth2 authentication. @@ -340,20 +369,6 @@ public class ApiClient { {{/hasOAuthMethods}} - /** - * Helper method to set access token for the first Bearer authentication. - * @param bearerToken Bearer token - */ - public void setBearerToken(String bearerToken) { - for (Authentication auth : authentications.values()) { - if (auth instanceof HttpBearerAuth) { - ((HttpBearerAuth) auth).setBearerToken(bearerToken); - return; - } - } - throw new RuntimeException("No Bearer authentication configured!"); - } - /** * Set the User-Agent header's value (by adding to the default header map). * @param userAgent User agent diff --git a/libraries/resttemplate/ApiClient.mustache b/libraries/resttemplate/ApiClient.mustache index a2e66a62b61..f4add57c3e1 100644 --- a/libraries/resttemplate/ApiClient.mustache +++ b/libraries/resttemplate/ApiClient.mustache @@ -66,9 +66,15 @@ import java.util.Map.Entry; import java.util.TimeZone; import {{invokerPackage}}.auth.Authentication; +{{#hasHttpBasicMethods}} import {{invokerPackage}}.auth.HttpBasicAuth; +{{/hasHttpBasicMethods}} +{{#hasHttpBearerMethods}} import {{invokerPackage}}.auth.HttpBearerAuth; +{{/hasHttpBearerMethods}} +{{#hasApiKeyMethods}} import {{invokerPackage}}.auth.ApiKeyAuth; +{{/hasApiKeyMethods}} {{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} @@ -170,93 +176,103 @@ public class ApiClient { return authentications.get(authName); } - /** - * Helper method to set token for HTTP bearer authentication. - * @param bearerToken the token - */ - public void setBearerToken(String bearerToken) { - for (Authentication auth : authentications.values()) { - if (auth instanceof HttpBearerAuth) { - ((HttpBearerAuth) auth).setBearerToken(bearerToken); - return; - } + {{#hasHttpBearerMethods}} + /** + * Helper method to set token for HTTP bearer authentication. + * @param bearerToken the token + */ + public void setBearerToken(String bearerToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBearerAuth) { + ((HttpBearerAuth) auth).setBearerToken(bearerToken); + return; } - throw new RuntimeException("No Bearer authentication configured!"); } - - /** - * Helper method to set username for the first HTTP basic authentication. - * @param username the username - */ - public void setUsername(String username) { - for (Authentication auth : authentications.values()) { - if (auth instanceof HttpBasicAuth) { - ((HttpBasicAuth) auth).setUsername(username); - return; - } - } - throw new RuntimeException("No HTTP basic authentication configured!"); + throw new RuntimeException("No Bearer authentication configured!"); + } + + {{/hasHttpBearerMethods}} + + {{#hasHttpBasicMethods}} + /** + * Helper method to set username for the first HTTP basic authentication. + * @param username Username + */ + public void setUsername(String username) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setUsername(username); + return; + } } - - /** - * Helper method to set password for the first HTTP basic authentication. - * @param password the password - */ - public void setPassword(String password) { - for (Authentication auth : authentications.values()) { - if (auth instanceof HttpBasicAuth) { - ((HttpBasicAuth) auth).setPassword(password); - return; - } - } - throw new RuntimeException("No HTTP basic authentication configured!"); + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set password for the first HTTP basic authentication. + * @param password Password + */ + public void setPassword(String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setPassword(password); + return; + } } - - /** - * Helper method to set API key value for the first API key authentication. - * @param apiKey the API key - */ - public void setApiKey(String apiKey) { - for (Authentication auth : authentications.values()) { - if (auth instanceof ApiKeyAuth) { - ((ApiKeyAuth) auth).setApiKey(apiKey); - return; - } - } - throw new RuntimeException("No API key authentication configured!"); + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + {{/hasHttpBasicMethods}} + + {{#hasApiKeyMethods}} + /** + * Helper method to set API key value for the first API key authentication. + * @param apiKey the API key + */ + public void setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return; + } } - - /** - * Helper method to set API key prefix for the first API key authentication. - * @param apiKeyPrefix the API key prefix - */ - public void setApiKeyPrefix(String apiKeyPrefix) { - for (Authentication auth : authentications.values()) { - if (auth instanceof ApiKeyAuth) { - ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); - return; - } - } - throw new RuntimeException("No API key authentication configured!"); + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + * @param apiKeyPrefix API key prefix + */ + public void setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return; + } } - - {{#hasOAuthMethods}} - /** - * Helper method to set access token for the first OAuth2 authentication. - * @param accessToken the access token - */ - public void setAccessToken(String accessToken) { - for (Authentication auth : authentications.values()) { - if (auth instanceof OAuth) { - ((OAuth) auth).setAccessToken(accessToken); - return; - } - } - throw new RuntimeException("No OAuth2 authentication configured!"); + throw new RuntimeException("No API key authentication configured!"); + } + + {{/hasApiKeyMethods}} + + {{#hasOAuthMethods}} + /** + * Helper method to set access token for the first OAuth2 authentication. + * @param accessToken Access token + */ + public void setAccessToken(String accessToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setAccessToken(accessToken); + return; + } } + throw new RuntimeException("No OAuth2 authentication configured!"); + } - {{/hasOAuthMethods}} - /** + {{/hasOAuthMethods}} + + /** * Set the User-Agent header's value (by adding to the default header map). * @param userAgent the user agent string * @return ApiClient this client From 8abbb1f6e8e2740121d6405e8c645c9320c7ac87 Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Sat, 23 May 2020 14:32:06 -0700 Subject: [PATCH 243/370] [java-jersey2] Conditionally include http signature mustache template (#6413) --- libraries/jersey2/ApiClient.mustache | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 66fe2735584..362aee07d75 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -59,7 +59,9 @@ import java.util.regex.Pattern; import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; import {{invokerPackage}}.auth.HttpBearerAuth; +{{#hasHttpSignatureMethods}} import {{invokerPackage}}.auth.HttpSignatureAuth; +{{/hasHttpSignatureMethods}} import {{invokerPackage}}.auth.ApiKeyAuth; {{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; From a16e21abd8e6ffbc90b2222c86343e30a951852b Mon Sep 17 00:00:00 2001 From: Slavek Kabrda Date: Mon, 25 May 2020 09:17:52 +0200 Subject: [PATCH 244/370] [Java][jersey2] Make (de)serialization work for oneOf models, add convenience and comparison methods (#6323) --- .../jersey2/AbstractOpenApiSchema.mustache | 44 +++++++++++++++++ libraries/jersey2/oneof_model.mustache | 47 +++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/libraries/jersey2/AbstractOpenApiSchema.mustache b/libraries/jersey2/AbstractOpenApiSchema.mustache index c924650e6c0..f928aad9d75 100644 --- a/libraries/jersey2/AbstractOpenApiSchema.mustache +++ b/libraries/jersey2/AbstractOpenApiSchema.mustache @@ -3,10 +3,13 @@ package {{invokerPackage}}.model; import {{invokerPackage}}.ApiException; +import java.util.Objects; import java.lang.reflect.Type; import java.util.Map; import javax.ws.rs.core.GenericType; +import com.fasterxml.jackson.annotation.JsonValue; + /** * Abstract class for oneOf,anyOf schemas defined in OpenAPI spec */ @@ -39,6 +42,7 @@ public abstract class AbstractOpenApiSchema { * * @return an instance of the actual schema/object */ + @JsonValue public Object getActualInstance() {return instance;} /*** @@ -57,6 +61,46 @@ public abstract class AbstractOpenApiSchema { return schemaType; } + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ").append(getClass()).append(" {\n"); + sb.append(" instance: ").append(toIndentedString(instance)).append("\n"); + sb.append(" isNullable: ").append(toIndentedString(isNullable)).append("\n"); + sb.append(" schemaType: ").append(toIndentedString(schemaType)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AbstractOpenApiSchema a = (AbstractOpenApiSchema) o; + return Objects.equals(this.instance, a.instance) && + Objects.equals(this.isNullable, a.isNullable) && + Objects.equals(this.schemaType, a.schemaType); + } + + @Override + public int hashCode() { + return Objects.hash(instance, isNullable, schemaType); + } + /*** * Is nullalble * diff --git a/libraries/jersey2/oneof_model.mustache b/libraries/jersey2/oneof_model.mustache index ffd739dfdd8..a2a9b045814 100644 --- a/libraries/jersey2/oneof_model.mustache +++ b/libraries/jersey2/oneof_model.mustache @@ -1,11 +1,51 @@ import javax.ws.rs.core.GenericType; import javax.ws.rs.core.Response; +import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; + {{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} +@JsonDeserialize(using={{classname}}.{{classname}}Deserializer.class) public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}}, {{{.}}}{{/vendorExtensions.x-implements}} { + public static class {{classname}}Deserializer extends StdDeserializer<{{classname}}> { + public {{classname}}Deserializer() { + this({{classname}}.class); + } + + public {{classname}}Deserializer(Class vc) { + super(vc); + } + + @Override + public {{classname}} deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + JsonNode tree = jp.readValueAsTree(); + + int match = 0; + Object deserialized = null; + {{#oneOf}} + try { + deserialized = tree.traverse(jp.getCodec()).readValueAs({{{.}}}.class); + match++; + } catch (Exception e) { + // deserialization failed, continue + } + {{/oneOf}} + if (match == 1) { + {{classname}} ret = new {{classname}}(); + ret.setActualInstance(deserialized); + return ret; + } + throw new IOException(String.format("Failed deserialization for {{classname}}: %d classes match result, expected 1", match)); + } + } // store a list of schema names defined in oneOf public final static Map schemas = new HashMap(); @@ -14,6 +54,13 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); } + {{#oneOf}} + public {{classname}}({{{.}}} o) { + super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + setActualInstance(o); + } + {{/oneOf}} + static { {{#oneOf}} schemas.put("{{{.}}}", new GenericType<{{{.}}}>() { From ab8c3411622266f4608bee41de4646c19201100a Mon Sep 17 00:00:00 2001 From: William Cheng Date: Tue, 26 May 2020 10:26:25 +0800 Subject: [PATCH 245/370] [Java][jersey2] minor improvement to jersey2 tests (#6418) * minor improvement to jersey2 test, remove script/bat * remove tests for java7 jersey2 * remove log from abstrct java class * undo change to jaxrs path --- libraries/jersey2/api_test.mustache | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libraries/jersey2/api_test.mustache b/libraries/jersey2/api_test.mustache index 5ee6e494084..1c122287e8d 100644 --- a/libraries/jersey2/api_test.mustache +++ b/libraries/jersey2/api_test.mustache @@ -2,7 +2,8 @@ package {{package}}; -import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.*; +import {{invokerPackage}}.auth.*; {{#imports}}import {{import}}; {{/imports}} import org.junit.Test; @@ -23,7 +24,8 @@ public class {{classname}}Test { private final {{classname}} api = new {{classname}}(); - {{#operations}}{{#operation}} + {{#operations}} + {{#operation}} /** * {{summary}} * @@ -47,5 +49,7 @@ public class {{classname}}Test { {{/vendorExtensions.x-group-parameters}} // TODO: test validations } - {{/operation}}{{/operations}} + + {{/operation}} + {{/operations}} } From a671e84358cc5fc72f55bb324d31d85efab0e48d Mon Sep 17 00:00:00 2001 From: William Cheng Date: Tue, 26 May 2020 10:26:39 +0800 Subject: [PATCH 246/370] java jersey2 enhance anyOf (#6420) --- libraries/jersey2/anyof_model.mustache | 47 +++++++++++++++++++++++++- libraries/jersey2/oneof_model.mustache | 4 ++- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/libraries/jersey2/anyof_model.mustache b/libraries/jersey2/anyof_model.mustache index 0ce4e381f4a..f5d76fed53b 100644 --- a/libraries/jersey2/anyof_model.mustache +++ b/libraries/jersey2/anyof_model.mustache @@ -1,11 +1,49 @@ import javax.ws.rs.core.GenericType; import javax.ws.rs.core.Response; +import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; + {{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} +@JsonDeserialize(using={{classname}}.{{classname}}Deserializer.class) public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}}, {{{.}}}{{/vendorExtensions.x-implements}} { + public static class {{classname}}Deserializer extends StdDeserializer<{{classname}}> { + public {{classname}}Deserializer() { + this({{classname}}.class); + } + + public {{classname}}Deserializer(Class vc) { + super(vc); + } + + @Override + public {{classname}} deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + JsonNode tree = jp.readValueAsTree(); + + Object deserialized = null; + {{#anyOf}} + // deserialzie {{{.}}} + try { + deserialized = tree.traverse(jp.getCodec()).readValueAs({{{.}}}.class); + {{classname}} ret = new {{classname}}(); + ret.setActualInstance(deserialized); + return ret; + } catch (Exception e) { + // deserialization failed, continue + } + + {{/anyOf}} + throw new IOException(String.format("Failed deserialization for {{classname}}: no match found")); + } + } // store a list of schema names defined in anyOf public final static Map schemas = new HashMap(); @@ -14,6 +52,13 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im super("anyOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); } + {{#anyOf}} + public {{classname}}({{{.}}} o) { + super("anyOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + setActualInstance(o); + } + + {{/anyOf}} static { {{#anyOf}} schemas.put("{{{.}}}", new GenericType<{{{.}}}>() { @@ -42,6 +87,6 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im } {{/anyOf}} - throw new RuntimeException("Invalid instance type. Must be {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}"); + throw new RuntimeException("Invalid instance type. Must be {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}"); } } diff --git a/libraries/jersey2/oneof_model.mustache b/libraries/jersey2/oneof_model.mustache index a2a9b045814..b7523272c00 100644 --- a/libraries/jersey2/oneof_model.mustache +++ b/libraries/jersey2/oneof_model.mustache @@ -31,12 +31,14 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im int match = 0; Object deserialized = null; {{#oneOf}} + // deserialize {{{.}}} try { deserialized = tree.traverse(jp.getCodec()).readValueAs({{{.}}}.class); match++; } catch (Exception e) { // deserialization failed, continue } + {{/oneOf}} if (match == 1) { {{classname}} ret = new {{classname}}(); @@ -59,8 +61,8 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); setActualInstance(o); } - {{/oneOf}} + {{/oneOf}} static { {{#oneOf}} schemas.put("{{{.}}}", new GenericType<{{{.}}}>() { From d13c5f023039102473f5b6cc3bf589fea65a9b67 Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Thu, 28 May 2020 06:34:00 -0700 Subject: [PATCH 247/370] [Java][jersey2] Improve http signature code comments (#6463) * Mustache template should use invokerPackage tag to generate import * fix typo and improve code comments --- libraries/jersey2/auth/HttpSignatureAuth.mustache | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libraries/jersey2/auth/HttpSignatureAuth.mustache b/libraries/jersey2/auth/HttpSignatureAuth.mustache index 75adbdbba3f..3e1c0f0e7f7 100644 --- a/libraries/jersey2/auth/HttpSignatureAuth.mustache +++ b/libraries/jersey2/auth/HttpSignatureAuth.mustache @@ -181,7 +181,7 @@ public class HttpSignatureAuth implements Authentication { /** * Returns the signer instance used to sign HTTP messages. * - * @returrn the signer instance. + * @return the signer instance. */ public Signer getSigner() { return signer; @@ -200,12 +200,14 @@ public class HttpSignatureAuth implements Authentication { * Set the private key used to sign HTTP requests using the HTTP signature scheme. * * @param key The private key. + * + * @throws InvalidKeyException Unable to parse the key, or the security provider for this key + * is not installed. */ - public void setPrivateKey(Key key) throws ApiException { + public void setPrivateKey(Key key) throws InvalidKeyException { if (key == null) { throw new ApiException("Private key (java.security.Key) cannot be null"); } - signer = new Signer(key, new Signature(keyId, signingAlgorithm, algorithm, parameterSpec, null, headers)); } From 785d496c62368a5cd7ccd0577f0b8164033604bc Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Thu, 28 May 2020 06:35:16 -0700 Subject: [PATCH 248/370] [Java][jersey2] Fix RuntimeException when HTTP signature parameters are not configured (#6457) * Mustache template should use invokerPackage tag to generate import * fix runtime exception when HttpSignatureAuth is not set * fix runtime exception when HttpSignatureAuth is not set --- libraries/jersey2/ApiClient.mustache | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 362aee07d75..8d12c42630d 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -200,8 +200,6 @@ public class ApiClient { {{#isHttpSignature}} if (auth instanceof HttpSignatureAuth) { authentications.put("{{name}}", auth); - } else { - authentications.put("{{name}}", null); } {{/isHttpSignature}} {{/isBasic}} @@ -246,10 +244,20 @@ public class ApiClient { return this; } + /** + * Returns the base URL to the location where the OpenAPI document is being served. + * + * @return The base URL to the target host. + */ public String getBasePath() { return basePath; } + /** + * Sets the base URL to the location where the OpenAPI document is being served. + * + * @param basePath The base URL to the target host. + */ public ApiClient setBasePath(String basePath) { this.basePath = basePath; {{#hasOAuthMethods}} @@ -1281,7 +1289,7 @@ public class ApiClient { for (String authName : authNames) { Authentication auth = authentications.get(authName); if (auth == null) { - throw new RuntimeException("Authentication undefined: " + authName); + continue; } auth.applyToParams(queryParams, headerParams, cookieParams, payload, method, uri); } From 186ea087ad6f76e2a7afa0cb9c4a3c035a0c6cef Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Sun, 31 May 2020 07:45:01 -0700 Subject: [PATCH 249/370] [Java][Jersey2] Fix typo and script, Log enhancements, HTTP signature, deserialization (#6476) * Mustache template should use invokerPackage tag to generate import * fix typo, fix script issue, add log statement for troubleshooting * Add java jersey2 samples with OpenAPI doc that has HTTP signature security scheme * Add sample for Java jersey2 and HTTP signature scheme * Add unit test for oneOf schema deserialization * Add unit test for oneOf schema deserialization * Add log statements * Add profile for jersey2 * Temporarily disable unit test * Temporarily disable unit test * fix typo in pom.xml * fix duplicate jersey2 samples * fix duplicate jersey2 samples * fix duplicate artifact id * fix duplicate jersey2 samples * run samples scripts --- libraries/jersey2/ApiClient.mustache | 9 ++++++++- libraries/jersey2/anyof_model.mustache | 7 ++++++- libraries/jersey2/auth/HttpSignatureAuth.mustache | 3 ++- libraries/jersey2/oneof_model.mustache | 6 ++++++ 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 8d12c42630d..d6ff3f94e0b 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -36,6 +36,8 @@ import org.glassfish.jersey.logging.LoggingFeature; import org.apache.commons.io.FileUtils; import org.glassfish.jersey.filter.LoggingFilter; {{/supportJava6}} +import java.util.logging.Level; +import java.util.logging.Logger; import java.util.Collection; import java.util.Collections; import java.util.Map; @@ -73,6 +75,8 @@ public class ApiClient { protected Map defaultHeaderMap = new HashMap(); protected Map defaultCookieMap = new HashMap(); protected String basePath = "{{{basePath}}}"; + private static final Logger log = Logger.getLogger(ApiClient.class.getName()); + protected List servers = new ArrayList({{#servers}}{{#-first}}Arrays.asList( {{/-first}} new ServerConfiguration( "{{{url}}}", @@ -928,6 +932,9 @@ public class ApiClient { } } catch (Exception ex) { // failed to deserialize, do nothing and try next one (schema) + // Logging the error may be useful to troubleshoot why a payload fails to match + // the schema. + log.log(Level.FINE, "Input data does not match schema '" + schemaName + "'", ex); } } else {// unknown type throw new ApiException(schemaType.getClass() + " is not a GenericType and cannot be handled properly in deserialization."); @@ -938,7 +945,7 @@ public class ApiClient { if (matchCounter > 1 && "oneOf".equals(schema.getSchemaType())) {// more than 1 match for oneOf throw new ApiException("Response body is invalid as it matches more than one schema (" + StringUtil.join(matchSchemas, ", ") + ") defined in the oneOf model: " + schema.getClass().getName()); } else if (matchCounter == 0) { // fail to match any in oneOf/anyOf schemas - throw new ApiException("Response body is invalid as it doens't match any schemas (" + StringUtil.join(schema.getSchemas().keySet(), ", ") + ") defined in the oneOf/anyOf model: " + schema.getClass().getName()); + throw new ApiException("Response body is invalid as it does not match any schemas (" + StringUtil.join(schema.getSchemas().keySet(), ", ") + ") defined in the oneOf/anyOf model: " + schema.getClass().getName()); } else { // only one matched schema.setActualInstance(result); return schema; diff --git a/libraries/jersey2/anyof_model.mustache b/libraries/jersey2/anyof_model.mustache index f5d76fed53b..5c3219b5de3 100644 --- a/libraries/jersey2/anyof_model.mustache +++ b/libraries/jersey2/anyof_model.mustache @@ -1,6 +1,8 @@ import javax.ws.rs.core.GenericType; import javax.ws.rs.core.Response; import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -15,6 +17,8 @@ import com.fasterxml.jackson.databind.deser.std.StdDeserializer; {{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} @JsonDeserialize(using={{classname}}.{{classname}}Deserializer.class) public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}}, {{{.}}}{{/vendorExtensions.x-implements}} { + private static final Logger log = Logger.getLogger({{classname}}.class.getName()); + public static class {{classname}}Deserializer extends StdDeserializer<{{classname}}> { public {{classname}}Deserializer() { this({{classname}}.class); @@ -37,7 +41,8 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im ret.setActualInstance(deserialized); return ret; } catch (Exception e) { - // deserialization failed, continue + // deserialization failed, continue, log to help debugging + log.log(Level.FINER, "Input data does not match '{{classname}}'", e); } {{/anyOf}} diff --git a/libraries/jersey2/auth/HttpSignatureAuth.mustache b/libraries/jersey2/auth/HttpSignatureAuth.mustache index 3e1c0f0e7f7..c978de46a0f 100644 --- a/libraries/jersey2/auth/HttpSignatureAuth.mustache +++ b/libraries/jersey2/auth/HttpSignatureAuth.mustache @@ -17,6 +17,7 @@ import java.util.Locale; import java.util.Map; import java.util.List; import java.security.spec.AlgorithmParameterSpec; +import java.security.InvalidKeyException; import org.tomitribe.auth.signatures.Algorithm; import org.tomitribe.auth.signatures.Signer; @@ -204,7 +205,7 @@ public class HttpSignatureAuth implements Authentication { * @throws InvalidKeyException Unable to parse the key, or the security provider for this key * is not installed. */ - public void setPrivateKey(Key key) throws InvalidKeyException { + public void setPrivateKey(Key key) throws InvalidKeyException, ApiException { if (key == null) { throw new ApiException("Private key (java.security.Key) cannot be null"); } diff --git a/libraries/jersey2/oneof_model.mustache b/libraries/jersey2/oneof_model.mustache index b7523272c00..fec28f2e2dc 100644 --- a/libraries/jersey2/oneof_model.mustache +++ b/libraries/jersey2/oneof_model.mustache @@ -1,6 +1,8 @@ import javax.ws.rs.core.GenericType; import javax.ws.rs.core.Response; import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -15,6 +17,8 @@ import com.fasterxml.jackson.databind.deser.std.StdDeserializer; {{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} @JsonDeserialize(using={{classname}}.{{classname}}Deserializer.class) public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}}, {{{.}}}{{/vendorExtensions.x-implements}} { + private static final Logger log = Logger.getLogger({{classname}}.class.getName()); + public static class {{classname}}Deserializer extends StdDeserializer<{{classname}}> { public {{classname}}Deserializer() { this({{classname}}.class); @@ -35,8 +39,10 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im try { deserialized = tree.traverse(jp.getCodec()).readValueAs({{{.}}}.class); match++; + log.log(Level.FINER, "Input data matches schema '{{{.}}}'"); } catch (Exception e) { // deserialization failed, continue + log.log(Level.FINER, "Input data does not match schema '{{{.}}}'", e); } {{/oneOf}} From bc0a229646dbc68eb077953555fe170eee5824fd Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 10 Jun 2020 00:38:11 +0800 Subject: [PATCH 250/370] [Java][Jersey2] various improvements (#6518) * [java][jersey2] Add support for discriminator, fix nullable typo and nullable deserialization (#6495) * Mustache template should use invokerPackage tag to generate import * fix typo, fix script issue, add log statement for troubleshooting * Add java jersey2 samples with OpenAPI doc that has HTTP signature security scheme * Add sample for Java jersey2 and HTTP signature scheme * Add unit test for oneOf schema deserialization * Add unit test for oneOf schema deserialization * Add log statements * Add profile for jersey2 * Temporarily disable unit test * Temporarily disable unit test * support for discriminator in jersey2 * fix typo in pom.xml * disable unit test because jersey2 deserialization is broken * disable unit test because jersey2 deserialization is broken * fix duplicate jersey2 samples * fix duplicate jersey2 samples * Add code comments * fix duplicate artifact id * fix duplicate jersey2 samples * run samples scripts * resolve merge conflicts * Add unit tests * fix unit tests * continue implementation of discriminator lookup * throw deserialization exception when value is null and schema does not allow null value * continue implementation of compose schema * continue implementation of compose schema * continue implementation of compose schema * Add more unit tests * Add unit tests for anyOf * Add unit tests Co-authored-by: Vikrant Balyan (vvb) * update samples * add tests to oas3 java jersey2 petstore * comment out jersey2 ensure uptodate * Jersey2 supports additional properties with composed schema (#6523) * Mustache template should use invokerPackage tag to generate import * fix typo, fix script issue, add log statement for troubleshooting * Add java jersey2 samples with OpenAPI doc that has HTTP signature security scheme * Add sample for Java jersey2 and HTTP signature scheme * Add unit test for oneOf schema deserialization * Add unit test for oneOf schema deserialization * Add log statements * Add profile for jersey2 * Temporarily disable unit test * Temporarily disable unit test * support for discriminator in jersey2 * fix typo in pom.xml * disable unit test because jersey2 deserialization is broken * disable unit test because jersey2 deserialization is broken * fix duplicate jersey2 samples * fix duplicate jersey2 samples * Add code comments * fix duplicate artifact id * fix duplicate jersey2 samples * run samples scripts * resolve merge conflicts * Add unit tests * fix unit tests * continue implementation of discriminator lookup * throw deserialization exception when value is null and schema does not allow null value * continue implementation of compose schema * continue implementation of compose schema * continue implementation of compose schema * Add more unit tests * Add unit tests for anyOf * Add unit tests * Set supportsAdditionalPropertiesWithComposedSchema to true for Java jersey2 * Support additional properties as nested field * Support additional properties as nested field * add code comments * add customer deserializer * Fix 'method too big' error with generated code * resolve merge conflicts Co-authored-by: Vikrant Balyan (vvb) * [Jersey2] Fix code generation of 'registerDiscriminator' method for large models (#6535) * Mustache template should use invokerPackage tag to generate import * fix typo, fix script issue, add log statement for troubleshooting * Add java jersey2 samples with OpenAPI doc that has HTTP signature security scheme * Add sample for Java jersey2 and HTTP signature scheme * Add unit test for oneOf schema deserialization * Add unit test for oneOf schema deserialization * Add log statements * Add profile for jersey2 * Temporarily disable unit test * Temporarily disable unit test * support for discriminator in jersey2 * fix typo in pom.xml * disable unit test because jersey2 deserialization is broken * disable unit test because jersey2 deserialization is broken * fix duplicate jersey2 samples * fix duplicate jersey2 samples * Add code comments * fix duplicate artifact id * fix duplicate jersey2 samples * run samples scripts * resolve merge conflicts * Add unit tests * fix unit tests * continue implementation of discriminator lookup * throw deserialization exception when value is null and schema does not allow null value * continue implementation of compose schema * continue implementation of compose schema * continue implementation of compose schema * Add more unit tests * Add unit tests for anyOf * Add unit tests * Fix 'method too big' error with generated code * resolve merge conflicts Co-authored-by: Vikrant Balyan (vvb) * update samples * comment out tests * support additional properties in serialize and deserialize * add discriminator lookup * remove oneof/anyof logic in apilcient * add serializer to mammal.java * add serialize to oneOf model * add serializer to anyof model * comment out test cases that are subject to further discussion * add back files * update configs, samples Co-authored-by: Sebastien Rosset Co-authored-by: Vikrant Balyan (vvb) --- .../jersey2/AbstractOpenApiSchema.mustache | 15 +- libraries/jersey2/ApiClient.mustache | 78 +------ libraries/jersey2/JSON.mustache | 202 +++++++++++++++++- .../jersey2/additional_properties.mustache | 39 ++++ libraries/jersey2/anyof_model.mustache | 101 ++++++++- libraries/jersey2/api.mustache | 2 +- libraries/jersey2/api_test.mustache | 5 +- libraries/jersey2/model.mustache | 19 ++ libraries/jersey2/oneof_model.mustache | 120 ++++++++++- libraries/jersey2/pojo.mustache | 29 ++- libraries/jersey2/pom.mustache | 1 + 11 files changed, 512 insertions(+), 99 deletions(-) create mode 100644 libraries/jersey2/additional_properties.mustache diff --git a/libraries/jersey2/AbstractOpenApiSchema.mustache b/libraries/jersey2/AbstractOpenApiSchema.mustache index f928aad9d75..e824f44ae3f 100644 --- a/libraries/jersey2/AbstractOpenApiSchema.mustache +++ b/libraries/jersey2/AbstractOpenApiSchema.mustache @@ -30,14 +30,14 @@ public abstract class AbstractOpenApiSchema { this.isNullable = isNullable; } - /*** - * Get the list of schemas allowed to be stored in this object + /** + * Get the list of oneOf/anyOf composed schemas allowed to be stored in this object * * @return an instance of the actual schema/object */ public abstract Map getSchemas(); - /*** + /** * Get the actual instance * * @return an instance of the actual schema/object @@ -45,14 +45,14 @@ public abstract class AbstractOpenApiSchema { @JsonValue public Object getActualInstance() {return instance;} - /*** + /** * Set the actual instance * * @param instance the actual instance of the schema/object */ public void setActualInstance(Object instance) {this.instance = instance;} - /*** + /** * Get the schema type (e.g. anyOf, oneOf) * * @return the schema type @@ -101,7 +101,7 @@ public abstract class AbstractOpenApiSchema { return Objects.hash(instance, isNullable, schemaType); } - /*** + /** * Is nullalble * * @return true if it's nullable @@ -113,4 +113,7 @@ public abstract class AbstractOpenApiSchema { return Boolean.FALSE; } } + +{{>libraries/jersey2/additional_properties}} + } diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index d6ff3f94e0b..1b2b63c9abe 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -68,7 +68,6 @@ import {{invokerPackage}}.auth.ApiKeyAuth; {{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} -import {{invokerPackage}}.model.AbstractOpenApiSchema; {{>generatedAnnotation}} public class ApiClient { @@ -894,67 +893,6 @@ public class ApiClient { } } - public AbstractOpenApiSchema deserializeSchemas(Response response, AbstractOpenApiSchema schema) throws ApiException{ - - Object result = null; - int matchCounter = 0; - ArrayList matchSchemas = new ArrayList<>(); - - if (schema.isNullable()) { - response.bufferEntity(); - if ("{}".equals(String.valueOf(response.readEntity(String.class))) || - "".equals(String.valueOf(response.readEntity(String.class)))) { - // schema is nullable and the response body is {} or empty string - return schema; - } - } - - for (Map.Entry entry : schema.getSchemas().entrySet()) { - String schemaName = entry.getKey(); - GenericType schemaType = entry.getValue(); - - if (schemaType instanceof GenericType) { // model - try { - Object deserializedObject = deserialize(response, schemaType); - if (deserializedObject != null) { - result = deserializedObject; - matchCounter++; - - if ("anyOf".equals(schema.getSchemaType())) { - break; - } else if ("oneOf".equals(schema.getSchemaType())) { - matchSchemas.add(schemaName); - } else { - throw new ApiException("Unknowe type found while expecting anyOf/oneOf:" + schema.getSchemaType()); - } - } else { - // failed to deserialize the response in the schema provided, proceed to the next one if any - } - } catch (Exception ex) { - // failed to deserialize, do nothing and try next one (schema) - // Logging the error may be useful to troubleshoot why a payload fails to match - // the schema. - log.log(Level.FINE, "Input data does not match schema '" + schemaName + "'", ex); - } - } else {// unknown type - throw new ApiException(schemaType.getClass() + " is not a GenericType and cannot be handled properly in deserialization."); - } - - } - - if (matchCounter > 1 && "oneOf".equals(schema.getSchemaType())) {// more than 1 match for oneOf - throw new ApiException("Response body is invalid as it matches more than one schema (" + StringUtil.join(matchSchemas, ", ") + ") defined in the oneOf model: " + schema.getClass().getName()); - } else if (matchCounter == 0) { // fail to match any in oneOf/anyOf schemas - throw new ApiException("Response body is invalid as it does not match any schemas (" + StringUtil.join(schema.getSchemas().keySet(), ", ") + ") defined in the oneOf/anyOf model: " + schema.getClass().getName()); - } else { // only one matched - schema.setActualInstance(result); - return schema; - } - - } - - - /** * Deserialize response body to Java object according to the Content-Type. * @param Type @@ -1062,7 +1000,6 @@ public class ApiClient { * @param contentType The request's Content-Type header * @param authNames The authentications to apply * @param returnType The return type into which to deserialize the response - * @param schema An instance of the response that uses oneOf/anyOf * @return The response body in type of string * @throws ApiException API exception */ @@ -1078,8 +1015,7 @@ public class ApiClient { String accept, String contentType, String[] authNames, - GenericType returnType, - AbstractOpenApiSchema schema) + GenericType returnType) throws ApiException { // Not using `.target(targetURL).path(path)` below, @@ -1178,12 +1114,10 @@ public class ApiClient { if (response.getStatusInfo() == Status.NO_CONTENT) { return new ApiResponse(statusCode, responseHeaders); } else if (response.getStatusInfo().getFamily() == Status.Family.SUCCESSFUL) { - if (returnType == null) return new ApiResponse(statusCode, responseHeaders); - else if (schema == null) { + if (returnType == null) { + return new ApiResponse(statusCode, responseHeaders); + } else { return new ApiResponse(statusCode, responseHeaders, deserialize(response, returnType)); - } else { // oneOf/anyOf - return new ApiResponse( - statusCode, responseHeaders, (T) deserializeSchemas(response, schema)); } } else { String message = "error"; @@ -1229,8 +1163,8 @@ public class ApiClient { * @deprecated Add qualified name of the operation as a first parameter. */ @Deprecated - public ApiResponse invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType, AbstractOpenApiSchema schema) throws ApiException { - return invokeAPI(null, path, method, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType, schema); + public ApiResponse invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { + return invokeAPI(null, path, method, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType); } /** diff --git a/libraries/jersey2/JSON.mustache b/libraries/jersey2/JSON.mustache index dc3d9893e6d..3d3339c5d6b 100644 --- a/libraries/jersey2/JSON.mustache +++ b/libraries/jersey2/JSON.mustache @@ -15,9 +15,16 @@ import com.fasterxml.jackson.datatype.joda.JodaModule; {{#threetenbp}} import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; {{/threetenbp}} +{{#models.0}} +import {{modelPackage}}.*; +{{/models.0}} import java.text.DateFormat; - +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.ws.rs.core.GenericType; import javax.ws.rs.ext.ContextResolver; {{>generatedAnnotation}} @@ -69,4 +76,197 @@ public class JSON implements ContextResolver { * @return object mapper */ public ObjectMapper getMapper() { return mapper; } + + /** + * Returns the target model class that should be used to deserialize the input data. + * The discriminator mappings are used to determine the target model class. + * + * @param node The input data. + * @param modelClass The class that contains the discriminator mappings. + */ + public static Class getClassForElement(JsonNode node, Class modelClass) { + ClassDiscriminatorMapping cdm = modelDiscriminators.get(modelClass); + if (cdm != null) { + return cdm.getClassForElement(node, new HashSet()); + } + return null; + } + + /** + * Helper class to register the discriminator mappings. + */ + private static class ClassDiscriminatorMapping { + // The model class name. + Class modelClass; + // The name of the discriminator property. + String discriminatorName; + // The discriminator mappings for a model class. + Map discriminatorMappings; + + // Constructs a new class discriminator. + ClassDiscriminatorMapping(Class cls, String propertyName, Map mappings) { + modelClass = cls; + discriminatorName = propertyName; + discriminatorMappings = new HashMap(); + if (mappings != null) { + discriminatorMappings.putAll(mappings); + } + } + + // Return the name of the discriminator property for this model class. + String getDiscriminatorPropertyName() { + return discriminatorName; + } + + // Return the discriminator value or null if the discriminator is not + // present in the payload. + String getDiscriminatorValue(JsonNode node) { + // Determine the value of the discriminator property in the input data. + if (discriminatorName != null) { + // Get the value of the discriminator property, if present in the input payload. + node = node.get(discriminatorName); + if (node != null && node.isValueNode()) { + String discrValue = node.asText(); + if (discrValue != null) { + return discrValue; + } + } + } + return null; + } + + /** + * Returns the target model class that should be used to deserialize the input data. + * This function can be invoked for anyOf/oneOf composed models with discriminator mappings. + * The discriminator mappings are used to determine the target model class. + * + * @param node The input data. + * @param visitedClasses The set of classes that have already been visited. + */ + Class getClassForElement(JsonNode node, Set visitedClasses) { + if (visitedClasses.contains(modelClass)) { + // Class has already been visited. + return null; + } + // Determine the value of the discriminator property in the input data. + String discrValue = getDiscriminatorValue(node); + if (discrValue == null) { + return null; + } + Class cls = discriminatorMappings.get(discrValue); + // It may not be sufficient to return this cls directly because that target class + // may itself be a composed schema, possibly with its own discriminator. + visitedClasses.add(modelClass); + for (Class childClass : discriminatorMappings.values()) { + ClassDiscriminatorMapping childCdm = modelDiscriminators.get(childClass); + if (childCdm == null) { + continue; + } + if (!discriminatorName.equals(childCdm.discriminatorName)) { + discrValue = getDiscriminatorValue(node); + if (discrValue == null) { + continue; + } + } + if (childCdm != null) { + // Recursively traverse the discriminator mappings. + Class childDiscr = childCdm.getClassForElement(node, visitedClasses); + if (childDiscr != null) { + return childDiscr; + } + } + } + return cls; + } + } + + /** + * Returns true if inst is an instance of modelClass in the OpenAPI model hierarchy. + * + * The Java class hierarchy is not implemented the same way as the OpenAPI model hierarchy, + * so it's not possible to use the instanceof keyword. + * + * @param modelClass A OpenAPI model class. + * @param inst The instance object. + */ + public static boolean isInstanceOf(Class modelClass, Object inst, Set visitedClasses) { + if (modelClass.isInstance(inst)) { + // This handles the 'allOf' use case with single parent inheritance. + return true; + } + if (visitedClasses.contains(modelClass)) { + // This is to prevent infinite recursion when the composed schemas have + // a circular dependency. + return false; + } + visitedClasses.add(modelClass); + + // Traverse the oneOf/anyOf composed schemas. + Map descendants = modelDescendants.get(modelClass); + if (descendants != null) { + for (GenericType childType : descendants.values()) { + if (isInstanceOf(childType.getRawType(), inst, visitedClasses)) { + return true; + } + } + } + return false; + } + + /** + * A map of discriminators for all model classes. + */ + private static Map modelDiscriminators = new HashMap(); + + /** + * A map of oneOf/anyOf descendants for each model class. + */ + private static Map> modelDescendants = new HashMap>(); + + /** + * Register a model class discriminator. + * + * @param modelClass the model class + * @param discriminatorPropertyName the name of the discriminator property + * @param mappings a map with the discriminator mappings. + */ + public static void registerDiscriminator(Class modelClass, String discriminatorPropertyName, Map mappings) { + ClassDiscriminatorMapping m = new ClassDiscriminatorMapping(modelClass, discriminatorPropertyName, mappings); + modelDiscriminators.put(modelClass, m); + } + + /** + * Register the oneOf/anyOf descendants of the modelClass. + * + * @param modelClass the model class + * @param descendants a map of oneOf/anyOf descendants. + */ + public static void registerDescendants(Class modelClass, Map descendants) { + modelDescendants.put(modelClass, descendants); + } + + private static JSON json; + + static + { + json = new JSON(); + } + + /** + * Get the default JSON instance. + * + * @return the default JSON instance + */ + public static JSON getDefault() { + return json; + } + + /** + * Set the default JSON instance. + * + * @param json JSON instance to be used + */ + public static void setDefault(JSON json) { + JSON.json = json; + } } diff --git a/libraries/jersey2/additional_properties.mustache b/libraries/jersey2/additional_properties.mustache new file mode 100644 index 00000000000..61973dc24fa --- /dev/null +++ b/libraries/jersey2/additional_properties.mustache @@ -0,0 +1,39 @@ +{{#additionalPropertiesType}} + /** + * A container for additional, undeclared properties. + * This is a holder for any undeclared properties as specified with + * the 'additionalProperties' keyword in the OAS document. + */ + private Map additionalProperties; + + /** + * Set the additional (undeclared) property with the specified name and value. + * If the property does not already exist, create it otherwise replace it. + */ + @JsonAnySetter + public {{classname}} putAdditionalProperty(String key, {{{.}}} value) { + if (this.additionalProperties == null) { + this.additionalProperties = new HashMap(); + } + this.additionalProperties.put(key, value); + return this; + } + + /** + * Return the additional (undeclared) property. + */ + @JsonAnyGetter + public Map getAdditionalProperties() { + return additionalProperties; + } + + /** + * Return the additional (undeclared) property with the specified name. + */ + public {{{.}}} getAdditionalProperty(String key) { + if (this.additionalProperties == null) { + return null; + } + return this.additionalProperties.get(key); + } +{{/additionalPropertiesType}} diff --git a/libraries/jersey2/anyof_model.mustache b/libraries/jersey2/anyof_model.mustache index 5c3219b5de3..a40ad85777a 100644 --- a/libraries/jersey2/anyof_model.mustache +++ b/libraries/jersey2/anyof_model.mustache @@ -4,21 +4,44 @@ import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; +import java.util.Collections; +import java.util.HashSet; +import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import org.openapitools.client.JSON; {{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} @JsonDeserialize(using={{classname}}.{{classname}}Deserializer.class) +@JsonSerialize(using = {{classname}}.{{classname}}Serializer.class) public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}}, {{{.}}}{{/vendorExtensions.x-implements}} { private static final Logger log = Logger.getLogger({{classname}}.class.getName()); + public static class {{classname}}Serializer extends StdSerializer<{{classname}}> { + public {{classname}}Serializer(Class<{{classname}}> t) { + super(t); + } + + public {{classname}}Serializer() { + this(null); + } + + @Override + public void serialize({{classname}} value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeObject(value.getActualInstance()); + } + } + public static class {{classname}}Deserializer extends StdDeserializer<{{classname}}> { public {{classname}}Deserializer() { this({{classname}}.class); @@ -33,6 +56,18 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im JsonNode tree = jp.readValueAsTree(); Object deserialized = null; + {{#discriminator}} + Class cls = JSON.getClassForElement(tree, {{classname}}.class); + if (cls != null) { + // When the OAS schema includes a discriminator, use the discriminator value to + // discriminate the anyOf schemas. + // Get the discriminator mapping value to get the class. + deserialized = tree.traverse(jp.getCodec()).readValueAs(cls); + {{classname}} ret = new {{classname}}(); + ret.setActualInstance(deserialized); + return ret; + } + {{/discriminator}} {{#anyOf}} // deserialzie {{{.}}} try { @@ -48,6 +83,41 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im {{/anyOf}} throw new IOException(String.format("Failed deserialization for {{classname}}: no match found")); } + + {{#additionalPropertiesType}} + /** + * Method called to deal with a property that did not map to a known Bean property. + * Method can deal with the problem as it sees fit (ignore, throw exception); but if it does return, + * it has to skip the matching Json content parser has. + * + * @param p - Parser that points to value of the unknown property + * @param ctxt - Context for deserialization; allows access to the parser, error reporting functionality + * @param instanceOrClass - Instance that is being populated by this deserializer, or if not known, Class that would be instantiated. If null, will assume type is what getValueClass() returns. + * @param propName - Name of the property that cannot be mapped + */ + @Override + protected void handleUnknownProperty(JsonParser p, + DeserializationContext ctxt, + Object instanceOrClass, + String propName) throws IOException { + System.out.println("Deserializing unknown property " + propName); + {{{.}}} deserialized = p.readValueAs({{{.}}}.class); + additionalProperties.put(propName, deserialized); + } + {{/additionalPropertiesType}} + + /** + * Handle deserialization of the 'null' value. + */ + @Override + public {{classname}} getNullValue(DeserializationContext ctxt) throws JsonMappingException { + {{#isNullable}} + return null; + {{/isNullable}} + {{^isNullable}} + throw new JsonMappingException("{{classname}} cannot be null"); + {{/isNullable}} + } } // store a list of schema names defined in anyOf @@ -56,7 +126,18 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im public {{classname}}() { super("anyOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); } +{{> libraries/jersey2/additional_properties }} + {{#additionalPropertiesType}} + @Override + public boolean equals(Object o) { + return super.equals(o) && Objects.equals(this.additionalProperties, o.additionalProperties) + } + @Override + public int hashCode() { + return Objects.hash(instance, isNullable, schemaType, additionalProperties); + } + {{/additionalPropertiesType}} {{#anyOf}} public {{classname}}({{{.}}} o) { super("anyOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); @@ -69,6 +150,16 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im schemas.put("{{{.}}}", new GenericType<{{{.}}}>() { }); {{/anyOf}} + JSON.registerDescendants({{classname}}.class, Collections.unmodifiableMap(schemas)); + {{#discriminator}} + // Initialize and register the discriminator mappings. + Map mappings = new HashMap(); + {{#mappedModels}} + mappings.put("{{mappingName}}", {{modelName}}.class); + {{/mappedModels}} + mappings.put("{{name}}", {{classname}}.class); + JSON.registerDiscriminator({{classname}}.class, "{{propertyBaseName}}", mappings); + {{/discriminator}} } @Override @@ -78,15 +169,15 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im @Override public void setActualInstance(Object instance) { - {{#isNulalble}} + {{#isNullable}} if (instance == null) { super.setActualInstance(instance); return; } - {{/isNulalble}} + {{/isNullable}} {{#anyOf}} - if (instance instanceof {{{.}}}) { + if (JSON.isInstanceOf({{{.}}}.class, instance, new HashSet())) { super.setActualInstance(instance); return; } diff --git a/libraries/jersey2/api.mustache b/libraries/jersey2/api.mustache index 509ae48a50e..5376c811c44 100644 --- a/libraries/jersey2/api.mustache +++ b/libraries/jersey2/api.mustache @@ -167,7 +167,7 @@ public class {{classname}} { {{/returnType}} return apiClient.invokeAPI("{{classname}}.{{operationId}}", localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, - localVarAuthNames, {{#returnType}}localVarReturnType{{/returnType}}{{^returnType}}null{{/returnType}}, {{#vendorExtensions.x-java-return-type-one-of}}new {{{returnType}}}(){{/vendorExtensions.x-java-return-type-one-of}}{{^vendorExtensions.x-java-return-type-one-of}}{{#vendorExtensions.x-java-return-type-any-of}}new {{{returnType}}}(){{/vendorExtensions.x-java-return-type-any-of}}{{^vendorExtensions.x-java-return-type-any-of}}null{{/vendorExtensions.x-java-return-type-any-of}}{{/vendorExtensions.x-java-return-type-one-of}}); + localVarAuthNames, {{#returnType}}localVarReturnType{{/returnType}}{{^returnType}}null{{/returnType}}); } {{#vendorExtensions.x-group-parameters}} diff --git a/libraries/jersey2/api_test.mustache b/libraries/jersey2/api_test.mustache index 1c122287e8d..1bb19c9acb1 100644 --- a/libraries/jersey2/api_test.mustache +++ b/libraries/jersey2/api_test.mustache @@ -6,9 +6,10 @@ import {{invokerPackage}}.*; import {{invokerPackage}}.auth.*; {{#imports}}import {{import}}; {{/imports}} -import org.junit.Test; -import org.junit.Ignore; import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + {{^fullJavaUtil}} import java.util.ArrayList; diff --git a/libraries/jersey2/model.mustache b/libraries/jersey2/model.mustache index 02787f8bb7f..c0664be10de 100644 --- a/libraries/jersey2/model.mustache +++ b/libraries/jersey2/model.mustache @@ -6,9 +6,21 @@ package {{package}}; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; {{/useReflectionEqualsHashCode}} +{{#models}} +{{#model}} +{{#additionalPropertiesType}} +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +{{/additionalPropertiesType}} +{{/model}} +{{/models}} {{^supportJava6}} import java.util.Objects; import java.util.Arrays; +import java.util.Map; +import java.util.HashMap; {{/supportJava6}} {{#supportJava6}} import org.apache.commons.lang3.ObjectUtils; @@ -39,9 +51,16 @@ import javax.validation.Valid; {{#performBeanValidation}} import org.hibernate.validator.constraints.*; {{/performBeanValidation}} +import {{invokerPackage}}.JSON; {{#models}} {{#model}} +{{#oneOf}} +{{#-first}} +import com.fasterxml.jackson.core.type.TypeReference; +{{/-first}} +{{/oneOf}} + {{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{#oneOf}}{{#-first}}{{>oneof_model}}{{/-first}}{{/oneOf}}{{^oneOf}}{{#anyOf}}{{#-first}}{{>anyof_model}}{{/-first}}{{/anyOf}}{{^anyOf}}{{>pojo}}{{/anyOf}}{{/oneOf}}{{/isEnum}} {{/model}} {{/models}} diff --git a/libraries/jersey2/oneof_model.mustache b/libraries/jersey2/oneof_model.mustache index fec28f2e2dc..8a275c9691c 100644 --- a/libraries/jersey2/oneof_model.mustache +++ b/libraries/jersey2/oneof_model.mustache @@ -4,21 +4,44 @@ import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; +import java.util.Collections; +import java.util.HashSet; +import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import org.openapitools.client.JSON; {{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} -@JsonDeserialize(using={{classname}}.{{classname}}Deserializer.class) +@JsonDeserialize(using = {{classname}}.{{classname}}Deserializer.class) +@JsonSerialize(using = {{classname}}.{{classname}}Serializer.class) public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}}, {{{.}}}{{/vendorExtensions.x-implements}} { private static final Logger log = Logger.getLogger({{classname}}.class.getName()); + public static class {{classname}}Serializer extends StdSerializer<{{classname}}> { + public {{classname}}Serializer(Class<{{classname}}> t) { + super(t); + } + + public {{classname}}Serializer() { + this(null); + } + + @Override + public void serialize({{classname}} value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeObject(value.getActualInstance()); + } + } + public static class {{classname}}Deserializer extends StdDeserializer<{{classname}}> { public {{classname}}Deserializer() { this({{classname}}.class); @@ -31,13 +54,33 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im @Override public {{classname}} deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { JsonNode tree = jp.readValueAsTree(); + Object deserialized = null; + {{#useOneOfDiscriminatorLookup}} + {{#discriminator}} + {{classname}} new{{classname}} = new {{classname}}(); + Map result2 = tree.traverse(jp.getCodec()).readValueAs(new TypeReference>() {}); + String discriminatorValue = (String)result2.get("{{{propertyBaseName}}}"); + switch (discriminatorValue) { + {{#mappedModels}} + case "{{{mappingName}}}": + deserialized = tree.traverse(jp.getCodec()).readValueAs({{{modelName}}}.class); + new{{classname}}.setActualInstance(deserialized); + return new{{classname}}; + {{/mappedModels}} + default: + log.log(Level.WARNING, String.format("Failed to lookup discriminator value `%s` for {{classname}}. Possible values:{{#mappedModels}} {{{mappingName}}}{{/mappedModels}}", discriminatorValue)); + } + {{/discriminator}} + {{/useOneOfDiscriminatorLookup}} int match = 0; - Object deserialized = null; {{#oneOf}} // deserialize {{{.}}} try { deserialized = tree.traverse(jp.getCodec()).readValueAs({{{.}}}.class); + // TODO: there is no validation against JSON schema constraints + // (min, max, enum, pattern...), this does not perform a strict JSON + // validation, which means the 'match' count may be higher than it should be. match++; log.log(Level.FINER, "Input data matches schema '{{{.}}}'"); } catch (Exception e) { @@ -53,6 +96,41 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im } throw new IOException(String.format("Failed deserialization for {{classname}}: %d classes match result, expected 1", match)); } + + {{#additionalPropertiesType}} + /** + * Method called to deal with a property that did not map to a known Bean property. + * Method can deal with the problem as it sees fit (ignore, throw exception); but if it does return, + * it has to skip the matching Json content parser has. + * + * @param p - Parser that points to value of the unknown property + * @param ctxt - Context for deserialization; allows access to the parser, error reporting functionality + * @param instanceOrClass - Instance that is being populated by this deserializer, or if not known, Class that would be instantiated. If null, will assume type is what getValueClass() returns. + * @param propName - Name of the property that cannot be mapped + */ + @Override + protected void handleUnknownProperty(JsonParser p, + DeserializationContext ctxt, + Object instanceOrClass, + String propName) throws IOException { + System.out.println("Deserializing unknown property " + propName); + {{{.}}} deserialized = p.readValueAs({{{.}}}.class); + additionalProperties.put(propName, deserialized); + } + {{/additionalPropertiesType}} + + /** + * Handle deserialization of the 'null' value. + */ + @Override + public {{classname}} getNullValue(DeserializationContext ctxt) throws JsonMappingException { + {{#isNullable}} + return null; + {{/isNullable}} + {{^isNullable}} + throw new JsonMappingException("{{classname}} cannot be null"); + {{/isNullable}} + } } // store a list of schema names defined in oneOf @@ -61,7 +139,18 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im public {{classname}}() { super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); } +{{> libraries/jersey2/additional_properties }} + {{#additionalPropertiesType}} + @Override + public boolean equals(Object o) { + return super.equals(o) && Objects.equals(this.additionalProperties, o.additionalProperties) + } + @Override + public int hashCode() { + return Objects.hash(instance, isNullable, schemaType, additionalProperties); + } + {{/additionalPropertiesType}} {{#oneOf}} public {{classname}}({{{.}}} o) { super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); @@ -74,6 +163,16 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im schemas.put("{{{.}}}", new GenericType<{{{.}}}>() { }); {{/oneOf}} + JSON.registerDescendants({{classname}}.class, Collections.unmodifiableMap(schemas)); + {{#discriminator}} + // Initialize and register the discriminator mappings. + Map mappings = new HashMap(); + {{#mappedModels}} + mappings.put("{{mappingName}}", {{modelName}}.class); + {{/mappedModels}} + mappings.put("{{name}}", {{classname}}.class); + JSON.registerDiscriminator({{classname}}.class, "{{propertyBaseName}}", mappings); + {{/discriminator}} } @Override @@ -81,17 +180,24 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im return {{classname}}.schemas; } + /** + * Set the instance that matches the oneOf child schema, check + * the instance parameter is valid against the oneOf child schemas. + * + * It could be an instance of the 'oneOf' schemas. + * The oneOf child schemas may themselves be a composed schema (allOf, anyOf, oneOf). + */ @Override public void setActualInstance(Object instance) { - {{#isNulalble}} + {{#isNullable}} if (instance == null) { super.setActualInstance(instance); return; } - {{/isNulalble}} + {{/isNullable}} {{#oneOf}} - if (instance instanceof {{{.}}}) { + if (JSON.isInstanceOf({{{.}}}.class, instance, new HashSet())) { super.setActualInstance(instance); return; } diff --git a/libraries/jersey2/pojo.mustache b/libraries/jersey2/pojo.mustache index c438cd43eb7..19e82e3dfa6 100644 --- a/libraries/jersey2/pojo.mustache +++ b/libraries/jersey2/pojo.mustache @@ -99,8 +99,12 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{^isReadOnly}} public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { - {{#vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});{{/vendorExtensions.x-is-jackson-optional-nullable}} - {{^vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = {{name}};{{/vendorExtensions.x-is-jackson-optional-nullable}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} return this; } {{#isListContainer}} @@ -226,7 +230,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{/isReadOnly}} {{/vars}} - +{{>libraries/jersey2/additional_properties}} {{^supportJava6}} @Override public boolean equals(java.lang.Object o) { @@ -242,7 +246,8 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE }{{#hasVars}} {{classname}} {{classVarName}} = ({{classname}}) o; return {{#vars}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{#hasMore}} && - {{/hasMore}}{{/vars}}{{#parent}} && + {{/hasMore}}{{/vars}}{{#additionalPropertiesType}}&& + Objects.equals(this.additionalProperties, {{classVarName}}.additionalProperties){{/additionalPropertiesType}}{{#parent}} && super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}} {{/useReflectionEqualsHashCode}} @@ -254,7 +259,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE return HashCodeBuilder.reflectionHashCode(this); {{/useReflectionEqualsHashCode}} {{^useReflectionEqualsHashCode}} - return Objects.hash({{#vars}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{#hasMore}}, {{/hasMore}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); + return Objects.hash({{#vars}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{#hasMore}}, {{/hasMore}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}{{#additionalPropertiesType}}, additionalProperties{{/additionalPropertiesType}}); {{/useReflectionEqualsHashCode}} } @@ -292,6 +297,9 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{#vars}} sb.append(" {{name}}: ").append(toIndentedString({{name}})).append("\n"); {{/vars}} + {{#additionalPropertiesType}} + sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n"); + {{/additionalPropertiesType}} sb.append("}"); return sb.toString(); } @@ -366,4 +374,15 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE } }; {{/parcelableModel}} +{{#discriminator}} +static { + // Initialize and register the discriminator mappings. + Map mappings = new HashMap(); + {{#mappedModels}} + mappings.put("{{mappingName}}", {{modelName}}.class); + {{/mappedModels}} + mappings.put("{{name}}", {{classname}}.class); + JSON.registerDiscriminator({{classname}}.class, "{{propertyBaseName}}", mappings); +} +{{/discriminator}} } diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 873fb95968d..9938e104641 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -74,6 +74,7 @@ -Xms512m -Xmx1500m methods 10 + false From b2c1bbd55f35f48ab81d3c921111f7285a75004c Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Tue, 9 Jun 2020 20:50:25 -0700 Subject: [PATCH 251/370] fix import of JSON class (#6606) --- libraries/jersey2/anyof_model.mustache | 2 +- libraries/jersey2/oneof_model.mustache | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/jersey2/anyof_model.mustache b/libraries/jersey2/anyof_model.mustache index a40ad85777a..0ca3162c5ec 100644 --- a/libraries/jersey2/anyof_model.mustache +++ b/libraries/jersey2/anyof_model.mustache @@ -19,7 +19,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.ser.std.StdSerializer; -import org.openapitools.client.JSON; +import {{invokerPackage}}.JSON; {{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} @JsonDeserialize(using={{classname}}.{{classname}}Deserializer.class) diff --git a/libraries/jersey2/oneof_model.mustache b/libraries/jersey2/oneof_model.mustache index 8a275c9691c..4ff6bb6d079 100644 --- a/libraries/jersey2/oneof_model.mustache +++ b/libraries/jersey2/oneof_model.mustache @@ -19,7 +19,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.ser.std.StdSerializer; -import org.openapitools.client.JSON; +import {{invokerPackage}}.JSON; {{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} @JsonDeserialize(using = {{classname}}.{{classname}}Deserializer.class) From b0cb7673f196e553d8e3901a2256ee7726def7d6 Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Tue, 9 Jun 2020 20:52:38 -0700 Subject: [PATCH 252/370] [Java][jersey2] Fix Java compiler warnings (#6605) * Mustache template should use invokerPackage tag to generate import * fix typo, fix script issue, add log statement for troubleshooting * Add java jersey2 samples with OpenAPI doc that has HTTP signature security scheme * Add sample for Java jersey2 and HTTP signature scheme * Add unit test for oneOf schema deserialization * Add unit test for oneOf schema deserialization * Add log statements * Add profile for jersey2 * Temporarily disable unit test * Temporarily disable unit test * support for discriminator in jersey2 * fix typo in pom.xml * disable unit test because jersey2 deserialization is broken * disable unit test because jersey2 deserialization is broken * fix duplicate jersey2 samples * fix duplicate jersey2 samples * Add code comments * fix duplicate artifact id * fix duplicate jersey2 samples * run samples scripts * resolve merge conflicts * Add unit tests * fix unit tests * continue implementation of discriminator lookup * throw deserialization exception when value is null and schema does not allow null value * continue implementation of compose schema * continue implementation of compose schema * continue implementation of compose schema * Add more unit tests * Add unit tests for anyOf * Add unit tests * [java][jersey2] Add support for discriminator, fix nullable typo and nullable deserialization (#6495) * Mustache template should use invokerPackage tag to generate import * fix typo, fix script issue, add log statement for troubleshooting * Add java jersey2 samples with OpenAPI doc that has HTTP signature security scheme * Add sample for Java jersey2 and HTTP signature scheme * Add unit test for oneOf schema deserialization * Add unit test for oneOf schema deserialization * Add log statements * Add profile for jersey2 * Temporarily disable unit test * Temporarily disable unit test * support for discriminator in jersey2 * fix typo in pom.xml * disable unit test because jersey2 deserialization is broken * disable unit test because jersey2 deserialization is broken * fix duplicate jersey2 samples * fix duplicate jersey2 samples * Add code comments * fix duplicate artifact id * fix duplicate jersey2 samples * run samples scripts * resolve merge conflicts * Add unit tests * fix unit tests * continue implementation of discriminator lookup * throw deserialization exception when value is null and schema does not allow null value * continue implementation of compose schema * continue implementation of compose schema * continue implementation of compose schema * Add more unit tests * Add unit tests for anyOf * Add unit tests Co-authored-by: Vikrant Balyan (vvb) * update samples * add tests to oas3 java jersey2 petstore * Fix 'method too big' error with generated code * resolve merge conflicts * comment out jersey2 ensure uptodate * fix compiler warnings * Jersey2 supports additional properties with composed schema (#6523) * Mustache template should use invokerPackage tag to generate import * fix typo, fix script issue, add log statement for troubleshooting * Add java jersey2 samples with OpenAPI doc that has HTTP signature security scheme * Add sample for Java jersey2 and HTTP signature scheme * Add unit test for oneOf schema deserialization * Add unit test for oneOf schema deserialization * Add log statements * Add profile for jersey2 * Temporarily disable unit test * Temporarily disable unit test * support for discriminator in jersey2 * fix typo in pom.xml * disable unit test because jersey2 deserialization is broken * disable unit test because jersey2 deserialization is broken * fix duplicate jersey2 samples * fix duplicate jersey2 samples * Add code comments * fix duplicate artifact id * fix duplicate jersey2 samples * run samples scripts * resolve merge conflicts * Add unit tests * fix unit tests * continue implementation of discriminator lookup * throw deserialization exception when value is null and schema does not allow null value * continue implementation of compose schema * continue implementation of compose schema * continue implementation of compose schema * Add more unit tests * Add unit tests for anyOf * Add unit tests * Set supportsAdditionalPropertiesWithComposedSchema to true for Java jersey2 * Support additional properties as nested field * Support additional properties as nested field * add code comments * add customer deserializer * Fix 'method too big' error with generated code * resolve merge conflicts Co-authored-by: Vikrant Balyan (vvb) * [Jersey2] Fix code generation of 'registerDiscriminator' method for large models (#6535) * Mustache template should use invokerPackage tag to generate import * fix typo, fix script issue, add log statement for troubleshooting * Add java jersey2 samples with OpenAPI doc that has HTTP signature security scheme * Add sample for Java jersey2 and HTTP signature scheme * Add unit test for oneOf schema deserialization * Add unit test for oneOf schema deserialization * Add log statements * Add profile for jersey2 * Temporarily disable unit test * Temporarily disable unit test * support for discriminator in jersey2 * fix typo in pom.xml * disable unit test because jersey2 deserialization is broken * disable unit test because jersey2 deserialization is broken * fix duplicate jersey2 samples * fix duplicate jersey2 samples * Add code comments * fix duplicate artifact id * fix duplicate jersey2 samples * run samples scripts * resolve merge conflicts * Add unit tests * fix unit tests * continue implementation of discriminator lookup * throw deserialization exception when value is null and schema does not allow null value * continue implementation of compose schema * continue implementation of compose schema * continue implementation of compose schema * Add more unit tests * Add unit tests for anyOf * Add unit tests * Fix 'method too big' error with generated code * resolve merge conflicts Co-authored-by: Vikrant Balyan (vvb) * Add unit test for date time * Add unit test for date time * update samples * comment out tests * support additional properties in serialize and deserialize * add discriminator lookup * remove oneof/anyof logic in apilcient * add serializer to mammal.java * add serialize to oneOf model * add serializer to anyof model * comment out test cases that are subject to further discussion * add back files * update configs, samples * resolve merge conflicts Co-authored-by: Vikrant Balyan (vvb) Co-authored-by: William Cheng --- libraries/jersey2/JSON.mustache | 30 +++++++++++++------------- libraries/jersey2/anyof_model.mustache | 8 +++---- libraries/jersey2/oneof_model.mustache | 6 +++--- libraries/jersey2/pojo.mustache | 2 +- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/libraries/jersey2/JSON.mustache b/libraries/jersey2/JSON.mustache index 3d3339c5d6b..bcc075ac9fc 100644 --- a/libraries/jersey2/JSON.mustache +++ b/libraries/jersey2/JSON.mustache @@ -84,10 +84,10 @@ public class JSON implements ContextResolver { * @param node The input data. * @param modelClass The class that contains the discriminator mappings. */ - public static Class getClassForElement(JsonNode node, Class modelClass) { + public static Class getClassForElement(JsonNode node, Class modelClass) { ClassDiscriminatorMapping cdm = modelDiscriminators.get(modelClass); if (cdm != null) { - return cdm.getClassForElement(node, new HashSet()); + return cdm.getClassForElement(node, new HashSet>()); } return null; } @@ -97,17 +97,17 @@ public class JSON implements ContextResolver { */ private static class ClassDiscriminatorMapping { // The model class name. - Class modelClass; + Class modelClass; // The name of the discriminator property. String discriminatorName; // The discriminator mappings for a model class. - Map discriminatorMappings; + Map> discriminatorMappings; // Constructs a new class discriminator. - ClassDiscriminatorMapping(Class cls, String propertyName, Map mappings) { + ClassDiscriminatorMapping(Class cls, String propertyName, Map> mappings) { modelClass = cls; discriminatorName = propertyName; - discriminatorMappings = new HashMap(); + discriminatorMappings = new HashMap>(); if (mappings != null) { discriminatorMappings.putAll(mappings); } @@ -143,7 +143,7 @@ public class JSON implements ContextResolver { * @param node The input data. * @param visitedClasses The set of classes that have already been visited. */ - Class getClassForElement(JsonNode node, Set visitedClasses) { + Class getClassForElement(JsonNode node, Set> visitedClasses) { if (visitedClasses.contains(modelClass)) { // Class has already been visited. return null; @@ -153,11 +153,11 @@ public class JSON implements ContextResolver { if (discrValue == null) { return null; } - Class cls = discriminatorMappings.get(discrValue); + Class cls = discriminatorMappings.get(discrValue); // It may not be sufficient to return this cls directly because that target class // may itself be a composed schema, possibly with its own discriminator. visitedClasses.add(modelClass); - for (Class childClass : discriminatorMappings.values()) { + for (Class childClass : discriminatorMappings.values()) { ClassDiscriminatorMapping childCdm = modelDiscriminators.get(childClass); if (childCdm == null) { continue; @@ -170,7 +170,7 @@ public class JSON implements ContextResolver { } if (childCdm != null) { // Recursively traverse the discriminator mappings. - Class childDiscr = childCdm.getClassForElement(node, visitedClasses); + Class childDiscr = childCdm.getClassForElement(node, visitedClasses); if (childDiscr != null) { return childDiscr; } @@ -189,7 +189,7 @@ public class JSON implements ContextResolver { * @param modelClass A OpenAPI model class. * @param inst The instance object. */ - public static boolean isInstanceOf(Class modelClass, Object inst, Set visitedClasses) { + public static boolean isInstanceOf(Class modelClass, Object inst, Set> visitedClasses) { if (modelClass.isInstance(inst)) { // This handles the 'allOf' use case with single parent inheritance. return true; @@ -216,12 +216,12 @@ public class JSON implements ContextResolver { /** * A map of discriminators for all model classes. */ - private static Map modelDiscriminators = new HashMap(); + private static Map, ClassDiscriminatorMapping> modelDiscriminators = new HashMap, ClassDiscriminatorMapping>(); /** * A map of oneOf/anyOf descendants for each model class. */ - private static Map> modelDescendants = new HashMap>(); + private static Map, Map> modelDescendants = new HashMap, Map>(); /** * Register a model class discriminator. @@ -230,7 +230,7 @@ public class JSON implements ContextResolver { * @param discriminatorPropertyName the name of the discriminator property * @param mappings a map with the discriminator mappings. */ - public static void registerDiscriminator(Class modelClass, String discriminatorPropertyName, Map mappings) { + public static void registerDiscriminator(Class modelClass, String discriminatorPropertyName, Map> mappings) { ClassDiscriminatorMapping m = new ClassDiscriminatorMapping(modelClass, discriminatorPropertyName, mappings); modelDiscriminators.put(modelClass, m); } @@ -241,7 +241,7 @@ public class JSON implements ContextResolver { * @param modelClass the model class * @param descendants a map of oneOf/anyOf descendants. */ - public static void registerDescendants(Class modelClass, Map descendants) { + public static void registerDescendants(Class modelClass, Map descendants) { modelDescendants.put(modelClass, descendants); } diff --git a/libraries/jersey2/anyof_model.mustache b/libraries/jersey2/anyof_model.mustache index 0ca3162c5ec..ef91fb3204b 100644 --- a/libraries/jersey2/anyof_model.mustache +++ b/libraries/jersey2/anyof_model.mustache @@ -57,7 +57,7 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im Object deserialized = null; {{#discriminator}} - Class cls = JSON.getClassForElement(tree, {{classname}}.class); + Class cls = JSON.getClassForElement(tree, {{classname}}.class); if (cls != null) { // When the OAS schema includes a discriminator, use the discriminator value to // discriminate the anyOf schemas. @@ -115,7 +115,7 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im return null; {{/isNullable}} {{^isNullable}} - throw new JsonMappingException("{{classname}} cannot be null"); + throw new JsonMappingException(ctxt.getParser(), "{{classname}} cannot be null"); {{/isNullable}} } } @@ -153,7 +153,7 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im JSON.registerDescendants({{classname}}.class, Collections.unmodifiableMap(schemas)); {{#discriminator}} // Initialize and register the discriminator mappings. - Map mappings = new HashMap(); + Map> mappings = new HashMap>(); {{#mappedModels}} mappings.put("{{mappingName}}", {{modelName}}.class); {{/mappedModels}} @@ -177,7 +177,7 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im {{/isNullable}} {{#anyOf}} - if (JSON.isInstanceOf({{{.}}}.class, instance, new HashSet())) { + if (JSON.isInstanceOf({{{.}}}.class, instance, new HashSet>())) { super.setActualInstance(instance); return; } diff --git a/libraries/jersey2/oneof_model.mustache b/libraries/jersey2/oneof_model.mustache index 4ff6bb6d079..2289c28360a 100644 --- a/libraries/jersey2/oneof_model.mustache +++ b/libraries/jersey2/oneof_model.mustache @@ -128,7 +128,7 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im return null; {{/isNullable}} {{^isNullable}} - throw new JsonMappingException("{{classname}} cannot be null"); + throw new JsonMappingException(ctxt.getParser(), "{{classname}} cannot be null"); {{/isNullable}} } } @@ -166,7 +166,7 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im JSON.registerDescendants({{classname}}.class, Collections.unmodifiableMap(schemas)); {{#discriminator}} // Initialize and register the discriminator mappings. - Map mappings = new HashMap(); + Map> mappings = new HashMap>(); {{#mappedModels}} mappings.put("{{mappingName}}", {{modelName}}.class); {{/mappedModels}} @@ -197,7 +197,7 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im {{/isNullable}} {{#oneOf}} - if (JSON.isInstanceOf({{{.}}}.class, instance, new HashSet())) { + if (JSON.isInstanceOf({{{.}}}.class, instance, new HashSet>())) { super.setActualInstance(instance); return; } diff --git a/libraries/jersey2/pojo.mustache b/libraries/jersey2/pojo.mustache index 19e82e3dfa6..af6f2491cbd 100644 --- a/libraries/jersey2/pojo.mustache +++ b/libraries/jersey2/pojo.mustache @@ -377,7 +377,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{#discriminator}} static { // Initialize and register the discriminator mappings. - Map mappings = new HashMap(); + Map> mappings = new HashMap>(); {{#mappedModels}} mappings.put("{{mappingName}}", {{modelName}}.class); {{/mappedModels}} From 36abc0fc60563df65075b6f6ea8b6f89743df9fe Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 10 Jun 2020 17:22:06 +0800 Subject: [PATCH 253/370] remove localVariablePrefix (#6588) --- libraries/jersey2/api.mustache | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/jersey2/api.mustache b/libraries/jersey2/api.mustache index 5376c811c44..16f7ef45b8c 100644 --- a/libraries/jersey2/api.mustache +++ b/libraries/jersey2/api.mustache @@ -173,12 +173,12 @@ public class {{classname}} { public class API{{operationId}}Request { {{#allParams}} - private {{#isRequired}}final {{/isRequired}}{{{dataType}}} {{localVariablePrefix}}{{paramName}}; + private {{#isRequired}}final {{/isRequired}}{{{dataType}}} {{paramName}}; {{/allParams}} private API{{operationId}}Request({{#pathParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}) { {{#pathParams}} - this.{{localVariablePrefix}}{{paramName}} = {{paramName}}; + this.{{paramName}} = {{paramName}}; {{/pathParams}} } {{#allParams}} @@ -190,7 +190,7 @@ public class {{classname}} { * @return API{{operationId}}Request */ public API{{operationId}}Request {{paramName}}({{{dataType}}} {{paramName}}) { - this.{{localVariablePrefix}}{{paramName}} = {{paramName}}; + this.{{paramName}} = {{paramName}}; return this; } {{/isPathParam}} @@ -236,7 +236,7 @@ public class {{classname}} { @Deprecated {{/isDeprecated}} public ApiResponse<{{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> executeWithHttpInfo() throws ApiException { - return {{operationId}}WithHttpInfo({{#allParams}}{{localVariablePrefix}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); } } From 75d7a5e387aa95591f32ec50dd02bd3871d19b86 Mon Sep 17 00:00:00 2001 From: bgong-mdsol Date: Wed, 10 Jun 2020 06:50:35 -0400 Subject: [PATCH 254/370] Use builder pattern for requests (#5961) --- libraries/native/README.mustache | 13 ++- libraries/native/api.mustache | 97 ++++++++++++++++++-- libraries/native/api_doc.mustache | 140 +++++++++++++++++++++++++++++ libraries/native/api_test.mustache | 59 ++++++++++++ 4 files changed, 298 insertions(+), 11 deletions(-) create mode 100644 libraries/native/api_doc.mustache create mode 100644 libraries/native/api_test.mustache diff --git a/libraries/native/README.mustache b/libraries/native/README.mustache index f574b47b485..7257a26f95f 100644 --- a/libraries/native/README.mustache +++ b/libraries/native/README.mustache @@ -81,7 +81,11 @@ Please follow the [installation](#installation) instruction and execute the foll {{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}} import {{{invokerPackage}}}.*; import {{{modelPackage}}}.*; -import {{{package}}}.{{{classname}}}; +import {{{package}}}.{{{classname}}};{{#vendorExtensions.x-group-parameters}} +import {{{package}}}.{{{classname}}}.*;{{/vendorExtensions.x-group-parameters}} +{{#asyncNative}} +import java.util.concurrent.CompletableFuture; +{{/asyncNative}} public class {{{classname}}}Example { @@ -94,7 +98,12 @@ public class {{{classname}}}Example { {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} {{/allParams}} try { - {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + {{^vendorExtensions.x-group-parameters}} + {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} result = {{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture result = {{/asyncNative}}{{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}{{#hasParams}} + API{{operationId}}Request request = API{{operationId}}Request.newBuilder(){{#allParams}} + .{{paramName}}({{paramName}}){{/allParams}} + .build();{{/hasParams}} + {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} result = {{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture result = {{/asyncNative}}{{/returnType}}apiInstance.{{operationId}}({{#hasParams}}request{{/hasParams}});{{/vendorExtensions.x-group-parameters}}{{#returnType}} System.out.println(result);{{/returnType}} } catch (ApiException e) { System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); diff --git a/libraries/native/api.mustache b/libraries/native/api.mustache index 7d6ed2d4bb7..8bd7393ab59 100644 --- a/libraries/native/api.mustache +++ b/libraries/native/api.mustache @@ -41,7 +41,7 @@ public class {{classname}} { private final Consumer memberVarInterceptor; private final Duration memberVarReadTimeout; private final Consumer> memberVarResponseInterceptor; - + public {{classname}}() { this(new ApiClient()); } @@ -56,6 +56,36 @@ public class {{classname}} { } {{#operation}} + {{#vendorExtensions.x-group-parameters}} + {{#hasParams}} + /** + * {{summary}} + * {{notes}} + * @param {{operationId}}Request {@link API{{operationId}}Request} + {{#returnType}} + * @return {{returnType}} + {{/returnType}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}({{#hasParams}}API{{operationId}}Request {{operationId}}Request{{/hasParams}}) throws ApiException { + {{#allParams}} + {{{dataType}}} {{paramName}} = {{operationId}}Request.{{paramName}}(); + {{/allParams}} + {{#returnType}}return {{/returnType}}{{^returnType}}{{#asyncNative}}return {{/asyncNative}}{{/returnType}}{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + } + + {{/hasParams}} + {{/vendorExtensions.x-group-parameters}} /** * {{summary}} * {{notes}} @@ -158,7 +188,7 @@ public class {{classname}} { HttpResponse.BodyHandlers.ofInputStream()); if (memberVarResponseInterceptor != null) { memberVarResponseInterceptor.accept(localVarResponse); - } + } if (localVarResponse.statusCode()/ 100 != 2) { throw new ApiException(localVarResponse.statusCode(), "{{operationId}} call received non-success response", @@ -180,18 +210,17 @@ public class {{classname}} { localVarResponse.body()) ); } else { - try { + {{#returnType}} + try { return CompletableFuture.completedFuture( - {{#returnType}} - memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference<{{{returnType}}}>() {}) - {{/returnType}} - {{^returnType}} - null - {{/returnType}} + memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference<{{{returnType}}}>() {}) ); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } + {{/returnType}}{{^returnType}} + return CompletableFuture.completedFuture(null); + {{/returnType}} } }); {{/asyncNative}} @@ -214,6 +243,56 @@ public class {{classname}} { } {{/asyncNative}} } + {{#vendorExtensions.x-group-parameters}} + {{#hasParams}} + + public static final class API{{operationId}}Request { + {{#requiredParams}} + private {{{dataType}}} {{paramName}}; // {{description}} (required) + {{/requiredParams}} + {{#optionalParams}} + private {{{dataType}}} {{paramName}}; // {{description}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}} + {{/optionalParams}} + + private API{{operationId}}Request(Builder builder) { + {{#requiredParams}} + this.{{paramName}} = builder.{{paramName}}; + {{/requiredParams}} + {{#optionalParams}} + this.{{paramName}} = builder.{{paramName}}; + {{/optionalParams}} + } + {{#allParams}} + public {{{dataType}}} {{paramName}}() { + return {{paramName}}; + } + {{/allParams}} + public static Builder newBuilder() { + return new Builder(); + } + + public static class Builder { + {{#requiredParams}} + private {{{dataType}}} {{paramName}}; + {{/requiredParams}} + {{#optionalParams}} + private {{{dataType}}} {{paramName}}; + {{/optionalParams}} + + {{#allParams}} + public Builder {{paramName}}({{{dataType}}} {{paramName}}) { + this.{{paramName}} = {{paramName}}; + return this; + } + {{/allParams}} + public API{{operationId}}Request build() { + return new API{{operationId}}Request(this); + } + } + } + + {{/hasParams}} + {{/vendorExtensions.x-group-parameters}} {{/operation}} } {{/operations}} diff --git a/libraries/native/api_doc.mustache b/libraries/native/api_doc.mustache new file mode 100644 index 00000000000..5ece7d73aba --- /dev/null +++ b/libraries/native/api_doc.mustache @@ -0,0 +1,140 @@ +# {{classname}}{{#description}} + +{{description}}{{/description}} + +All URIs are relative to *{{basePath}}* + +Method | HTTP request | Description +------------- | ------------- | ------------- +{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}} + +{{#operations}} +{{#operation}} + +## {{operationId}} + +{{^vendorExtensions.x-group-parameters}} +> {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) +{{/vendorExtensions.x-group-parameters}} +{{#vendorExtensions.x-group-parameters}} +> {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}({{#hasParams}}{{operationId}}Request{{/hasParams}}) +{{/vendorExtensions.x-group-parameters}} + +{{summary}}{{#notes}} + +{{notes}}{{/notes}} + +### Example + +```java +// Import classes: +import {{{invokerPackage}}}.ApiClient; +import {{{invokerPackage}}}.ApiException; +import {{{invokerPackage}}}.Configuration;{{#hasAuthMethods}} +import {{{invokerPackage}}}.auth.*;{{/hasAuthMethods}} +import {{{invokerPackage}}}.models.*; +import {{{package}}}.{{{classname}}};{{#vendorExtensions.x-group-parameters}} +import {{{package}}}.{{{classname}}}.*;{{/vendorExtensions.x-group-parameters}} +{{#asyncNative}} +import java.util.concurrent.CompletableFuture; +{{/asyncNative}} + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("{{{basePath}}}"); + {{#hasAuthMethods}} + {{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + // Configure HTTP basic authorization: {{{name}}} + HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setUsername("YOUR USERNAME"); + {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasicBasic}}{{#isBasicBearer}} + // Configure HTTP bearer authorization: {{{name}}} + HttpBearerAuth {{{name}}} = (HttpBearerAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setBearerToken("BEARER TOKEN");{{/isBasicBearer}}{{/isBasic}}{{#isApiKey}} + // Configure API key authorization: {{{name}}} + ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setApiKey("YOUR API KEY"); + // Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null) + //{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} + // Configure OAuth2 access token for authorization: {{{name}}} + OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}} + {{/authMethods}} + {{/hasAuthMethods}} + + {{{classname}}} apiInstance = new {{{classname}}}(defaultClient); + {{#allParams}} + {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} + {{/allParams}} + try { + {{^vendorExtensions.x-group-parameters}} + {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} result = {{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture result = {{/asyncNative}}{{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}{{#hasParams}} + API{{operationId}}Request request = API{{operationId}}Request.newBuilder(){{#allParams}} + .{{paramName}}({{paramName}}){{/allParams}} + .build();{{/hasParams}} + {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} result = {{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture result = {{/asyncNative}}{{/returnType}}apiInstance.{{operationId}}({{#hasParams}}request{{/hasParams}});{{/vendorExtensions.x-group-parameters}}{{#returnType}} + System.out.println(result);{{/returnType}} + } catch (ApiException e) { + System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } +} +``` + +### Parameters + +{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{^vendorExtensions.x-group-parameters}}{{#allParams}}{{#-last}} +Name | Type | Description | Notes +------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} +{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{^isContainer}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} +{{/allParams}} +{{/vendorExtensions.x-group-parameters}} +{{#vendorExtensions.x-group-parameters}} +{{#hasParams}} +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------| +| {{operationId}}Request | [**API{{operationId}}Request**]({{classname}}.md#API{{operationId}}Request)|-|-|{{/hasParams}} +{{/vendorExtensions.x-group-parameters}} + +### Return type + +{{#returnType}}{{#asyncNative}}CompletableFuture<{{/asyncNative}}{{#returnTypeIsPrimitive}}**{{returnType}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{returnType}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}{{#asyncNative}}>{{/asyncNative}}{{/returnType}} +{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}null{{/asyncNative}} (empty response body){{/returnType}} + +### Authorization + +{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{name}}](../README.md#{{name}}){{^-last}}, {{/-last}}{{/authMethods}} + +### HTTP request headers + +- **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} +- **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} + +{{#responses.0}} +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +{{#responses}} +| **{{code}}** | {{message}} | {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}} | +{{/responses}} +{{/responses.0}} +{{#vendorExtensions.x-group-parameters}}{{#hasParams}} + + +## API{{operationId}}Request +### Properties +{{#allParams}}{{#-last}} +| Name | Type | Description | Notes | +| ------------- | ------------- | ------------- | -------------|{{/-last}}{{/allParams}} +{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}} | {{description}} |{{^required}} [optional]{{/required}}{{^isContainer}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} +{{/allParams}} + +{{/hasParams}}{{/vendorExtensions.x-group-parameters}} +{{/operation}} +{{/operations}} diff --git a/libraries/native/api_test.mustache b/libraries/native/api_test.mustache new file mode 100644 index 00000000000..dbfedfeb7b0 --- /dev/null +++ b/libraries/native/api_test.mustache @@ -0,0 +1,59 @@ +{{>licenseInfo}} + +package {{package}}; + +import {{invokerPackage}}.ApiException; +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Test; +import org.junit.Ignore; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +{{#asyncNative}} +import java.util.concurrent.CompletableFuture; +{{/asyncNative}} + +/** + * API tests for {{classname}} + */ +@Ignore +public class {{classname}}Test { + + private final {{classname}} api = new {{classname}}(); + + {{#operations}}{{#operation}} + /** + * {{summary}} + * + * {{notes}} + * + * @throws ApiException + * if the Api call fails + */ + @Test + public void {{operationId}}Test() throws ApiException { + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + {{^vendorExtensions.x-group-parameters}} + {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} response = {{/returnType}} + {{^returnType}}{{#asyncNative}}CompletableFuture response = {{/asyncNative}}{{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{/vendorExtensions.x-group-parameters}} + {{#vendorExtensions.x-group-parameters}}{{#hasParams}} + {{classname}}.API{{operationId}}Request request = {{classname}}.API{{operationId}}Request.newBuilder(){{#allParams}} + .{{paramName}}({{paramName}}){{/allParams}} + .build();{{/hasParams}} + {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} response = {{/returnType}} + {{^returnType}}{{#asyncNative}}CompletableFuture response = {{/asyncNative}}{{/returnType}}api.{{operationId}}({{#hasParams}}request{{/hasParams}}); + {{/vendorExtensions.x-group-parameters}} + + // TODO: test validations + } + {{/operation}}{{/operations}} +} From 298b2eb28db8c88fecbc046b5a58b952a414403e Mon Sep 17 00:00:00 2001 From: tgerth <39165556+tgerth@users.noreply.github.com> Date: Fri, 12 Jun 2020 11:23:42 +0200 Subject: [PATCH 255/370] [JAVA] RxJava3 support (#6622) * rx3 support * ran the shell script ./bin/generate-samples.sht * added missing rx3 migration, removed tabs --- libraries/retrofit2/ApiClient.mustache | 7 ++++++- libraries/retrofit2/api.mustache | 10 ++++++++-- libraries/retrofit2/build.gradle.mustache | 7 +++++++ libraries/retrofit2/build.sbt.mustache | 4 ++++ libraries/retrofit2/pom.mustache | 15 +++++++++++++++ 5 files changed, 40 insertions(+), 3 deletions(-) diff --git a/libraries/retrofit2/ApiClient.mustache b/libraries/retrofit2/ApiClient.mustache index 88f0a67004c..c0ca8d00c18 100644 --- a/libraries/retrofit2/ApiClient.mustache +++ b/libraries/retrofit2/ApiClient.mustache @@ -25,6 +25,9 @@ import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; {{#useRxJava2}} import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; {{/useRxJava2}} +{{#useRxJava3}} +import hu.akarnokd.rxjava3.retrofit.RxJava3CallAdapterFactory; +{{/useRxJava3}} import retrofit2.converter.gson.GsonConverterFactory; import retrofit2.converter.scalars.ScalarsConverterFactory; import {{invokerPackage}}.auth.HttpBasicAuth; @@ -151,7 +154,9 @@ public class ApiClient { .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) {{/useRxJava}}{{#useRxJava2}} .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) - {{/useRxJava2}} + {{/useRxJava2}}{{#useRxJava3}} + .addCallAdapterFactory(RxJava3CallAdapterFactory.create()) + {{/useRxJava3}} .addConverterFactory(ScalarsConverterFactory.create()) .addConverterFactory(GsonCustomConverterFactory.create(json.getGson())); } diff --git a/libraries/retrofit2/api.mustache b/libraries/retrofit2/api.mustache index 44f33a514f8..a54e6ffd60f 100644 --- a/libraries/retrofit2/api.mustache +++ b/libraries/retrofit2/api.mustache @@ -8,10 +8,16 @@ import rx.Observable; {{#useRxJava2}} import io.reactivex.Observable; {{/useRxJava2}} +{{#useRxJava3}} +import io.reactivex.rxjava3.core.Observable; +{{/useRxJava3}} {{^returnType}} {{#useRxJava2}} import io.reactivex.Completable; {{/useRxJava2}} +{{#useRxJava3}} +import io.reactivex.rxjava3.core.Completable; +{{/useRxJava3}} {{/returnType}} {{#doNotUseRx}} import retrofit2.Call; @@ -41,7 +47,7 @@ public interface {{classname}} { {{#allParams}} * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} - * @return {{^doNotUseRx}}{{#useRxJava}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/useRxJava}}{{#useRxJava2}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{returnType}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{/doNotUseRx}}{{#doNotUseRx}}Call<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/doNotUseRx}} + * @return {{^doNotUseRx}}{{#useRxJava}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/useRxJava}}{{#useRxJava2}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{returnType}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{#useRxJava3}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{returnType}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava3}}{{/doNotUseRx}}{{#doNotUseRx}}Call<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/doNotUseRx}} {{#isDeprecated}} * @deprecated {{/isDeprecated}} @@ -68,7 +74,7 @@ public interface {{classname}} { {{/prioritizedContentTypes}} {{/formParams}} @{{httpMethod}}("{{{path}}}") - {{^doNotUseRx}}{{#useRxJava}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/useRxJava}}{{#useRxJava2}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{{returnType}}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{/doNotUseRx}}{{#doNotUseRx}}Call<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/doNotUseRx}} {{operationId}}({{^allParams}});{{/allParams}} + {{^doNotUseRx}}{{#useRxJava}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/useRxJava}}{{#useRxJava2}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{{returnType}}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{#useRxJava3}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{{returnType}}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava3}}{{/doNotUseRx}}{{#doNotUseRx}}Call<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/doNotUseRx}} {{operationId}}({{^allParams}});{{/allParams}} {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{#hasMore}}, {{/hasMore}}{{^hasMore}} );{{/hasMore}}{{/allParams}} diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index 6a7b8e8cca8..3098d699287 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -145,6 +145,9 @@ ext { {{#useRxJava2}} rx_java_version = "2.1.1" {{/useRxJava2}} + {{#useRxJava3}} + rx_java_version = "3.0.4" + {{/useRxJava3}} {{#joda}} jodatime_version = "2.9.9" {{/joda}} @@ -166,6 +169,10 @@ dependencies { compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' compile "io.reactivex.rxjava2:rxjava:$rx_java_version" {{/useRxJava2}} + {{#useRxJava3}} + compile 'com.github.akarnokd:rxjava3-retrofit-adapter:3.0.0' + compile "io.reactivex.rxjava3:rxjava:$rx_java_version" + {{/useRxJava3}} compile "io.swagger:swagger-annotations:$swagger_annotations_version" compile "com.google.code.findbugs:jsr305:3.0.2" compile ("org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version"){ diff --git a/libraries/retrofit2/build.sbt.mustache b/libraries/retrofit2/build.sbt.mustache index 4c85b1411d2..55d77e1d0de 100644 --- a/libraries/retrofit2/build.sbt.mustache +++ b/libraries/retrofit2/build.sbt.mustache @@ -44,6 +44,10 @@ lazy val root = (project in file(".")). "com.squareup.retrofit2" % "adapter-rxjava2" % "2.3.0" % "compile", "io.reactivex.rxjava2" % "rxjava" % "2.1.1" % "compile", {{/useRxJava2}} + {{#useRxJava3}} + "com.github.akarnokd" % "rxjava3-retrofit-adapter" % "3.0.0" % "compile", + "io.reactivex.rxjava3" % "rxjava" % "3.0.4" % "compile", + {{/useRxJava3}} "io.swagger" % "swagger-annotations" % "1.5.21" % "compile", "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", {{#joda}} diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index 61bacc3bb7c..ba983599e24 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -276,6 +276,18 @@ ${retrofit-version}
{{/useRxJava2}} + {{#useRxJava3}} + + io.reactivex.rxjava3 + rxjava + ${rxjava-version} + + + com.github.akarnokd + rxjava3-retrofit-adapter + 3.0.0 + + {{/useRxJava3}} {{#usePlayWS}} @@ -400,6 +412,9 @@ {{#useRxJava2}} 2.1.1 {{/useRxJava2}} + {{#useRxJava3}} + 3.0.4 + {{/useRxJava3}} {{#joda}} 2.9.9 {{/joda}} From 63d382b6affd05ef074306d81bf8001af1ab9f7c Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Fri, 12 Jun 2020 09:02:45 -0700 Subject: [PATCH 256/370] Fix URL encoding problem for HTTP signatures (#6637) --- .../jersey2/auth/HttpSignatureAuth.mustache | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/libraries/jersey2/auth/HttpSignatureAuth.mustache b/libraries/jersey2/auth/HttpSignatureAuth.mustache index c978de46a0f..744f9f6bd4b 100644 --- a/libraries/jersey2/auth/HttpSignatureAuth.mustache +++ b/libraries/jersey2/auth/HttpSignatureAuth.mustache @@ -234,16 +234,12 @@ public class HttpSignatureAuth implements Authentication { throw new ApiException("Signer cannot be null. Please call the method `setPrivateKey` to set it up correctly"); } - // construct the path with the URL query string - String path = uri.getPath(); - - List urlQueries = new ArrayList(); - for (Pair queryParam : queryParams) { - urlQueries.add(queryParam.getName() + "=" + URLEncoder.encode(queryParam.getValue(), "utf8").replaceAll("\\+", "%20")); - } - - if (!urlQueries.isEmpty()) { - path = path + "?" + String.join("&", urlQueries); + // construct the path with the URL-encoded path and query. + // Calling getRawPath and getRawQuery ensures the path is URL-encoded as it will be serialized + // on the wire. The HTTP signature must use the encode URL as it is sent on the wire. + String path = uri.getRawPath(); + if (uri.getRawQuery() != "") { + path += "?" + uri.getRawQuery(); } headerParams.put("Authorization", signer.sign(method, path, headerParams).toString()); From 9b559ac17fc9bc393b1107a6438f792f28192be8 Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Fri, 12 Jun 2020 09:15:24 -0700 Subject: [PATCH 257/370] [java][jersey2] Add hook to customize SSL context, trust manager and host verifier (#6633) * Add hook to customize SSL context, trust manager and host verifier * run sample scripts --- libraries/jersey2/ApiClient.mustache | 60 +++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 1b2b63c9abe..d0773177c76 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -27,6 +27,13 @@ import java.io.IOException; import java.io.InputStream; import java.net.URI; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.security.cert.X509Certificate; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; {{^supportJava6}} import java.nio.file.Files; import java.nio.file.StandardCopyOption; @@ -1195,13 +1202,64 @@ public class ApiClient { java.util.logging.Logger.getLogger("org.glassfish.jersey.client").setLevel(java.util.logging.Level.SEVERE); } performAdditionalClientConfiguration(clientConfig); - return ClientBuilder.newClient(clientConfig); + ClientBuilder clientBuilder = ClientBuilder.newBuilder(); + customizeClientBuilder(clientBuilder); + clientBuilder = clientBuilder.withConfig(clientConfig); + return clientBuilder.build(); } + /** + * Perform additional configuration of the API client. + * This method can be overriden to customize the API client. + */ protected void performAdditionalClientConfiguration(ClientConfig clientConfig) { // No-op extension point } + /** + * Customize the client builder. + * + * This method can be overriden to customize the API client. For example, this can be used to: + * 1. Set the hostname verifier to be used by the client to verify the endpoint's hostname + * against its identification information. + * 2. Set the client-side key store. + * 3. Set the SSL context that will be used when creating secured transport connections to + * server endpoints from web targets created by the client instance that is using this SSL context. + * 4. Set the client-side trust store. + * + * To completely disable certificate validation (at your own risk), you can + * override this method and invoke disableCertificateValidation(clientBuilder). + */ + protected void customizeClientBuilder(ClientBuilder clientBuilder) { + // No-op extension point + } + + /** + * Disable X.509 certificate validation in TLS connections. + * + * Please note that trusting all certificates is extremely risky. + * This may be useful in a development environment with self-signed certificates. + */ + protected void disableCertificateValidation(ClientBuilder clientBuilder) throws KeyManagementException, NoSuchAlgorithmException { + TrustManager[] trustAllCerts = new X509TrustManager[] { + new X509TrustManager() { + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + @Override + public void checkClientTrusted(X509Certificate[] certs, String authType) { + } + @Override + public void checkServerTrusted(X509Certificate[] certs, String authType) { + } + } + }; + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, trustAllCerts, new SecureRandom()); + clientBuilder.sslContext(sslContext); + } + protected Map> buildResponseHeaders(Response response) { Map> responseHeaders = new HashMap>(); for (Entry> entry: response.getHeaders().entrySet()) { From 982b9eb63dd062ab22b52fc5611443334ab1b071 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Sat, 13 Jun 2020 14:30:22 +0800 Subject: [PATCH 258/370] [Java][Retrofit2] deprecate RxJava 1.x (#6641) * deprecate rxjava1.x * update samples --- libraries/retrofit2/ApiClient.mustache | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/retrofit2/ApiClient.mustache b/libraries/retrofit2/ApiClient.mustache index c0ca8d00c18..42aa2dd351e 100644 --- a/libraries/retrofit2/ApiClient.mustache +++ b/libraries/retrofit2/ApiClient.mustache @@ -152,9 +152,11 @@ public class ApiClient { .baseUrl(baseUrl) {{#useRxJava}} .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) - {{/useRxJava}}{{#useRxJava2}} + {{/useRxJava}} + {{#useRxJava2}} .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) - {{/useRxJava2}}{{#useRxJava3}} + {{/useRxJava2}} + {{#useRxJava3}} .addCallAdapterFactory(RxJava3CallAdapterFactory.create()) {{/useRxJava3}} .addConverterFactory(ScalarsConverterFactory.create()) From ee8ee94543925cc189b2ff272ca954ddcc506eb4 Mon Sep 17 00:00:00 2001 From: Jochen Schalanda Date: Sun, 14 Jun 2020 11:01:18 +0200 Subject: [PATCH 259/370] Fix usage of javax.annotation (#6645) * Fix usage of javax.annotation:javax.annotation-api * Regenerate samples ``` bin/generate-samples.sh bin/configs/java-* bin/configs/jaxrs-* bin/configs/spring-* bin/configs/kotlin-* bin/configs/other/java-* bin/configs/other/jaxrs-* bin/configs/other/kotlin-* bin/configs/other/openapi3/jaxrs-cxf-client.yaml bin/configs/other/openapi3/kotlin-* ``` --- build.gradle.mustache | 1 + generatedAnnotation.mustache | 2 +- libraries/feign/build.gradle.mustache | 1 + libraries/feign/build.sbt.mustache | 1 + libraries/feign/pom.mustache | 7 +++++++ libraries/google-api-client/build.gradle.mustache | 1 + libraries/google-api-client/build.sbt.mustache | 1 + libraries/google-api-client/pom.mustache | 7 +++++++ libraries/jersey2/build.gradle.mustache | 1 + libraries/jersey2/build.sbt.mustache | 1 + libraries/jersey2/pom.mustache | 7 +++++++ libraries/microprofile/generatedAnnotation.mustache | 2 +- libraries/microprofile/pom.mustache | 9 ++++++++- libraries/native/build.gradle.mustache | 1 + libraries/native/generatedAnnotation.mustache | 2 +- libraries/native/pom.mustache | 7 +++++++ libraries/okhttp-gson/build.gradle.mustache | 1 + libraries/okhttp-gson/build.sbt.mustache | 1 + libraries/okhttp-gson/pom.mustache | 1 + libraries/rest-assured/build.gradle.mustache | 1 + libraries/rest-assured/build.sbt.mustache | 1 + libraries/rest-assured/pom.mustache | 5 ++--- libraries/resteasy/build.gradle.mustache | 1 + libraries/resteasy/build.sbt.mustache | 1 + libraries/resteasy/pom.mustache | 7 +++++++ libraries/resttemplate/build.gradle.mustache | 1 + libraries/resttemplate/pom.mustache | 7 +++++++ libraries/retrofit/build.gradle.mustache | 1 + libraries/retrofit/build.sbt.mustache | 1 + libraries/retrofit/pom.mustache | 7 +++++++ libraries/retrofit2/build.gradle.mustache | 2 +- libraries/retrofit2/build.sbt.mustache | 1 + libraries/retrofit2/pom.mustache | 7 +++++++ libraries/vertx/build.gradle.mustache | 1 + libraries/vertx/pom.mustache | 7 +++++++ libraries/webclient/pom.mustache | 7 +++++++ pom.mustache | 7 +++++++ 37 files changed, 111 insertions(+), 8 deletions(-) diff --git a/build.gradle.mustache b/build.gradle.mustache index 38ece474ad8..fd3ca0ede28 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -169,6 +169,7 @@ dependencies { {{^java8}} compile "com.brsanthu:migbase64:2.2" {{/java8}} + compile 'javax.annotation:javax.annotation-api:1.3.2' testCompile "junit:junit:$junit_version" } diff --git a/generatedAnnotation.mustache b/generatedAnnotation.mustache index a47b6faa85b..875d7b97afe 100644 --- a/generatedAnnotation.mustache +++ b/generatedAnnotation.mustache @@ -1 +1 @@ -{{^hideGenerationTimestamp}}@javax.annotation.Generated(value = "{{generatorClass}}", date = "{{generatedDate}}"){{/hideGenerationTimestamp}} \ No newline at end of file +@javax.annotation.Generated(value = "{{generatorClass}}"{{^hideGenerationTimestamp}}, date = "{{generatedDate}}"{{/hideGenerationTimestamp}}) \ No newline at end of file diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index 86cdad95f82..8302b841064 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -154,5 +154,6 @@ dependencies { {{/threetenbp}} compile "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version" compile "com.brsanthu:migbase64:2.2" + compile 'javax.annotation:javax.annotation-api:1.3.2' testCompile "junit:junit:$junit_version" } diff --git a/libraries/feign/build.sbt.mustache b/libraries/feign/build.sbt.mustache index cd55527b8ec..e5caa1b2000 100644 --- a/libraries/feign/build.sbt.mustache +++ b/libraries/feign/build.sbt.mustache @@ -21,6 +21,7 @@ lazy val root = (project in file(".")). "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", "com.brsanthu" % "migbase64" % "2.2" % "compile", + "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index a40806b32e9..1c4517f7c40 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -304,6 +304,12 @@ org.apache.oltu.oauth2.client ${oltu-version} + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + @@ -339,6 +345,7 @@ {{#threetenbp}} 2.9.10 {{/threetenbp}} + 1.3.2 4.13 1.0.0 1.0.1 diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache index f6a517fbb92..d6e5035dc5d 100644 --- a/libraries/google-api-client/build.gradle.mustache +++ b/libraries/google-api-client/build.gradle.mustache @@ -155,5 +155,6 @@ dependencies { {{#withXml}} compile "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jackson_version" {{/withXml}} + compile 'javax.annotation:javax.annotation-api:1.3.2' testCompile "junit:junit:$junit_version" } diff --git a/libraries/google-api-client/build.sbt.mustache b/libraries/google-api-client/build.sbt.mustache index 516fe0eb90e..de076de7db2 100644 --- a/libraries/google-api-client/build.sbt.mustache +++ b/libraries/google-api-client/build.sbt.mustache @@ -27,6 +27,7 @@ lazy val root = (project in file(".")). {{#threetenbp}} "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", {{/threetenbp}} + "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index 2412ba208ec..da57a9df7f7 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -295,6 +295,12 @@ ${jackson-threetenbp-version} {{/threetenbp}} + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + @@ -318,6 +324,7 @@ {{#threetenbp}} 2.9.10 {{/threetenbp}} + 1.3.2 1.0.0 4.13 diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index 270585b5b28..fa00d428c3f 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -174,6 +174,7 @@ dependencies { {{^java8}} compile "com.brsanthu:migbase64:2.2" {{/java8}} + compile 'javax.annotation:javax.annotation-api:1.3.2' testCompile "junit:junit:$junit_version" } diff --git a/libraries/jersey2/build.sbt.mustache b/libraries/jersey2/build.sbt.mustache index 4cb53ac02e2..d4262ef3fdd 100644 --- a/libraries/jersey2/build.sbt.mustache +++ b/libraries/jersey2/build.sbt.mustache @@ -38,6 +38,7 @@ lazy val root = (project in file(".")). "org.apache.commons" % "commons-lang3" % "3.6", "commons-io" % "commons-io" % "2.5", {{/supportJava6}} + "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 9938e104641..53477e978e3 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -362,6 +362,12 @@ provided {{/useBeanValidation}} + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + junit @@ -387,6 +393,7 @@ {{#threetenbp}} 2.9.10 {{/threetenbp}} + 1.3.2 4.13 {{#hasHttpSignatureMethods}} 1.4 diff --git a/libraries/microprofile/generatedAnnotation.mustache b/libraries/microprofile/generatedAnnotation.mustache index 49110fc1ad9..875d7b97afe 100644 --- a/libraries/microprofile/generatedAnnotation.mustache +++ b/libraries/microprofile/generatedAnnotation.mustache @@ -1 +1 @@ -@javax.annotation.Generated(value = "{{generatorClass}}", date = "{{generatedDate}}") \ No newline at end of file +@javax.annotation.Generated(value = "{{generatorClass}}"{{^hideGenerationTimestamp}}, date = "{{generatedDate}}"{{/hideGenerationTimestamp}}) \ No newline at end of file diff --git a/libraries/microprofile/pom.mustache b/libraries/microprofile/pom.mustache index ca7d6b7a830..381c9f81898 100644 --- a/libraries/microprofile/pom.mustache +++ b/libraries/microprofile/pom.mustache @@ -143,7 +143,13 @@ hibernate-validator 5.2.2.Final -{{/useBeanValidationFeature}} +{{/useBeanValidationFeature}} + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + @@ -168,6 +174,7 @@ {{/useBeanValidation}} 3.2.7 2.9.7 + 1.3.2 UTF-8 diff --git a/libraries/native/build.gradle.mustache b/libraries/native/build.gradle.mustache index cea6681a95e..c68123d6df1 100644 --- a/libraries/native/build.gradle.mustache +++ b/libraries/native/build.gradle.mustache @@ -62,5 +62,6 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + compile 'javax.annotation:javax.annotation-api:1.3.2' testCompile "junit:junit:$junit_version" } diff --git a/libraries/native/generatedAnnotation.mustache b/libraries/native/generatedAnnotation.mustache index dc1f2cd40e9..baf5ff08b49 100644 --- a/libraries/native/generatedAnnotation.mustache +++ b/libraries/native/generatedAnnotation.mustache @@ -1 +1 @@ -{{^hideGenerationTimestamp}}@javax.annotation.processing.Generated(value = "{{generatorClass}}", date = "{{generatedDate}}"){{/hideGenerationTimestamp}} \ No newline at end of file +@javax.annotation.processing.Generated(value = "{{generatorClass}}"{{^hideGenerationTimestamp}}, date = "{{generatedDate}}"{{/hideGenerationTimestamp}}) \ No newline at end of file diff --git a/libraries/native/pom.mustache b/libraries/native/pom.mustache index 7e6ebb2f950..d9f160341c2 100644 --- a/libraries/native/pom.mustache +++ b/libraries/native/pom.mustache @@ -200,6 +200,12 @@ jsr305 3.0.2 + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + @@ -216,6 +222,7 @@ 11 2.9.9 0.2.1 + 1.3.2 4.13 diff --git a/libraries/okhttp-gson/build.gradle.mustache b/libraries/okhttp-gson/build.gradle.mustache index 91913276775..405261e7600 100644 --- a/libraries/okhttp-gson/build.gradle.mustache +++ b/libraries/okhttp-gson/build.gradle.mustache @@ -142,6 +142,7 @@ dependencies { {{#threetenbp}} compile 'org.threeten:threetenbp:1.4.3' {{/threetenbp}} + compile 'javax.annotation:javax.annotation-api:1.3.2' testCompile 'junit:junit:4.13' } diff --git a/libraries/okhttp-gson/build.sbt.mustache b/libraries/okhttp-gson/build.sbt.mustache index 7c137589e37..12783935f16 100644 --- a/libraries/okhttp-gson/build.sbt.mustache +++ b/libraries/okhttp-gson/build.sbt.mustache @@ -26,6 +26,7 @@ lazy val root = (project in file(".")). "io.gsonfire" % "gson-fire" % "1.8.3" % "compile", "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", "com.google.code.findbugs" % "jsr305" % "3.0.2" % "compile", + "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index b6d67f28350..41bbd03864b 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -309,6 +309,7 @@ javax.annotation javax.annotation-api ${javax-annotation-version} + provided diff --git a/libraries/rest-assured/build.gradle.mustache b/libraries/rest-assured/build.gradle.mustache index 0868a2aa7c0..2e94cb0e0b4 100644 --- a/libraries/rest-assured/build.gradle.mustache +++ b/libraries/rest-assured/build.gradle.mustache @@ -159,5 +159,6 @@ dependencies { {{#performBeanValidation}} compile "org.hibernate:hibernate-validator:6.0.19.Final" {{/performBeanValidation}} + compile 'javax.annotation:javax.annotation-api:1.3.2' testCompile "junit:junit:$junit_version" } diff --git a/libraries/rest-assured/build.sbt.mustache b/libraries/rest-assured/build.sbt.mustache index 955f515fc70..7b506a49b23 100644 --- a/libraries/rest-assured/build.sbt.mustache +++ b/libraries/rest-assured/build.sbt.mustache @@ -48,6 +48,7 @@ lazy val root = (project in file(".")). {{#performBeanValidation}} "org.hibernate" % "hibernate-validator" % "6.0.19.Final" % "compile", {{/performBeanValidation}} + "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) diff --git a/libraries/rest-assured/pom.mustache b/libraries/rest-assured/pom.mustache index 2e68695d431..7c49b4c448c 100644 --- a/libraries/rest-assured/pom.mustache +++ b/libraries/rest-assured/pom.mustache @@ -229,14 +229,12 @@ jsr305 3.0.2 - {{^hideGenerationTimestamp}} javax.annotation javax.annotation-api - 1.3.2 + ${javax-annotation-version} provided - {{/hideGenerationTimestamp}} io.rest-assured rest-assured @@ -364,6 +362,7 @@ 2.10.0 {{/threetenbp}} {{/jackson}} + 1.3.2 1.17.5 4.13 diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index a3973d45951..302b1839d51 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -157,5 +157,6 @@ dependencies { compile "commons-io:commons-io:$commons_io_version" compile "org.apache.commons:commons-lang3:$commons_lang3_version" {{/supportJava6}} + compile 'javax.annotation:javax.annotation-api:1.3.2' testCompile "junit:junit:$junit_version" } diff --git a/libraries/resteasy/build.sbt.mustache b/libraries/resteasy/build.sbt.mustache index d265cf2a630..4c079bcffd8 100644 --- a/libraries/resteasy/build.sbt.mustache +++ b/libraries/resteasy/build.sbt.mustache @@ -29,6 +29,7 @@ lazy val root = (project in file(".")). "org.apache.commons" % "commons-lang3" % "3.5" % "compile", "commons-io" % "commons-io" % "2.5" % "compile", {{/supportJava6}} + "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index d09da29b472..4e93ec65f5e 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -285,6 +285,12 @@ jackson-datatype-threetenbp ${threetenbp-version} + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + junit @@ -300,6 +306,7 @@ 2.10.4 2.10.4 0.2.1 + 1.3.2 2.9.10 {{^java8}} 2.9.9 diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index 4eb1e7d212e..7190f95a95f 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -153,5 +153,6 @@ dependencies { {{#withXml}} compile "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jackson_version" {{/withXml}} + compile 'javax.annotation:javax.annotation-api:1.3.2' testCompile "junit:junit:$junit_version" } diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache index 708e02dffc1..f3a1f0abda9 100644 --- a/libraries/resttemplate/pom.mustache +++ b/libraries/resttemplate/pom.mustache @@ -299,6 +299,12 @@ ${jackson-threetenbp-version} {{/threetenbp}} + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + @@ -315,6 +321,7 @@ 2.10.4 2.10.4 0.2.1 + 1.3.2 {{#joda}} 2.9.9 {{/joda}} diff --git a/libraries/retrofit/build.gradle.mustache b/libraries/retrofit/build.gradle.mustache index fab2f0d9fe2..e610846f49d 100644 --- a/libraries/retrofit/build.gradle.mustache +++ b/libraries/retrofit/build.gradle.mustache @@ -128,5 +128,6 @@ dependencies { {{#threetenbp}} compile "org.threeten:threetenbp:$threetenbp_version" {{/threetenbp}} + compile 'javax.annotation:javax.annotation-api:1.3.2' testCompile "junit:junit:$junit_version" } diff --git a/libraries/retrofit/build.sbt.mustache b/libraries/retrofit/build.sbt.mustache index 360f53d1ae8..d55bb7c78b4 100644 --- a/libraries/retrofit/build.sbt.mustache +++ b/libraries/retrofit/build.sbt.mustache @@ -17,6 +17,7 @@ lazy val root = (project in file(".")). {{#threetenbp}} "org.threeten" % "threetenbp" % "1.4.0" % "compile", {{/threetenbp}} + "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) diff --git a/libraries/retrofit/pom.mustache b/libraries/retrofit/pom.mustache index 7c689ae4b6c..7def21d411f 100644 --- a/libraries/retrofit/pom.mustache +++ b/libraries/retrofit/pom.mustache @@ -264,6 +264,12 @@ provided {{/parcelableModel}} + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + junit @@ -282,6 +288,7 @@ 1.4.0 {{/threetenbp}} 1.0.1 + 1.3.2 1.0.0 4.13 diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index 3098d699287..4279b21cf47 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -200,6 +200,6 @@ dependencies { compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" compile "com.fasterxml.jackson.datatype:jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}:$jackson_version" {{/usePlayWS}} - + compile 'javax.annotation:javax.annotation-api:1.3.2' testCompile "junit:junit:$junit_version" } diff --git a/libraries/retrofit2/build.sbt.mustache b/libraries/retrofit2/build.sbt.mustache index 55d77e1d0de..8292f12f4e6 100644 --- a/libraries/retrofit2/build.sbt.mustache +++ b/libraries/retrofit2/build.sbt.mustache @@ -57,6 +57,7 @@ lazy val root = (project in file(".")). "org.threeten" % "threetenbp" % "1.4.0" % "compile", {{/threetenbp}} "io.gsonfire" % "gson-fire" % "1.8.0" % "compile", + "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.11" % "test" ) diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index ba983599e24..119ccaab2d4 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -374,6 +374,12 @@ provided {{/parcelableModel}} + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + junit @@ -421,6 +427,7 @@ {{#threetenbp}} 1.4.0 {{/threetenbp}} + 1.3.2 1.0.1 4.13 diff --git a/libraries/vertx/build.gradle.mustache b/libraries/vertx/build.gradle.mustache index c6c76b8e8b8..742f19fd1cf 100644 --- a/libraries/vertx/build.gradle.mustache +++ b/libraries/vertx/build.gradle.mustache @@ -53,6 +53,7 @@ dependencies { compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_version" {{/threetenbp}} compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + compile 'javax.annotation:javax.annotation-api:1.3.2' testCompile "junit:junit:$junit_version" testCompile "io.vertx:vertx-unit:$vertx_version" } diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache index 587a6e76cc4..737f09435d6 100644 --- a/libraries/vertx/pom.mustache +++ b/libraries/vertx/pom.mustache @@ -272,6 +272,12 @@ ${jackson-version} {{/threetenbp}} + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + @@ -295,6 +301,7 @@ 2.10.4 2.10.4 0.2.1 + 1.3.2 4.13 diff --git a/libraries/webclient/pom.mustache b/libraries/webclient/pom.mustache index 138270ea3f9..b3bcdc1ecc4 100644 --- a/libraries/webclient/pom.mustache +++ b/libraries/webclient/pom.mustache @@ -130,6 +130,12 @@ ${jodatime-version} {{/joda}} + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + @@ -146,6 +152,7 @@ 2.10.3 2.10.3 0.2.1 + 1.3.2 4.13 3.1.8.RELEASE 0.7.8.RELEASE diff --git a/pom.mustache b/pom.mustache index e9cbf546b6d..b543073f635 100644 --- a/pom.mustache +++ b/pom.mustache @@ -356,6 +356,12 @@ provided {{/parcelableModel}} + + javax.annotation + javax.annotation-api + ${javax-annotation-version} + provided + junit @@ -376,6 +382,7 @@ {{#threetenbp}} 2.9.10 {{/threetenbp}} + 1.3.2 1.0.0 4.13 From 0e3c34901117905686b3133f1eb01e091636f40b Mon Sep 17 00:00:00 2001 From: Jonathan Goldman Date: Sun, 14 Jun 2020 21:35:58 -0400 Subject: [PATCH 260/370] [Java] Add add constructor to BYO OkHttpClient (#6401) * [Java] Add add constructor to BYO OkHttpClient * client example * this client changed too --- libraries/okhttp-gson/ApiClient.mustache | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index 3969c08d391..0b74114ac5e 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -102,6 +102,23 @@ public class ApiClient { authentications = Collections.unmodifiableMap(authentications); } + /* + * Basic constructor with custom OkHttpClient + */ + public ApiClient(OkHttpClient client) { + init(); + + httpClient = client; + + // Setup authentications (key: authentication name, value: authentication).{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + } + {{#hasOAuthMethods}} {{#oauthMethods}} {{#-first}} From 4888d21d9051f52f1455b1b26de3adb3299872dc Mon Sep 17 00:00:00 2001 From: William Cheng Date: Tue, 16 Jun 2020 22:08:59 +0800 Subject: [PATCH 261/370] [java] Specify Java version for maven-javadoc-plugin (fixes Java 11 error) (#6679) * Add jersey2-experimental to petstore build script on-behalf-of: @nqminds * [java] Add to javadoc in pom.mustache We add the following tag to the of maven-javadoc-plugin for most pom.mustache files that use it. This tells javadoc which version of java the compiler used. This fixes the following error when running Java 11: [ERROR] Exit code: 1 - javadoc: error - The code being documented uses modules but the packages defined in https://docs.oracle.com/javase/8/docs/api/ are in the unnamed module Additionally, we also add maven-compiler-plugin to jersey2/pom.mustache to specify that the source code is Java 6/7/8. on-behalf-of: @nqminds * [java-jersey2-java6] Update failing old tests Pull-request #4666 changed jersey generation, but didn't update the test samples Tests now succeed. on-behalf-of: @nqminds * [java-retrofit2-play24] Fix integration-tests Running mvn integration-test failed in samples/client/petstore/java/retrofit2-play24 This merges pull requests #1735 and #5527 into retrofit2-play24. Also removes the jackson-databind-version field, since it should always be the same as jackson-version, and updates build.gradle/build.sbt on-behalf-of: @nqminds Co-authored-by: Alois Klink --- libraries/feign/pom.mustache | 11 ++++ libraries/google-api-client/pom.mustache | 11 ++++ libraries/jersey2/pom.mustache | 11 ++++ libraries/rest-assured/pom.mustache | 1 + libraries/resteasy/pom.mustache | 11 ++++ libraries/retrofit/pom.mustache | 11 ++++ libraries/retrofit2/build.gradle.mustache | 8 +-- libraries/retrofit2/build.sbt.mustache | 10 +--- .../play24/Play24CallFactory.mustache | 9 +++ libraries/retrofit2/pom.mustache | 59 ++++++++++++------- libraries/vertx/pom.mustache | 11 ++++ pom.mustache | 11 ++++ 12 files changed, 131 insertions(+), 33 deletions(-) diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index 1c4517f7c40..b76784db04a 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -161,6 +161,17 @@ 3.1.1 none + {{#supportJava6}} + 1.6 + {{/supportJava6}} + {{^supportJava6}} + {{#java8}} + 1.8 + {{/java8}} + {{^java8}} + 1.7 + {{/java8}} + {{/supportJava6}} diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index da57a9df7f7..203685fe6b6 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -166,6 +166,17 @@ 3.1.1 none + {{#supportJava6}} + 1.6 + {{/supportJava6}} + {{^supportJava6}} + {{#java8}} + 1.8 + {{/java8}} + {{^java8}} + 1.7 + {{/java8}} + {{/supportJava6}} diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 53477e978e3..155f306546c 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -182,6 +182,17 @@ none + {{#supportJava6}} + 1.6 + {{/supportJava6}} + {{^supportJava6}} + {{#java8}} + 1.8 + {{/java8}} + {{^java8}} + 1.7 + {{/java8}} + {{/supportJava6}} http.response.details diff --git a/libraries/rest-assured/pom.mustache b/libraries/rest-assured/pom.mustache index 7c49b4c448c..4009b48e876 100644 --- a/libraries/rest-assured/pom.mustache +++ b/libraries/rest-assured/pom.mustache @@ -153,6 +153,7 @@ 3.2.0 none + 1.8 diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index 4e93ec65f5e..35c915d45fb 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -164,6 +164,17 @@ 3.1.1 none + {{#supportJava6}} + 1.6 + {{/supportJava6}} + {{^supportJava6}} + {{#java8}} + 1.8 + {{/java8}} + {{^java8}} + 1.7 + {{/java8}} + {{/supportJava6}} diff --git a/libraries/retrofit/pom.mustache b/libraries/retrofit/pom.mustache index 7def21d411f..d7cd63d9e12 100644 --- a/libraries/retrofit/pom.mustache +++ b/libraries/retrofit/pom.mustache @@ -166,6 +166,17 @@ 3.1.1 none + {{#supportJava6}} + 1.6 + {{/supportJava6}} + {{^supportJava6}} + {{#java8}} + 1.8 + {{/java8}} + {{^java8}} + 1.7 + {{/java8}} + {{/supportJava6}} diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index 4279b21cf47..c0c622fa034 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -122,18 +122,16 @@ ext { oltu_version = "1.0.1" retrofit_version = "2.3.0" {{#usePlayWS}} + jackson_version = "2.10.4" + jackson_databind_version = "2.10.4" + jackson_databind_nullable_version = "0.2.1" {{#play24}} - jackson_version = "2.6.6" play_version = "2.4.11" {{/play24}} {{#play25}} - jackson_version = "2.10.4" play_version = "2.5.14" {{/play25}} {{#play26}} - jackson_version = "2.10.4" - jackson_databind_version = "2.10.4" - jackson_databind_nullable_version = "0.2.1" play_version = "2.6.7" {{/play26}} {{/usePlayWS}} diff --git a/libraries/retrofit2/build.sbt.mustache b/libraries/retrofit2/build.sbt.mustache index 8292f12f4e6..c7785d9e392 100644 --- a/libraries/retrofit2/build.sbt.mustache +++ b/libraries/retrofit2/build.sbt.mustache @@ -17,24 +17,18 @@ lazy val root = (project in file(".")). {{#usePlayWS}} {{#play24}} "com.typesafe.play" % "play-java-ws_2.11" % "2.4.11" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.6.6" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.6.6" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.6.6" % "compile", {{/play24}} {{#play25}} "com.typesafe.play" % "play-java-ws_2.11" % "2.5.15" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.4" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.4" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.4" % "compile", {{/play25}} {{#play26}} "com.typesafe.play" % "play-ahc-ws_2.12" % "2.6.7" % "compile", "javax.validation" % "validation-api" % "1.1.0.Final" % "compile", + {{/play26}} + "com.squareup.retrofit2" % "converter-jackson" % "2.3.0" % "compile", "com.fasterxml.jackson.core" % "jackson-core" % "2.10.4" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.4" % "compile", "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.4" % "compile", - {{/play26}} - "com.squareup.retrofit2" % "converter-jackson" % "2.3.0" % "compile", {{/usePlayWS}} {{#useRxJava}} "com.squareup.retrofit2" % "adapter-rxjava" % "2.3.0" % "compile", diff --git a/libraries/retrofit2/play24/Play24CallFactory.mustache b/libraries/retrofit2/play24/Play24CallFactory.mustache index 344fadd2e3e..b17ac641564 100644 --- a/libraries/retrofit2/play24/Play24CallFactory.mustache +++ b/libraries/retrofit2/play24/Play24CallFactory.mustache @@ -1,8 +1,10 @@ package {{invokerPackage}}; import okhttp3.*; +import okio.AsyncTimeout; import okio.Buffer; import okio.BufferedSource; +import okio.Timeout; import play.libs.F; import play.libs.ws.WSClient; import play.libs.ws.WSRequest; @@ -95,10 +97,12 @@ public class Play24CallFactory implements okhttp3.Call.Factory { private WSRequest wsRequest; private final Request request; + private final AsyncTimeout timeout; public PlayWSCall(WSClient wsClient, Request request) { this.wsClient = wsClient; this.request = request; + this.timeout = new AsyncTimeout(); } @Override @@ -106,6 +110,11 @@ public class Play24CallFactory implements okhttp3.Call.Factory { return request; } + @Override + public Timeout timeout() { + return timeout; + } + @Override public void enqueue(final okhttp3.Callback responseCallback) { final Call call = this; diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index 119ccaab2d4..c8591422ae8 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -139,12 +139,44 @@ + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + {{#supportJava6}} + 1.6 + 1.6 + {{/supportJava6}} + {{^supportJava6}} + {{#java8}} + 1.8 + 1.8 + {{/java8}} + {{^java8}} + 1.7 + 1.7 + {{/java8}} + {{/supportJava6}} + + org.apache.maven.plugins maven-javadoc-plugin 3.1.1 none + {{#supportJava6}} + 1.6 + {{/supportJava6}} + {{^supportJava6}} + {{#java8}} + 1.8 + {{/java8}} + {{^java8}} + 1.7 + {{/java8}} + {{/supportJava6}} @@ -308,7 +340,12 @@ com.fasterxml.jackson.core jackson-databind - ${jackson-databind-version} + ${jackson-version} + + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} com.fasterxml.jackson.datatype @@ -329,11 +366,6 @@ play-java-ws_2.11 ${play-version} - - org.openapitools - jackson-databind-nullable - ${jackson-databind-nullable-version} - {{/play24}} {{#play25}} @@ -341,11 +373,6 @@ play-java-ws_2.11 ${play-version} - - org.openapitools - jackson-databind-nullable - ${jackson-databind-nullable-version} - {{/play25}} {{#play26}} @@ -358,11 +385,6 @@ validation-api 1.1.0.Final - - org.openapitools - jackson-databind-nullable - ${jackson-databind-nullable-version} - {{/play26}} {{/usePlayWS}} {{#parcelableModel}} @@ -396,17 +418,14 @@ 1.8.3 1.5.22 {{#usePlayWS}} - 2.10.3 + 2.10.4 {{#play24}} - 2.6.6 2.4.11 {{/play24}} {{#play25}} - 2.10.4 2.5.15 {{/play25}} {{#play26}} - 2.10.4 2.6.7 {{/play26}} 0.2.1 diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache index 737f09435d6..310db959c48 100644 --- a/libraries/vertx/pom.mustache +++ b/libraries/vertx/pom.mustache @@ -154,6 +154,17 @@ 3.1.1 none + {{#supportJava6}} + 1.6 + {{/supportJava6}} + {{^supportJava6}} + {{#java8}} + 1.8 + {{/java8}} + {{^java8}} + 1.7 + {{/java8}} + {{/supportJava6}} diff --git a/pom.mustache b/pom.mustache index b543073f635..5cae3afa36d 100644 --- a/pom.mustache +++ b/pom.mustache @@ -181,6 +181,17 @@ 3.1.1 none + {{#supportJava6}} + 1.6 + {{/supportJava6}} + {{^supportJava6}} + {{#java8}} + 1.8 + {{/java8}} + {{^java8}} + 1.7 + {{/java8}} + {{/supportJava6}} From fc1cdc93fa0faf7eec69ec65953a6439d6762ed1 Mon Sep 17 00:00:00 2001 From: Ravisankar-Challa Date: Wed, 17 Jun 2020 16:56:02 +1000 Subject: [PATCH 262/370] [Java][MicroProfile] Use jsonb imports for serializing and deserializing enum (#6064) * Use jsonb imports for serializing and deserializing pojo * Fix: Exclude jsonbProperty class when withXml=true Co-authored-by: Ravisankar Challa --- libraries/microprofile/enumClass.mustache | 35 ++++++++++++++++++++++- libraries/microprofile/pojo.mustache | 15 ++++++++++ libraries/microprofile/pom.mustache | 5 ++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/libraries/microprofile/enumClass.mustache b/libraries/microprofile/enumClass.mustache index 5bdcf238a2c..8fc406681de 100644 --- a/libraries/microprofile/enumClass.mustache +++ b/libraries/microprofile/enumClass.mustache @@ -1,13 +1,24 @@ +{{#withXml}} @XmlType(name="{{datatypeWithEnum}}") @XmlEnum({{dataType}}.class) +{{/withXml}} +{{^withXml}} +@JsonbTypeSerializer({{datatypeWithEnum}}.Serializer.class) +@JsonbTypeDeserializer({{datatypeWithEnum}}.Deserializer.class) +{{/withXml}} public enum {{datatypeWithEnum}} { {{#allowableValues}} + {{#withXml}} {{#enumVars}}@XmlEnumValue({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) {{name}}({{dataType}}.valueOf({{{value}}})){{^-last}}, {{/-last}}{{#-last}};{{/-last}}{{/enumVars}} + {{/withXml}} + {{^withXml}} +{{#enumVars}}{{name}}({{dataType}}.valueOf({{{value}}})){{^-last}}, {{/-last}}{{#-last}};{{/-last}}{{/enumVars}} + {{/withXml}} {{/allowableValues}} - private {{dataType}} value; + {{dataType}} value; {{datatypeWithEnum}} ({{dataType}} v) { value = v; @@ -22,6 +33,7 @@ public enum {{datatypeWithEnum}} { return String.valueOf(value); } + {{#withXml}} public static {{datatypeWithEnum}} fromValue(String v) { for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { if (String.valueOf(b.value).equals(v)) { @@ -30,4 +42,25 @@ public enum {{datatypeWithEnum}} { } {{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + v + "'");{{/useNullForUnknownEnumValue}} } + {{/withXml}} + {{^withXml}} + public static final class Deserializer implements JsonbDeserializer<{{datatypeWithEnum}}> { + @Override + public {{datatypeWithEnum}} deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) { + for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + if (String.valueOf(b.value).equals(parser.getString())) { + return b; + } + } + {{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + parser.getString() + "'");{{/useNullForUnknownEnumValue}} + } + } + + public static final class Serializer implements JsonbSerializer<{{datatypeWithEnum}}> { + @Override + public void serialize({{datatypeWithEnum}} obj, JsonGenerator generator, SerializationContext ctx) { + generator.write(obj.value); + } + } + {{/withXml}} } diff --git a/libraries/microprofile/pojo.mustache b/libraries/microprofile/pojo.mustache index 4ded8e94e2e..0cde7940d3f 100644 --- a/libraries/microprofile/pojo.mustache +++ b/libraries/microprofile/pojo.mustache @@ -1,3 +1,4 @@ +{{#withXml}} import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlAccessType; @@ -5,7 +6,19 @@ import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.XmlEnum; import javax.xml.bind.annotation.XmlEnumValue; +{{/withXml}} +{{^withXml}} +import java.lang.reflect.Type; +import javax.json.bind.annotation.JsonbTypeDeserializer; +import javax.json.bind.annotation.JsonbTypeSerializer; +import javax.json.bind.serializer.DeserializationContext; +import javax.json.bind.serializer.JsonbDeserializer; +import javax.json.bind.serializer.JsonbSerializer; +import javax.json.bind.serializer.SerializationContext; +import javax.json.stream.JsonGenerator; +import javax.json.stream.JsonParser; import javax.json.bind.annotation.JsonbProperty; +{{/withXml}} {{#withXml}} @XmlAccessorType(XmlAccessType.FIELD) @@ -56,7 +69,9 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}}{{#serializ {{/maximum}} * @return {{name}} **/ + {{^withXml}} @JsonbProperty("{{baseName}}") + {{/withXml}} {{#vendorExtensions.x-extra-annotation}} {{{vendorExtensions.x-extra-annotation}}} {{/vendorExtensions.x-extra-annotation}} diff --git a/libraries/microprofile/pom.mustache b/libraries/microprofile/pom.mustache index 381c9f81898..ad160732687 100644 --- a/libraries/microprofile/pom.mustache +++ b/libraries/microprofile/pom.mustache @@ -102,6 +102,11 @@ javax.json.bind-api 1.0 + + javax.json + javax.json-api + 1.1.4 + javax.xml.bind jaxb-api From 64b3722a866ec7f95dae3b24c62ccb95e597293d Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 17 Jun 2020 22:45:26 +0800 Subject: [PATCH 263/370] add getActualInstanceRecursively (#6636) --- .../jersey2/AbstractOpenApiSchema.mustache | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/libraries/jersey2/AbstractOpenApiSchema.mustache b/libraries/jersey2/AbstractOpenApiSchema.mustache index e824f44ae3f..d51d4497283 100644 --- a/libraries/jersey2/AbstractOpenApiSchema.mustache +++ b/libraries/jersey2/AbstractOpenApiSchema.mustache @@ -52,6 +52,25 @@ public abstract class AbstractOpenApiSchema { */ public void setActualInstance(Object instance) {this.instance = instance;} + /** + * Get the instant recursively when the schemas defined in oneOf/anyof happen to be oneOf/anyOf schema as well + * + * @return an instance of the actual schema/object + */ + public Object getActualInstanceRecursively() { + return getActualInstanceRecursively(this); + } + + private Object getActualInstanceRecursively(AbstractOpenApiSchema object) { + if (object.getActualInstance() == null) { + return null; + } else if (object.getActualInstance() instanceof AbstractOpenApiSchema) { + return getActualInstanceRecursively((AbstractOpenApiSchema)object.getActualInstance()); + } else { + return object.getActualInstance(); + } + } + /** * Get the schema type (e.g. anyOf, oneOf) * From 888fc36d3f85082997844ff44f967f0c04ef7ada Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Thu, 18 Jun 2020 08:17:00 -0700 Subject: [PATCH 264/370] [java][jersey2] Fix processing of additional, undeclared properties (#6647) * Add unit tests for additional properties * add unit tests * Add unit tests and fix processing of additionalProperties * fix deserialization issue with additional properties --- libraries/jersey2/anyof_model.mustache | 29 +++++--------------------- libraries/jersey2/oneof_model.mustache | 29 +++++--------------------- libraries/jersey2/pojo.mustache | 3 +++ 3 files changed, 13 insertions(+), 48 deletions(-) diff --git a/libraries/jersey2/anyof_model.mustache b/libraries/jersey2/anyof_model.mustache index ef91fb3204b..e23cece67dd 100644 --- a/libraries/jersey2/anyof_model.mustache +++ b/libraries/jersey2/anyof_model.mustache @@ -84,28 +84,6 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im throw new IOException(String.format("Failed deserialization for {{classname}}: no match found")); } - {{#additionalPropertiesType}} - /** - * Method called to deal with a property that did not map to a known Bean property. - * Method can deal with the problem as it sees fit (ignore, throw exception); but if it does return, - * it has to skip the matching Json content parser has. - * - * @param p - Parser that points to value of the unknown property - * @param ctxt - Context for deserialization; allows access to the parser, error reporting functionality - * @param instanceOrClass - Instance that is being populated by this deserializer, or if not known, Class that would be instantiated. If null, will assume type is what getValueClass() returns. - * @param propName - Name of the property that cannot be mapped - */ - @Override - protected void handleUnknownProperty(JsonParser p, - DeserializationContext ctxt, - Object instanceOrClass, - String propName) throws IOException { - System.out.println("Deserializing unknown property " + propName); - {{{.}}} deserialized = p.readValueAs({{{.}}}.class); - additionalProperties.put(propName, deserialized); - } - {{/additionalPropertiesType}} - /** * Handle deserialization of the 'null' value. */ @@ -128,14 +106,17 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im } {{> libraries/jersey2/additional_properties }} {{#additionalPropertiesType}} + /** + * Return true if this {{name}} object is equal to o. + */ @Override public boolean equals(Object o) { - return super.equals(o) && Objects.equals(this.additionalProperties, o.additionalProperties) + return super.equals(o) && Objects.equals(this.additionalProperties, (({{classname}})o).additionalProperties); } @Override public int hashCode() { - return Objects.hash(instance, isNullable, schemaType, additionalProperties); + return Objects.hash(getActualInstance(), isNullable(), getSchemaType(), additionalProperties); } {{/additionalPropertiesType}} {{#anyOf}} diff --git a/libraries/jersey2/oneof_model.mustache b/libraries/jersey2/oneof_model.mustache index 2289c28360a..dedc9d634f7 100644 --- a/libraries/jersey2/oneof_model.mustache +++ b/libraries/jersey2/oneof_model.mustache @@ -97,28 +97,6 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im throw new IOException(String.format("Failed deserialization for {{classname}}: %d classes match result, expected 1", match)); } - {{#additionalPropertiesType}} - /** - * Method called to deal with a property that did not map to a known Bean property. - * Method can deal with the problem as it sees fit (ignore, throw exception); but if it does return, - * it has to skip the matching Json content parser has. - * - * @param p - Parser that points to value of the unknown property - * @param ctxt - Context for deserialization; allows access to the parser, error reporting functionality - * @param instanceOrClass - Instance that is being populated by this deserializer, or if not known, Class that would be instantiated. If null, will assume type is what getValueClass() returns. - * @param propName - Name of the property that cannot be mapped - */ - @Override - protected void handleUnknownProperty(JsonParser p, - DeserializationContext ctxt, - Object instanceOrClass, - String propName) throws IOException { - System.out.println("Deserializing unknown property " + propName); - {{{.}}} deserialized = p.readValueAs({{{.}}}.class); - additionalProperties.put(propName, deserialized); - } - {{/additionalPropertiesType}} - /** * Handle deserialization of the 'null' value. */ @@ -141,14 +119,17 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im } {{> libraries/jersey2/additional_properties }} {{#additionalPropertiesType}} + /** + * Return true if this {{name}} object is equal to o. + */ @Override public boolean equals(Object o) { - return super.equals(o) && Objects.equals(this.additionalProperties, o.additionalProperties) + return super.equals(o) && Objects.equals(this.additionalProperties, (({{classname}})o).additionalProperties); } @Override public int hashCode() { - return Objects.hash(instance, isNullable, schemaType, additionalProperties); + return Objects.hash(getActualInstance(), isNullable(), getSchemaType(), additionalProperties); } {{/additionalPropertiesType}} {{#oneOf}} diff --git a/libraries/jersey2/pojo.mustache b/libraries/jersey2/pojo.mustache index af6f2491cbd..a74a9d35f4a 100644 --- a/libraries/jersey2/pojo.mustache +++ b/libraries/jersey2/pojo.mustache @@ -232,6 +232,9 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{/vars}} {{>libraries/jersey2/additional_properties}} {{^supportJava6}} + /** + * Return true if this {{name}} object is equal to o. + */ @Override public boolean equals(java.lang.Object o) { {{#useReflectionEqualsHashCode}} From bb87de735ffe2716f7c5d0a1525248cedf838bab Mon Sep 17 00:00:00 2001 From: Ravisankar-Challa Date: Sun, 21 Jun 2020 21:02:44 +1000 Subject: [PATCH 265/370] [Java][Microprofile] JSON enum processing fix (#6700) * When withXml=false we shouldn't add the jaxb imports When users are just dealing with json and set withXml=false jaxb (Java Api XML binding) imports are not needed. * Updated the microprodile-rest-client samples * Removed cxf-rt-rs-extension-providers dependency * Fix processing of enum values * Remove unwanted changes * Remove spaces --- libraries/microprofile/enumClass.mustache | 12 ++++++------ libraries/microprofile/pojo.mustache | 6 ++++-- libraries/microprofile/pom.mustache | 2 -- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libraries/microprofile/enumClass.mustache b/libraries/microprofile/enumClass.mustache index 8fc406681de..ee3c5901fe4 100644 --- a/libraries/microprofile/enumClass.mustache +++ b/libraries/microprofile/enumClass.mustache @@ -3,17 +3,17 @@ @XmlEnum({{dataType}}.class) {{/withXml}} {{^withXml}} -@JsonbTypeSerializer({{datatypeWithEnum}}.Serializer.class) -@JsonbTypeDeserializer({{datatypeWithEnum}}.Deserializer.class) + @JsonbTypeSerializer({{datatypeWithEnum}}.Serializer.class) + @JsonbTypeDeserializer({{datatypeWithEnum}}.Deserializer.class) {{/withXml}} -public enum {{datatypeWithEnum}} { + public enum {{datatypeWithEnum}} { {{#allowableValues}} {{#withXml}} -{{#enumVars}}@XmlEnumValue({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) {{name}}({{dataType}}.valueOf({{{value}}})){{^-last}}, {{/-last}}{{#-last}};{{/-last}}{{/enumVars}} + {{#enumVars}}@XmlEnumValue({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) {{name}}({{dataType}}.valueOf({{{value}}})){{^-last}}, {{/-last}}{{#-last}};{{/-last}}{{/enumVars}} {{/withXml}} {{^withXml}} -{{#enumVars}}{{name}}({{dataType}}.valueOf({{{value}}})){{^-last}}, {{/-last}}{{#-last}};{{/-last}}{{/enumVars}} + {{#enumVars}}{{name}}({{dataType}}.valueOf({{{value}}})){{^-last}}, {{/-last}}{{#-last}};{{/-last}}{{/enumVars}} {{/withXml}} {{/allowableValues}} @@ -63,4 +63,4 @@ public enum {{datatypeWithEnum}} { } } {{/withXml}} -} + } diff --git a/libraries/microprofile/pojo.mustache b/libraries/microprofile/pojo.mustache index 0cde7940d3f..b69cf9dbfd6 100644 --- a/libraries/microprofile/pojo.mustache +++ b/libraries/microprofile/pojo.mustache @@ -75,12 +75,14 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}}{{#serializ {{#vendorExtensions.x-extra-annotation}} {{{vendorExtensions.x-extra-annotation}}} {{/vendorExtensions.x-extra-annotation}} -{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} {{#isEnum}}{{^isListContainer}}{{^isMapContainer}}public {{dataType}} {{getter}}() { +{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} {{#withXml}}{{#isEnum}}{{^isListContainer}}{{^isMapContainer}}public {{dataType}} {{getter}}() { if ({{name}} == null) { return null; } return {{name}}.value(); - }{{/isMapContainer}}{{/isListContainer}}{{/isEnum}}{{#isEnum}}{{#isListContainer}}public {{{datatypeWithEnum}}} {{getter}}() { + }{{/isMapContainer}}{{/isListContainer}}{{/isEnum}}{{/withXml}}{{^withXml}}{{#isEnum}}{{^isListContainer}}{{^isMapContainer}}public {{datatypeWithEnum}} {{getter}}() { + return {{name}}; + }{{/isMapContainer}}{{/isListContainer}}{{/isEnum}}{{/withXml}}{{#isEnum}}{{#isListContainer}}public {{{datatypeWithEnum}}} {{getter}}() { return {{name}}; }{{/isListContainer}}{{/isEnum}}{{#isEnum}}{{#isMapContainer}}public {{{datatypeWithEnum}}} {{getter}}() { return {{name}}; diff --git a/libraries/microprofile/pom.mustache b/libraries/microprofile/pom.mustache index ad160732687..f57a1f77234 100644 --- a/libraries/microprofile/pom.mustache +++ b/libraries/microprofile/pom.mustache @@ -88,7 +88,6 @@ 1.3.5 test - {{^disableMultipart}} org.apache.cxf @@ -96,7 +95,6 @@ 3.2.6 {{/disableMultipart}} - javax.json.bind javax.json.bind-api From f208a155758a226435452027374e95fefbce8094 Mon Sep 17 00:00:00 2001 From: bgong-mdsol Date: Mon, 22 Jun 2020 04:15:11 -0400 Subject: [PATCH 266/370] java-native added WithHttpInfo (#6704) remove /t --- libraries/native/ApiResponse.mustache | 58 +++++++ libraries/native/api.mustache | 216 ++++++++++++++++---------- libraries/native/api_doc.mustache | 133 +++++++++++++++- 3 files changed, 323 insertions(+), 84 deletions(-) create mode 100644 libraries/native/ApiResponse.mustache diff --git a/libraries/native/ApiResponse.mustache b/libraries/native/ApiResponse.mustache new file mode 100644 index 00000000000..1f3f3a31981 --- /dev/null +++ b/libraries/native/ApiResponse.mustache @@ -0,0 +1,58 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import java.util.List; +import java.util.Map; +{{#caseInsensitiveResponseHeaders}} +import java.util.Map.Entry; +import java.util.TreeMap; +{{/caseInsensitiveResponseHeaders}} + +/** + * API response returned by API call. + * + * @param The type of data that is deserialized from response body + */ +public class ApiResponse { + final private int statusCode; + final private Map> headers; + final private T data; + + /** + * @param statusCode The status code of HTTP response + * @param headers The headers of HTTP response + */ + public ApiResponse(int statusCode, Map> headers) { + this(statusCode, headers, null); + } + + /** + * @param statusCode The status code of HTTP response + * @param headers The headers of HTTP response + * @param data The object deserialized from response bod + */ + public ApiResponse(int statusCode, Map> headers, T data) { + this.statusCode = statusCode; + {{#caseInsensitiveResponseHeaders}} + Map> responseHeaders = new TreeMap>(String.CASE_INSENSITIVE_ORDER); + for(Entry> entry : headers.entrySet()){ + responseHeaders.put(entry.getKey().toLowerCase(), entry.getValue()); + } + {{/caseInsensitiveResponseHeaders}} + this.headers = {{#caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}; + this.data = data; + } + + public int getStatusCode() { + return statusCode; + } + + public Map> getHeaders() { + return headers; + } + + public T getData() { + return data; + } +} diff --git a/libraries/native/api.mustache b/libraries/native/api.mustache index 8bd7393ab59..1fca3864396 100644 --- a/libraries/native/api.mustache +++ b/libraries/native/api.mustache @@ -3,6 +3,9 @@ package {{package}}; import {{invokerPackage}}.ApiClient; import {{invokerPackage}}.ApiException; +{{^asyncNative}} +import {{invokerPackage}}.ApiResponse; +{{/asyncNative}} import {{invokerPackage}}.Pair; {{#imports}} @@ -27,8 +30,8 @@ import java.util.StringJoiner; import java.util.List; import java.util.Map; {{/fullJavaUtil}} - {{#asyncNative}} + import java.util.concurrent.CompletableFuture; {{/asyncNative}} @@ -77,12 +80,38 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}({{#hasParams}}API{{operationId}}Request {{operationId}}Request{{/hasParams}}) throws ApiException { + public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}(API{{operationId}}Request {{operationId}}Request) throws ApiException { {{#allParams}} {{{dataType}}} {{paramName}} = {{operationId}}Request.{{paramName}}(); {{/allParams}} {{#returnType}}return {{/returnType}}{{^returnType}}{{#asyncNative}}return {{/asyncNative}}{{/returnType}}{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); } + {{^asyncNative}} + + /** + * {{summary}} + * {{notes}} + * @param {{operationId}}Request {@link API{{operationId}}Request} + * @return ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo(API{{operationId}}Request {{operationId}}Request) throws ApiException { + {{#allParams}} + {{{dataType}}} {{paramName}} = {{operationId}}Request.{{paramName}}(); + {{/allParams}} + return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + } + {{/asyncNative}} {{/hasParams}} {{/vendorExtensions.x-group-parameters}} @@ -107,17 +136,103 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}} ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + {{^asyncNative}} + {{#returnType}}ApiResponse<{{{returnType}}}> localVarResponse = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{#returnType}} + return localVarResponse.getData(); + {{/returnType}} + {{/asyncNative}} + {{#asyncNative}} + try { + HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + return memberVarHttpClient.sendAsync( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofString()).thenComposeAsync(localVarResponse -> { + if (localVarResponse.statusCode()/ 100 != 2) { + return CompletableFuture.failedFuture(new ApiException(localVarResponse.statusCode(), + "{{operationId}} call received non-success response", + localVarResponse.headers(), + localVarResponse.body()) + ); + } else { + {{#returnType}} + try { + return CompletableFuture.completedFuture( + memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference<{{{returnType}}}>() {}) + ); + } catch (IOException e) { + return CompletableFuture.failedFuture(new ApiException(e)); + } + {{/returnType}} + {{^returnType}} + return CompletableFuture.completedFuture(null); + {{/returnType}} + } + }); + } + catch (ApiException e) { + return CompletableFuture.failedFuture(e); + } + {{/asyncNative}} + } + {{^asyncNative}} + + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}}{{/required}} + {{/allParams}} + * @return ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + try { + HttpResponse localVarResponse = memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + if (localVarResponse.statusCode()/ 100 != 2) { + throw new ApiException(localVarResponse.statusCode(), + "{{operationId}} call received non-success response", + localVarResponse.headers(), + localVarResponse.body() == null ? null : new String(localVarResponse.body().readAllBytes())); + } + return new ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + {{#returnType}}memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference<{{{returnType}}}>() {}){{/returnType}}{{^returnType}}null{{/returnType}} + ); + } catch (IOException e) { + throw new ApiException(e); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + } + {{/asyncNative}} + + private HttpRequest.Builder {{operationId}}RequestBuilder({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { {{#allParams}} {{#required}} // verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { - {{#asyncNative}} - return CompletableFuture.failedFuture(new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}")); - {{/asyncNative}} - {{^asyncNative}} - throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); - {{/asyncNative}} + throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); } {{/required}} {{/allParams}} @@ -161,87 +276,24 @@ public class {{classname}} { {{/bodyParam}} localVarRequestBuilder.header("Accept", "application/json"); - {{^asyncNative}} - try { - {{/asyncNative}} - {{#asyncNative}} - {{#bodyParam}} + {{#bodyParam}} try { - {{/bodyParam}} - {{/asyncNative}} - {{#bodyParam}} byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes({{paramName}}); localVarRequestBuilder.method("{{httpMethod}}", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody)); - {{/bodyParam}} - {{^bodyParam}} - localVarRequestBuilder.method("{{httpMethod}}", HttpRequest.BodyPublishers.noBody()); - {{/bodyParam}} - if (memberVarReadTimeout != null) { - localVarRequestBuilder.timeout(memberVarReadTimeout); - } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); - } - {{^asyncNative}} - HttpResponse localVarResponse = memberVarHttpClient.send( - localVarRequestBuilder.build(), - HttpResponse.BodyHandlers.ofInputStream()); - if (memberVarResponseInterceptor != null) { - memberVarResponseInterceptor.accept(localVarResponse); - } - if (localVarResponse.statusCode()/ 100 != 2) { - throw new ApiException(localVarResponse.statusCode(), - "{{operationId}} call received non-success response", - localVarResponse.headers(), - localVarResponse.body() == null ? null : new String(localVarResponse.body().readAllBytes())); - } - {{#returnType}} - return memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference<{{{returnType}}}>() {}); - {{/returnType}} - {{/asyncNative}} - {{#asyncNative}} - return memberVarHttpClient.sendAsync( - localVarRequestBuilder.build(), - HttpResponse.BodyHandlers.ofString()).thenComposeAsync(localVarResponse -> { - if (localVarResponse.statusCode()/ 100 != 2) { - return CompletableFuture.failedFuture(new ApiException(localVarResponse.statusCode(), - "{{operationId}} call received non-success response", - localVarResponse.headers(), - localVarResponse.body()) - ); - } else { - {{#returnType}} - try { - return CompletableFuture.completedFuture( - memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference<{{{returnType}}}>() {}) - ); - } catch (IOException e) { - return CompletableFuture.failedFuture(new ApiException(e)); - } - {{/returnType}}{{^returnType}} - return CompletableFuture.completedFuture(null); - {{/returnType}} - } - }); - {{/asyncNative}} - {{#asyncNative}} - {{#bodyParam}} } catch (IOException e) { - return CompletableFuture.failedFuture(new ApiException(e)); + throw new ApiException(e); } {{/bodyParam}} - {{/asyncNative}} - {{^asyncNative}} - } catch (IOException e) { - throw new ApiException(e); + {{^bodyParam}} + localVarRequestBuilder.method("{{httpMethod}}", HttpRequest.BodyPublishers.noBody()); + {{/bodyParam}} + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); } - {{/asyncNative}} - {{^asyncNative}} - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ApiException(e); + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); } - {{/asyncNative}} + return localVarRequestBuilder; } {{#vendorExtensions.x-group-parameters}} {{#hasParams}} diff --git a/libraries/native/api_doc.mustache b/libraries/native/api_doc.mustache index 5ece7d73aba..ff699f921e6 100644 --- a/libraries/native/api_doc.mustache +++ b/libraries/native/api_doc.mustache @@ -7,6 +7,9 @@ All URIs are relative to *{{basePath}}* Method | HTTP request | Description ------------- | ------------- | ------------- {{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{^asyncNative}} +[**{{operationId}}WithHttpInfo**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/asyncNative}} {{/operation}}{{/operations}} {{#operations}} @@ -70,10 +73,14 @@ public class Example { {{/allParams}} try { {{^vendorExtensions.x-group-parameters}} - {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} result = {{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture result = {{/asyncNative}}{{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}{{#hasParams}} + {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} result = {{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture result = {{/asyncNative}}{{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{/vendorExtensions.x-group-parameters}} + {{#vendorExtensions.x-group-parameters}} + {{#hasParams}} API{{operationId}}Request request = API{{operationId}}Request.newBuilder(){{#allParams}} .{{paramName}}({{paramName}}){{/allParams}} - .build();{{/hasParams}} + .build(); + {{/hasParams}} {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} result = {{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture result = {{/asyncNative}}{{/returnType}}apiInstance.{{operationId}}({{#hasParams}}request{{/hasParams}});{{/vendorExtensions.x-group-parameters}}{{#returnType}} System.out.println(result);{{/returnType}} } catch (ApiException e) { @@ -124,6 +131,128 @@ Name | Type | Description | Notes | **{{code}}** | {{message}} | {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}} | {{/responses}} {{/responses.0}} +{{^asyncNative}} + +## {{operationId}}WithHttpInfo + +{{^vendorExtensions.x-group-parameters}} +> ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}} {{operationId}}WithHttpInfo({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) +{{/vendorExtensions.x-group-parameters}} +{{#vendorExtensions.x-group-parameters}} +> ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}} {{operationId}}WithHttpInfo({{#hasParams}}{{operationId}}Request{{/hasParams}}) +{{/vendorExtensions.x-group-parameters}} + +{{summary}}{{#notes}} + +{{notes}}{{/notes}} + +### Example + +```java +// Import classes: +import {{{invokerPackage}}}.ApiClient; +import {{{invokerPackage}}}.ApiException; +import {{{invokerPackage}}}.ApiResponse; +import {{{invokerPackage}}}.Configuration;{{#hasAuthMethods}} +import {{{invokerPackage}}}.auth.*;{{/hasAuthMethods}} +import {{{invokerPackage}}}.models.*; +import {{{package}}}.{{{classname}}};{{#vendorExtensions.x-group-parameters}} +import {{{package}}}.{{{classname}}}.*;{{/vendorExtensions.x-group-parameters}} + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("{{{basePath}}}"); + {{#hasAuthMethods}} + {{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + // Configure HTTP basic authorization: {{{name}}} + HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setUsername("YOUR USERNAME"); + {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasicBasic}}{{#isBasicBearer}} + // Configure HTTP bearer authorization: {{{name}}} + HttpBearerAuth {{{name}}} = (HttpBearerAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setBearerToken("BEARER TOKEN");{{/isBasicBearer}}{{/isBasic}}{{#isApiKey}} + // Configure API key authorization: {{{name}}} + ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setApiKey("YOUR API KEY"); + // Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null) + //{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} + // Configure OAuth2 access token for authorization: {{{name}}} + OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}} + {{/authMethods}} + {{/hasAuthMethods}} + + {{{classname}}} apiInstance = new {{{classname}}}(defaultClient); + {{#allParams}} + {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} + {{/allParams}} + try { + {{^vendorExtensions.x-group-parameters}} + ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> response = apiInstance.{{{operationId}}}WithHttpInfo({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{/vendorExtensions.x-group-parameters}} + {{#vendorExtensions.x-group-parameters}} + {{#hasParams}} + API{{operationId}}Request request = API{{operationId}}Request.newBuilder(){{#allParams}} + .{{paramName}}({{paramName}}){{/allParams}} + .build(); + {{/hasParams}} + ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> response = apiInstance.{{{operationId}}}WithHttpInfo({{#hasParams}}request{{/hasParams}}); + {{/vendorExtensions.x-group-parameters}} + System.out.println("Status code: " + response.getStatusCode()); + System.out.println("Response headers: " + response.getHeaders().toString()); + {{#returnType}} + System.out.println("Response body: " + response.getData().toString()); + {{/returnType}} + } catch (ApiException e) { + System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } +} +``` + +### Parameters + +{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{^vendorExtensions.x-group-parameters}}{{#allParams}}{{#-last}} +Name | Type | Description | Notes +------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} +{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{^isContainer}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} +{{/allParams}} +{{/vendorExtensions.x-group-parameters}} +{{#vendorExtensions.x-group-parameters}} +{{#hasParams}} +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------| +| {{operationId}}Request | [**API{{operationId}}Request**]({{classname}}.md#API{{operationId}}Request)|-|-|{{/hasParams}} +{{/vendorExtensions.x-group-parameters}} + +### Return type + +{{#returnType}}ApiResponse<{{#returnTypeIsPrimitive}}**{{returnType}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{returnType}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}>{{/returnType}} +{{^returnType}}ApiResponse{{/returnType}} + +### Authorization + +{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{name}}](../README.md#{{name}}){{^-last}}, {{/-last}}{{/authMethods}} + +### HTTP request headers + +- **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} +- **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} + +{{#responses.0}} +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +{{#responses}} +| **{{code}}** | {{message}} | {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}} | +{{/responses}} +{{/responses.0}} +{{/asyncNative}} {{#vendorExtensions.x-group-parameters}}{{#hasParams}} From 387cfa80b6d44fdceddcef2e729b561a3fdcb706 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Tue, 23 Jun 2020 21:58:16 +0800 Subject: [PATCH 267/370] [Java][jersey2] fix oneOf, anyOf documentation (#6695) * fix oneOf doc in Java jersey2 * fix sample code * add new files * minor tweat to the doc --- libraries/jersey2/model_anyof_doc.mustache | 38 ++++++++++++++++++++++ libraries/jersey2/model_doc.mustache | 19 +++++++++++ libraries/jersey2/model_oneof_doc.mustache | 38 ++++++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100644 libraries/jersey2/model_anyof_doc.mustache create mode 100644 libraries/jersey2/model_doc.mustache create mode 100644 libraries/jersey2/model_oneof_doc.mustache diff --git a/libraries/jersey2/model_anyof_doc.mustache b/libraries/jersey2/model_anyof_doc.mustache new file mode 100644 index 00000000000..e360aa56e6c --- /dev/null +++ b/libraries/jersey2/model_anyof_doc.mustache @@ -0,0 +1,38 @@ +# {{classname}} + +{{#description}} +{{&description}} + +{{/description}} +## anyOf schemas +{{#anyOf}} +* [{{{.}}}]({{{.}}}.md) +{{/anyOf}} + +{{#isNullable}} +NOTE: this class is nullable. + +{{/isNullable}} +## Example +```java +// Import classes: +import {{{package}}}.{{{classname}}}; +{{#anyOf}} +import {{{package}}}.{{{.}}}; +{{/anyOf}} + +public class Example { + public static void main(String[] args) { + {{classname}} example{{classname}} = new {{classname}}(); + {{#anyOf}} + + // create a new {{{.}}} + {{{.}}} example{{{.}}} = new {{{.}}}(); + // set {{{classname}}} to {{{.}}} + example{{classname}}.setActualInstance(example{{{.}}}); + // to get back the {{{.}}} set earlier + {{{.}}} test{{{.}}} = ({{{.}}}) example{{classname}}.getActualInstance(); + {{/anyOf}} + } +} +``` diff --git a/libraries/jersey2/model_doc.mustache b/libraries/jersey2/model_doc.mustache new file mode 100644 index 00000000000..be1aedcf2f3 --- /dev/null +++ b/libraries/jersey2/model_doc.mustache @@ -0,0 +1,19 @@ +{{#models}}{{#model}} + +{{#isEnum}} +{{>enum_outer_doc}} +{{/isEnum}} +{{^isEnum}} +{{^oneOf.isEmpty}} +{{>model_oneof_doc}} +{{/oneOf.isEmpty}} +{{^anyOf.isEmpty}} +{{>model_anyof_doc}} +{{/anyOf.isEmpty}} +{{^anyOf}} +{{^oneOf}} +{{>pojo_doc}} +{{/oneOf}} +{{/anyOf}} +{{/isEnum}} +{{/model}}{{/models}} diff --git a/libraries/jersey2/model_oneof_doc.mustache b/libraries/jersey2/model_oneof_doc.mustache new file mode 100644 index 00000000000..5fff76c9efa --- /dev/null +++ b/libraries/jersey2/model_oneof_doc.mustache @@ -0,0 +1,38 @@ +# {{classname}} + +{{#description}} +{{&description}} + +{{/description}} +## oneOf schemas +{{#oneOf}} +* [{{{.}}}]({{{.}}}.md) +{{/oneOf}} + +{{#isNullable}} +NOTE: this class is nullable. + +{{/isNullable}} +## Example +```java +// Import classes: +import {{{package}}}.{{{classname}}}; +{{#oneOf}} +import {{{package}}}.{{{.}}}; +{{/oneOf}} + +public class Example { + public static void main(String[] args) { + {{classname}} example{{classname}} = new {{classname}}(); + {{#oneOf}} + + // create a new {{{.}}} + {{{.}}} example{{{.}}} = new {{{.}}}(); + // set {{{classname}}} to {{{.}}} + example{{classname}}.setActualInstance(example{{{.}}}); + // to get back the {{{.}}} set earlier + {{{.}}} test{{{.}}} = ({{{.}}}) example{{classname}}.getActualInstance(); + {{/oneOf}} + } +} +``` From 9e164cc2e70bff666432253b0d66d5264acfaff8 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 26 Jun 2020 16:25:55 +0800 Subject: [PATCH 268/370] [Java][jersey2] Add debugging to OAuth (#6757) * add debugging to oauth * use fine instead --- libraries/jersey2/ApiClient.mustache | 2 +- libraries/jersey2/auth/OAuth.mustache | 286 +++++++++++++------------- 2 files changed, 149 insertions(+), 139 deletions(-) diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index d0773177c76..a14b0c16f77 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -461,7 +461,7 @@ public class ApiClient { public ApiClient setOauthCredentials(String clientId, String clientSecret) { for (Authentication auth : authentications.values()) { if (auth instanceof OAuth) { - ((OAuth) auth).setCredentials(clientId, clientSecret); + ((OAuth) auth).setCredentials(clientId, clientSecret, isDebugging()); return this; } } diff --git a/libraries/jersey2/auth/OAuth.mustache b/libraries/jersey2/auth/OAuth.mustache index d18b41b0e4c..62b573a66c0 100644 --- a/libraries/jersey2/auth/OAuth.mustache +++ b/libraries/jersey2/auth/OAuth.mustache @@ -22,151 +22,161 @@ import java.util.logging.Logger; {{>generatedAnnotation}} public class OAuth implements Authentication { - private static final Logger log = Logger.getLogger(OAuth.class.getName()); - - private String tokenUrl; - private String absoluteTokenUrl; - private OAuthFlow flow = OAuthFlow.application; - private OAuth20Service service; - private DefaultApi20 authApi; - private String scope; - private String username; - private String password; - private String code; - private volatile OAuth2AccessToken accessToken; - - public OAuth(String basePath, String tokenUrl) { - this.tokenUrl = tokenUrl; - this.absoluteTokenUrl = createAbsoluteTokenUrl(basePath, tokenUrl); - authApi = new DefaultApi20() { - @Override - public String getAccessTokenEndpoint() { - return absoluteTokenUrl; - } - - @Override - protected String getAuthorizationBaseUrl() { - throw new UnsupportedOperationException("Shouldn't get there !"); - } - }; - } - - private static String createAbsoluteTokenUrl(String basePath, String tokenUrl) { - if (!URI.create(tokenUrl).isAbsolute()) { - try { - return UriBuilder.fromPath(basePath).path(tokenUrl).build().toURL().toString(); - } catch (MalformedURLException e) { - log.log(Level.SEVERE, "Couldn't create absolute token URL", e); - } + private static final Logger log = Logger.getLogger(OAuth.class.getName()); + + private String tokenUrl; + private String absoluteTokenUrl; + private OAuthFlow flow = OAuthFlow.application; + private OAuth20Service service; + private DefaultApi20 authApi; + private String scope; + private String username; + private String password; + private String code; + private volatile OAuth2AccessToken accessToken; + + public OAuth(String basePath, String tokenUrl) { + this.tokenUrl = tokenUrl; + this.absoluteTokenUrl = createAbsoluteTokenUrl(basePath, tokenUrl); + authApi = new DefaultApi20() { + @Override + public String getAccessTokenEndpoint() { + return absoluteTokenUrl; + } + + @Override + protected String getAuthorizationBaseUrl() { + throw new UnsupportedOperationException("Shouldn't get there !"); + } + }; } - return tokenUrl; - } - - @Override - public void applyToParams( - List queryParams, - Map headerParams, - Map cookieParams, - String payload, - String method, - URI uri) - throws ApiException { - - if (accessToken == null) { - obtainAccessToken(null); + + private static String createAbsoluteTokenUrl(String basePath, String tokenUrl) { + if (!URI.create(tokenUrl).isAbsolute()) { + try { + return UriBuilder.fromPath(basePath).path(tokenUrl).build().toURL().toString(); + } catch (MalformedURLException e) { + log.log(Level.SEVERE, "Couldn't create absolute token URL", e); + } + } + return tokenUrl; + } + + @Override + public void applyToParams( + List queryParams, + Map headerParams, + Map cookieParams, + String payload, + String method, + URI uri) + throws ApiException { + + if (accessToken == null) { + obtainAccessToken(null); + } + if (accessToken != null) { + headerParams.put("Authorization", "Bearer " + accessToken.getAccessToken()); + } + } + + public OAuth2AccessToken renewAccessToken() throws ApiException { + String refreshToken = null; + if (accessToken != null) { + refreshToken = accessToken.getRefreshToken(); + accessToken = null; + } + return obtainAccessToken(refreshToken); + } + + public synchronized OAuth2AccessToken obtainAccessToken(String refreshToken) throws ApiException { + if (service == null) { + log.log(Level.FINE, "service is null in obtainAccessToken."); + return null; + } + try { + if (refreshToken != null) { + return service.refreshAccessToken(refreshToken); + } + } catch (OAuthException | InterruptedException | ExecutionException | IOException e) { + log.log(Level.FINE, "Refreshing the access token using the refresh token failed", e); + } + try { + switch (flow) { + case password: + if (username != null && password != null) { + accessToken = service.getAccessTokenPasswordGrant(username, password, scope); + } + break; + case accessCode: + if (code != null) { + accessToken = service.getAccessToken(code); + code = null; + } + break; + case application: + accessToken = service.getAccessTokenClientCredentialsGrant(scope); + break; + default: + log.log(Level.SEVERE, "Invalid flow in obtainAccessToken: " + flow); + } + } catch (OAuthException | InterruptedException | ExecutionException | IOException e) { + throw new ApiException(e); + } + return accessToken; + } + + public OAuth2AccessToken getAccessToken() { + return accessToken; } - if (accessToken != null) { - headerParams.put("Authorization", "Bearer " + accessToken.getAccessToken()); + + public OAuth setAccessToken(OAuth2AccessToken accessToken) { + this.accessToken = accessToken; + return this; } - } - public OAuth2AccessToken renewAccessToken() throws ApiException { - String refreshToken = null; - if (accessToken != null) { - refreshToken = accessToken.getRefreshToken(); - accessToken = null; + public OAuth setAccessToken(String accessToken) { + this.accessToken = new OAuth2AccessToken(accessToken); + return this; } - return obtainAccessToken(refreshToken); - } - public synchronized OAuth2AccessToken obtainAccessToken(String refreshToken) throws ApiException { - if (service == null) { - return null; + public OAuth setScope(String scope) { + this.scope = scope; + return this; } - try { - if (refreshToken != null) { - return service.refreshAccessToken(refreshToken); - } - } catch (OAuthException | InterruptedException | ExecutionException | IOException e) { - log.log(Level.FINE, "Refreshing the access token using the refresh token failed", e); + + public OAuth setCredentials(String clientId, String clientSecret, Boolean debug) { + if (Boolean.TRUE.equals(debug)) { + service = new ServiceBuilder(clientId) + .apiSecret(clientSecret).debug() + .build(authApi); + } else { + service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .build(authApi); + } + return this; } - try { - switch (flow) { - case password: - if (username != null && password != null) { - accessToken = service.getAccessTokenPasswordGrant(username, password, scope); - } - break; - case accessCode: - if (code != null) { - accessToken = service.getAccessToken(code); - code = null; - } - break; - case application: - accessToken = service.getAccessTokenClientCredentialsGrant(scope); - } - } catch (OAuthException | InterruptedException | ExecutionException | IOException e) { - throw new ApiException(e); + + public OAuth usePasswordFlow(String username, String password) { + this.flow = OAuthFlow.password; + this.username = username; + this.password = password; + return this; + } + + public OAuth useAuthorizationCodeFlow(String code) { + this.flow = OAuthFlow.accessCode; + this.code = code; + return this; + } + + public OAuth setFlow(OAuthFlow flow) { + this.flow = flow; + return this; + } + + public void setBasePath(String basePath) { + this.absoluteTokenUrl = createAbsoluteTokenUrl(basePath, tokenUrl); } - return accessToken; - } - - public OAuth2AccessToken getAccessToken() { - return accessToken; - } - - public OAuth setAccessToken(OAuth2AccessToken accessToken) { - this.accessToken = accessToken; - return this; - } - - public OAuth setAccessToken(String accessToken) { - this.accessToken = new OAuth2AccessToken(accessToken); - return this; - } - - public OAuth setScope(String scope) { - this.scope = scope; - return this; - } - - public OAuth setCredentials(String clientId, String clientSecret) { - service = new ServiceBuilder(clientId) - .apiSecret(clientSecret) - .build(authApi); - return this; - } - - public OAuth usePasswordFlow(String username, String password) { - this.flow = OAuthFlow.password; - this.username = username; - this.password = password; - return this; - } - - public OAuth useAuthorizationCodeFlow(String code) { - this.flow = OAuthFlow.accessCode; - this.code = code; - return this; - } - - public OAuth setFlow(OAuthFlow flow) { - this.flow = flow; - return this; - } - - public void setBasePath(String basePath) { - this.absoluteTokenUrl = createAbsoluteTokenUrl(basePath, tokenUrl); - } } From bbed81824877249f3066198b23f4e9ecb200074f Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Sun, 28 Jun 2020 08:14:22 -0700 Subject: [PATCH 269/370] [java][jersey2] Add support for (expires) and (created) fields in HTTP signature (#6632) * Add support for (expires) and (created) fields in HTTP signature * Add support for (expires) and (created) fields in HTTP signature --- .../jersey2/auth/HttpSignatureAuth.mustache | 19 +++++++++++++++++-- libraries/jersey2/pom.mustache | 2 +- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/libraries/jersey2/auth/HttpSignatureAuth.mustache b/libraries/jersey2/auth/HttpSignatureAuth.mustache index 744f9f6bd4b..787bef3db0c 100644 --- a/libraries/jersey2/auth/HttpSignatureAuth.mustache +++ b/libraries/jersey2/auth/HttpSignatureAuth.mustache @@ -49,6 +49,9 @@ public class HttpSignatureAuth implements Authentication { // The digest algorithm which is used to calculate a cryptographic digest of the HTTP request body. private String digestAlgorithm; + // The maximum validity duration of the HTTP signature. + private Long maxSignatureValidity; + /** * Construct a new HTTP signature auth configuration object. * @@ -57,19 +60,23 @@ public class HttpSignatureAuth implements Authentication { * @param algorithm The cryptographic algorithm. * @param digestAlgorithm The digest algorithm. * @param headers The list of HTTP headers that should be included in the HTTP signature. + * @param maxSignatureValidity The maximum validity duration of the HTTP signature. + * Used to set the '(expires)' field in the HTTP signature. */ public HttpSignatureAuth(String keyId, SigningAlgorithm signingAlgorithm, Algorithm algorithm, String digestAlgorithm, AlgorithmParameterSpec parameterSpec, - List headers) { + List headers, + Long maxSignatureValidity) { this.keyId = keyId; this.signingAlgorithm = signingAlgorithm; this.algorithm = algorithm; this.parameterSpec = parameterSpec; this.digestAlgorithm = digestAlgorithm; this.headers = headers; + this.maxSignatureValidity = maxSignatureValidity; } /** @@ -179,6 +186,14 @@ public class HttpSignatureAuth implements Authentication { this.headers = headers; } + /** + * Returns the maximum validity duration of the HTTP signature. + * @return The maximum validity duration of the HTTP signature. + */ + public Long getMaxSignatureValidity() { + return maxSignatureValidity; + } + /** * Returns the signer instance used to sign HTTP messages. * @@ -209,7 +224,7 @@ public class HttpSignatureAuth implements Authentication { if (key == null) { throw new ApiException("Private key (java.security.Key) cannot be null"); } - signer = new Signer(key, new Signature(keyId, signingAlgorithm, algorithm, parameterSpec, null, headers)); + signer = new Signer(key, new Signature(keyId, signingAlgorithm, algorithm, parameterSpec, null, headers, maxSignatureValidity)); } @Override diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 155f306546c..4b6850ff230 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -407,7 +407,7 @@ 1.3.2 4.13 {{#hasHttpSignatureMethods}} - 1.4 + 1.5 {{/hasHttpSignatureMethods}} {{#hasOAuthMethods}} 6.9.0 From 5c1a32ccdfe616d111f4f406abce3893eab870ee Mon Sep 17 00:00:00 2001 From: William Cheng Date: Mon, 29 Jun 2020 16:08:42 +0800 Subject: [PATCH 270/370] [Java][jersey2] Add nullable body support (#6784) * add nullable body support * update serializeToString with nullable body * add nullable support to body parameter * minor code format change * Revert "minor code format change" This reverts commit 3af1838a9bf421e633165dbd8e62bb7740b539ef. * code format fix --- libraries/jersey2/ApiClient.mustache | 29 +++++++++++++++++++--------- libraries/jersey2/api.mustache | 2 +- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index a14b0c16f77..9d726cc93dc 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -839,7 +839,7 @@ public class ApiClient { * @return Entity * @throws ApiException API exception */ - public Entity serialize(Object obj, Map formParams, String contentType) throws ApiException { + public Entity serialize(Object obj, Map formParams, String contentType, boolean isBodyNullable) throws ApiException { Entity entity; if (contentType.startsWith("multipart/form-data")) { MultiPart multiPart = new MultiPart(); @@ -863,7 +863,11 @@ public class ApiClient { entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE); } else { // We let jersey handle the serialization - entity = Entity.entity(obj == null ? Entity.text("") : obj, contentType); + if (isBodyNullable) { // payload is nullable + entity = Entity.entity(obj == null ? Entity.text("null") : obj, contentType); + } else { + entity = Entity.entity(obj == null ? Entity.text("") : obj, contentType); + } } return entity; } @@ -874,10 +878,11 @@ public class ApiClient { * @param obj Object * @param formParams Form parameters * @param contentType Context type + * @param isBodyNulalble True if the body is nullable * @return String * @throws ApiException API exception */ - public String serializeToString(Object obj, Map formParams, String contentType) throws ApiException { + public String serializeToString(Object obj, Map formParams, String contentType, boolean isBodyNullable) throws ApiException { try { if (contentType.startsWith("multipart/form-data")) { throw new ApiException("multipart/form-data not yet supported for serializeToString (http signature authentication)"); @@ -893,7 +898,11 @@ public class ApiClient { return formString.substring(0, formString.length() - 1); } } else { - return json.getMapper().writeValueAsString(obj); + if (isBodyNullable) { + return obj == null ? "null" : json.getMapper().writeValueAsString(obj); + } else { + return json.getMapper().writeValueAsString(obj); + } } } catch (Exception ex) { throw new ApiException("Failed to perform serializeToString: " + ex.toString()); @@ -1007,6 +1016,7 @@ public class ApiClient { * @param contentType The request's Content-Type header * @param authNames The authentications to apply * @param returnType The return type into which to deserialize the response + * @param isBodyNullable True if the body is nullable * @return The response body in type of string * @throws ApiException API exception */ @@ -1022,7 +1032,8 @@ public class ApiClient { String accept, String contentType, String[] authNames, - GenericType returnType) + GenericType returnType, + boolean isBodyNullable) throws ApiException { // Not using `.target(targetURL).path(path)` below, @@ -1069,7 +1080,7 @@ public class ApiClient { } } - Entity entity = serialize(body, formParams, contentType); + Entity entity = serialize(body, formParams, contentType, isBodyNullable); // put all headers in one place Map allHeaderParams = new HashMap<>(defaultHeaderMap); @@ -1081,7 +1092,7 @@ public class ApiClient { queryParams, allHeaderParams, cookieParams, - serializeToString(body, formParams, contentType), + serializeToString(body, formParams, contentType, isBodyNullable), method, target.getUri()); @@ -1170,8 +1181,8 @@ public class ApiClient { * @deprecated Add qualified name of the operation as a first parameter. */ @Deprecated - public ApiResponse invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { - return invokeAPI(null, path, method, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType); + public ApiResponse invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType, boolean isBodyNullable) throws ApiException { + return invokeAPI(null, path, method, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType, isBodyNullable); } /** diff --git a/libraries/jersey2/api.mustache b/libraries/jersey2/api.mustache index 16f7ef45b8c..5fcfb9b19bb 100644 --- a/libraries/jersey2/api.mustache +++ b/libraries/jersey2/api.mustache @@ -167,7 +167,7 @@ public class {{classname}} { {{/returnType}} return apiClient.invokeAPI("{{classname}}.{{operationId}}", localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, - localVarAuthNames, {{#returnType}}localVarReturnType{{/returnType}}{{^returnType}}null{{/returnType}}); + localVarAuthNames, {{#returnType}}localVarReturnType{{/returnType}}{{^returnType}}null{{/returnType}}, {{#bodyParam}}{{#isNullable}}true{{/isNullable}}{{^isNullable}}false{{/isNullable}}{{/bodyParam}}{{^bodyParam}}false{{/bodyParam}}); } {{#vendorExtensions.x-group-parameters}} From 3625fa1fd195c9081a8657df2594ee86b6fb75e9 Mon Sep 17 00:00:00 2001 From: Jochen Schalanda Date: Wed, 1 Jul 2020 09:08:28 +0200 Subject: [PATCH 271/370] [Java][client][native][Gradle] Add missing jackson-databind-nullable (#6802) * Add missing jackson-databind-nullable to java-native Gradle build Closes #6801 * Regenerate java-native samples * update samples Co-authored-by: William Cheng --- libraries/native/build.gradle.mustache | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/native/build.gradle.mustache b/libraries/native/build.gradle.mustache index c68123d6df1..f3d5335ad5f 100644 --- a/libraries/native/build.gradle.mustache +++ b/libraries/native/build.gradle.mustache @@ -62,6 +62,7 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + compile "org.openapitools:jackson-databind-nullable:0.2.1" compile 'javax.annotation:javax.annotation-api:1.3.2' testCompile "junit:junit:$junit_version" } From c247c1dffd6ec4703e737ad2d45f8c165e9b6ffd Mon Sep 17 00:00:00 2001 From: William Cheng Date: Thu, 2 Jul 2020 00:12:32 +0800 Subject: [PATCH 272/370] [Java] Deprecate feignVersion option (#6824) * deprecate feign option * update doc * udpate samples --- libraries/feign/auth/OAuth.mustache | 7 ------- libraries/feign/build.gradle.mustache | 4 ++-- libraries/feign/build.sbt.mustache | 8 ++++---- libraries/feign/pom.mustache | 4 ++-- 4 files changed, 8 insertions(+), 15 deletions(-) diff --git a/libraries/feign/auth/OAuth.mustache b/libraries/feign/auth/OAuth.mustache index feefdb93981..b451e97ae6e 100644 --- a/libraries/feign/auth/OAuth.mustache +++ b/libraries/feign/auth/OAuth.mustache @@ -19,9 +19,7 @@ import org.apache.oltu.oauth2.common.message.types.GrantType; import org.apache.oltu.oauth2.common.token.BasicOAuthToken; import feign.Client; -{{#useFeign10}} import feign.Request.HttpMethod; -{{/useFeign10}} import feign.Request.Options; import feign.RequestInterceptor; import feign.RequestTemplate; @@ -95,12 +93,7 @@ public class OAuth implements RequestInterceptor { try { accessTokenResponse = oauthClient.accessToken(tokenRequestBuilder.buildBodyMessage()); } catch (Exception e) { - {{#useFeign10}} throw new RetryableException(0, e.getMessage(), HttpMethod.POST, e, null, template.request()); - {{/useFeign10}} - {{^useFeign10}} - throw new RetryableException(e.getMessage(), e,null); - {{/useFeign10}} } if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { setAccessToken(accessTokenResponse.getAccessToken(), accessTokenResponse.getExpiresIn()); diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index 8302b841064..075db4f0cdb 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -126,8 +126,8 @@ ext { {{#threetenbp}} jackson_threetenbp_version = "2.9.10" {{/threetenbp}} - feign_version = "{{#useFeign10}}11.0{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" - feign_form_version = "{{#useFeign10}}3.8.0{{/useFeign10}}{{^useFeign10}}2.1.0{{/useFeign10}}" + feign_version = "11.0" + feign_form_version = "3.8.0" junit_version = "4.13" oltu_version = "1.0.1" } diff --git a/libraries/feign/build.sbt.mustache b/libraries/feign/build.sbt.mustache index e5caa1b2000..664cc67edfc 100644 --- a/libraries/feign/build.sbt.mustache +++ b/libraries/feign/build.sbt.mustache @@ -10,10 +10,10 @@ lazy val root = (project in file(".")). resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( "io.swagger" % "swagger-annotations" % "1.5.24" % "compile", - "io.github.openfeign" % "feign-core" % "{{#useFeign10}}11.0{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", - "io.github.openfeign" % "feign-jackson" % "{{#useFeign10}}11.0{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", - "io.github.openfeign" % "feign-slf4j" % "{{#useFeign10}}11.0{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", - "io.github.openfeign.form" % "feign-form" % "{{#useFeign10}}3.8.0{{/useFeign10}}{{^useFeign10}}2.1.0{{/useFeign10}}" % "compile", + "io.github.openfeign" % "feign-core" % "11.0" % "compile", + "io.github.openfeign" % "feign-jackson" % "11.0" % "compile", + "io.github.openfeign" % "feign-slf4j" % "11.0" % "compile", + "io.github.openfeign.form" % "feign-form" % "3.8.0" % "compile", "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index b76784db04a..60581b5336f 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -348,8 +348,8 @@ ${java.version} ${java.version} 1.5.24 - {{#useFeign10}}11.0{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}} - {{#useFeign10}}3.8.0{{/useFeign10}}{{^useFeign10}}2.1.0{{/useFeign10}} + 11.0 + 3.8.0 2.10.3 0.2.1 2.10.3 From 0f178a282b5b6c646f48e5d1949fe4128b1ff7b3 Mon Sep 17 00:00:00 2001 From: Hippolyte HENRY Date: Thu, 2 Jul 2020 05:45:30 +0200 Subject: [PATCH 273/370] [Java][jersey2] Add a getter for the User-Agent header value (#6831) * [Java][jersey2] Add a getter for the User-Agent header value * generate samples --- libraries/jersey2/ApiClient.mustache | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 9d726cc93dc..dc15ec47491 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -81,6 +81,7 @@ public class ApiClient { protected Map defaultHeaderMap = new HashMap(); protected Map defaultCookieMap = new HashMap(); protected String basePath = "{{{basePath}}}"; + protected String userAgent; private static final Logger log = Logger.getLogger(ApiClient.class.getName()); protected List servers = new ArrayList({{#servers}}{{#-first}}Arrays.asList( @@ -521,10 +522,19 @@ public class ApiClient { * @return API client */ public ApiClient setUserAgent(String userAgent) { + userAgent = userAgent; addDefaultHeader("User-Agent", userAgent); return this; } + /** + * Get the User-Agent header's value. + * @return User-Agent string + */ + public String getUserAgent(){ + return userAgent; + } + /** * Add a default header. * From f22500fbc7d5c777094dc2d78629a2dd65a5b989 Mon Sep 17 00:00:00 2001 From: tgerth <39165556+tgerth@users.noreply.github.com> Date: Thu, 2 Jul 2020 09:37:57 +0200 Subject: [PATCH 274/370] Make ApiClient in retrofit2 be able to use own OkHttpClient (#6699) * set adapterBuilder.client() only if okBuilder was used in retrofit2 * updated the samples * added field okHttpClient and updated samples * bug fixed, added exception if okBuilder is null * added semicolon * added space, changed Exception to RuntimeException and changed its message * updated the samples --- libraries/retrofit2/ApiClient.mustache | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/libraries/retrofit2/ApiClient.mustache b/libraries/retrofit2/ApiClient.mustache index 42aa2dd351e..6c16a948610 100644 --- a/libraries/retrofit2/ApiClient.mustache +++ b/libraries/retrofit2/ApiClient.mustache @@ -56,10 +56,18 @@ public class ApiClient { private OkHttpClient.Builder okBuilder; private Retrofit.Builder adapterBuilder; private JSON json; + private OkHttpClient okHttpClient; public ApiClient() { apiAuthorizations = new LinkedHashMap(); createDefaultAdapter(); + okBuilder = new OkHttpClient.Builder(); + } + + public ApiClient(OkHttpClient client){ + apiAuthorizations = new LinkedHashMap(); + createDefaultAdapter(); + okHttpClient = client; } public ApiClient(String[] authNames) { @@ -141,7 +149,6 @@ public class ApiClient { {{/hasOAuthMethods}} public void createDefaultAdapter() { json = new JSON(); - okBuilder = new OkHttpClient.Builder(); String baseUrl = "{{{basePath}}}"; if (!baseUrl.endsWith("/")) @@ -164,10 +171,11 @@ public class ApiClient { } public S createService(Class serviceClass) { - return adapterBuilder - .client(okBuilder.build()) - .build() - .create(serviceClass); + if (okHttpClient != null) { + return adapterBuilder.client(okHttpClient).build().create(serviceClass); + } else { + return adapterBuilder.client(okBuilder.build()).build().create(serviceClass); + } } public ApiClient setDateFormat(DateFormat dateFormat) { @@ -357,7 +365,11 @@ public class ApiClient { throw new RuntimeException("auth name \"" + authName + "\" already in api authorizations"); } apiAuthorizations.put(authName, authorization); + if(okBuilder == null){ + throw new RuntimeException("The ApiClient was created with a built OkHttpClient so it's not possible to add an authorization interceptor to it"); + } okBuilder.addInterceptor(authorization); + return this; } From 773c8bb980a30e91bf96f82cecfbf39b96232f7f Mon Sep 17 00:00:00 2001 From: grzegorz-moto <60603738+grzegorz-moto@users.noreply.github.com> Date: Thu, 2 Jul 2020 12:34:28 +0200 Subject: [PATCH 275/370] [Java][WebClient]remove the dead code from java ApiClient.mustache (#6556) * remove the dead code Remove the dead code from ApiClient The code is not used and it contains vulnerability of Log Forgery when it writes unvalidated http header to the log. An attacker could take advantage of this behaviour to forge log entries or inject malicious content into the log. * update Petstore samples * whitespace --- libraries/webclient/ApiClient.mustache | 52 -------------------------- 1 file changed, 52 deletions(-) diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index 72b80bac81a..f38a9b8c450 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -647,56 +647,4 @@ public class ApiClient { return collectionFormat.collectionToString(values); } - - private class ApiClientHttpRequestInterceptor implements ClientHttpRequestInterceptor { - private final Log log = LogFactory.getLog(ApiClientHttpRequestInterceptor.class); - - @Override - public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { - logRequest(request, body); - ClientHttpResponse response = execution.execute(request, body); - logResponse(response); - return response; - } - - private void logRequest(HttpRequest request, byte[] body) throws UnsupportedEncodingException { - log.info("URI: " + request.getURI()); - log.info("HTTP Method: " + request.getMethod()); - log.info("HTTP Headers: " + headersToString(request.getHeaders())); - log.info("Request Body: " + new String(body, StandardCharsets.UTF_8)); - } - - private void logResponse(ClientHttpResponse response) throws IOException { - log.info("HTTP Status Code: " + response.getRawStatusCode()); - log.info("Status Text: " + response.getStatusText()); - log.info("HTTP Headers: " + headersToString(response.getHeaders())); - log.info("Response Body: " + bodyToString(response.getBody())); - } - - private String headersToString(HttpHeaders headers) { - StringBuilder builder = new StringBuilder(); - for(Entry> entry : headers.entrySet()) { - builder.append(entry.getKey()).append("=["); - for(String value : entry.getValue()) { - builder.append(value).append(","); - } - builder.setLength(builder.length() - 1); // Get rid of trailing comma - builder.append("],"); - } - builder.setLength(builder.length() - 1); // Get rid of trailing comma - return builder.toString(); - } - - private String bodyToString(InputStream body) throws IOException { - StringBuilder builder = new StringBuilder(); - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(body, StandardCharsets.UTF_8)); - String line = bufferedReader.readLine(); - while (line != null) { - builder.append(line).append(System.lineSeparator()); - line = bufferedReader.readLine(); - } - bufferedReader.close(); - return builder.toString(); - } - } } From 02917851dbbaf03116f69aa3f66c16db11a43ded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Rodr=C3=ADguez=20Mart=C3=ADn?= Date: Thu, 2 Jul 2020 18:23:17 +0200 Subject: [PATCH 276/370] [BUG] [JAVA] Fix multiple files upload (#4803) (#6808) * gh-4803: Fix bug java client multiple files upload * gh-4803: Fix bug java client multiple files upload * gh-4803: Fix bug java client multiple files upload * gh-4803: Fix bug java client multiple files upload * gh-4803: Fix bug java client multiple files upload --- libraries/resttemplate/api.mustache | 5 +++-- libraries/webclient/api.mustache | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libraries/resttemplate/api.mustache b/libraries/resttemplate/api.mustache index dc6d434c3e4..2f1ed68e996 100644 --- a/libraries/resttemplate/api.mustache +++ b/libraries/resttemplate/api.mustache @@ -10,7 +10,8 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Locale; -import java.util.Map;{{/fullJavaUtil}} +import java.util.Map; +import java.util.stream.Collectors;{{/fullJavaUtil}} import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -130,7 +131,7 @@ public class {{classname}} { {{/hasMore}}{{/cookieParams}}{{/hasCookieParams}}{{#hasFormParams}} {{#formParams}}if ({{paramName}} != null) - formParams.{{^collectionFormat}}add{{/collectionFormat}}{{#collectionFormat}}put{{/collectionFormat}}("{{baseName}}", {{#isFile}}new FileSystemResource({{paramName}}){{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} + formParams.{{^collectionFormat}}add{{/collectionFormat}}{{#collectionFormat}}put{{/collectionFormat}}("{{baseName}}", {{#isFile}}{{^collectionFormat}}new FileSystemResource({{paramName}}){{/collectionFormat}}{{/isFile}}{{#isFile}}{{#collectionFormat}}{{paramName}}.stream().map(FileSystemResource::new).collect(Collectors.toList()){{/collectionFormat}}{{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} {{/hasMore}}{{/formParams}}{{/hasFormParams}} final String[] accepts = { {{#hasProduces}} diff --git a/libraries/webclient/api.mustache b/libraries/webclient/api.mustache index 7b3c23d59b4..a8077006c8f 100644 --- a/libraries/webclient/api.mustache +++ b/libraries/webclient/api.mustache @@ -10,6 +10,7 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.stream.Collectors; {{/fullJavaUtil}} import org.springframework.beans.factory.annotation.Autowired; @@ -108,7 +109,7 @@ public class {{classname}} { {{#formParams}} if ({{paramName}} != null) - formParams.add{{#collectionFormat}}All{{/collectionFormat}}("{{baseName}}", {{#isFile}}new FileSystemResource({{paramName}}){{/isFile}}{{^isFile}}{{paramName}}{{/isFile}}); + formParams.add{{#collectionFormat}}All{{/collectionFormat}}("{{baseName}}", {{#isFile}}{{^collectionFormat}}new FileSystemResource({{paramName}}){{/collectionFormat}}{{/isFile}}{{#isFile}}{{#collectionFormat}}{{paramName}}.stream().map(FileSystemResource::new).collect(Collectors.toList()){{/collectionFormat}}{{/isFile}}{{^isFile}}{{paramName}}{{/isFile}}); {{/formParams}} {{/hasFormParams}} From dfd7eb85b7a1d92ad66823d6e2b58049d5c018cf Mon Sep 17 00:00:00 2001 From: jekkel Date: Wed, 8 Jul 2020 10:30:31 +0200 Subject: [PATCH 277/370] [Java][Client][vert.x] Support per-call authentication and JsonNullable in client request bodies, fix path parameter encoding (#5732) * Support per-call authentication and JsonNullable in client request bodies Extensions ---------- Since vertx is an asynchronous/reactive toolkit usage of mutable fields of `ApiClient` to store authentication prohibits delegation of authentication from incoming call without recreating the client everytime (which is prohibitively expensive due to instantiation of objectmapper). This commit adds a per call authentication override which takes precedence over the mutable fields so a single client can be safely reused. To ease usage a simple builder-style auxiliary `AuthInfo` object is provided providing methods for each specified authentication. A new configuration option for `ApiClient` has been added: `timeout`. It gets applied as timeout for the vertx http request. Fixes ----- Request bodies have been wrongly serialized using vert.x built-in objectmapper instead of the embedded instance thus usage of beans with `JsonNullable` wrapped fields in request bodies led to bad requests. * update vertx samples * Client Java Vertx: Add url encode for path parameters. * update vertx samples --- libraries/vertx/ApiClient.mustache | 80 ++++++++++++++++++++++++++++-- libraries/vertx/api.mustache | 3 ++ libraries/vertx/apiImpl.mustache | 44 ++++++++++++---- libraries/vertx/api_test.mustache | 4 +- libraries/vertx/rxApiImpl.mustache | 75 +++++++++++++++++++--------- 5 files changed, 166 insertions(+), 40 deletions(-) diff --git a/libraries/vertx/ApiClient.mustache b/libraries/vertx/ApiClient.mustache index bc19a925308..c7d0056fef8 100644 --- a/libraries/vertx/ApiClient.mustache +++ b/libraries/vertx/ApiClient.mustache @@ -9,6 +9,7 @@ import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; @@ -55,6 +56,7 @@ public class ApiClient { private DateFormat dateFormat; private ObjectMapper objectMapper; private String downloadsDir = ""; + private int timeout = -1; public ApiClient(Vertx vertx, JsonObject config) { Objects.requireNonNull(vertx, "Vertx must not be null"); @@ -96,6 +98,7 @@ public class ApiClient { this.downloadsDir = config.getString("downloadsDir", this.downloadsDir); this.config = config; this.identifier = UUID.randomUUID().toString(); + this.timeout = config.getInteger("timeout", -1); } public Vertx getVertx() { @@ -428,7 +431,11 @@ public class ApiClient { AsyncFile file = (AsyncFile) body; request.sendStream(file, responseHandler); } else { - request.sendJson(body, responseHandler); + try { + request.sendBuffer(Buffer.buffer(this.objectMapper.writeValueAsBytes(body)), responseHandler); + } catch (JsonProcessingException jsonProcessingException) { + responseHandler.handle(Future.failedFuture(jsonProcessingException)); + } } } @@ -446,14 +453,15 @@ public class ApiClient { * @param accepts The request's Accept headers * @param contentTypes The request's Content-Type headers * @param authNames The authentications to apply + * @param authInfo The call specific auth override * @param returnType The return type into which to deserialize the response * @param resultHandler The asynchronous response handler */ public void invokeAPI(String path, String method, List queryParams, Object body, MultiMap headerParams, - MultiMap cookieParams, Map formParams, String[] accepts, String[] contentTypes, String[] authNames, + MultiMap cookieParams, Map formParams, String[] accepts, String[] contentTypes, String[] authNames, AuthInfo authInfo, TypeReference returnType, Handler> resultHandler) { - updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); + updateParamsForAuth(authNames, authInfo, queryParams, headerParams, cookieParams); if (accepts != null && accepts.length > 0) { headerParams.add(HttpHeaders.ACCEPT, selectHeaderAccept(accepts)); @@ -465,6 +473,7 @@ public class ApiClient { HttpMethod httpMethod = HttpMethod.valueOf(method); HttpRequest request = getWebClient().requestAbs(httpMethod, basePath + path); + request.timeout(this.timeout); if (httpMethod == HttpMethod.PATCH) { request.putHeader("X-HTTP-Method-Override", "PATCH"); @@ -645,11 +654,72 @@ public class ApiClient { * * @param authNames The authentications to apply */ - protected void updateParamsForAuth(String[] authNames, List queryParams, MultiMap headerParams, MultiMap cookieParams) { + protected void updateParamsForAuth(String[] authNames, AuthInfo authInfo, List queryParams, MultiMap headerParams, MultiMap cookieParams) { for (String authName : authNames) { - Authentication auth = authentications.get(authName); + Authentication auth; + if (authInfo != null && authInfo.authentications.containsKey(authName)) { + auth = authInfo.authentications.get(authName); + } else { + auth = authentications.get(authName); + } if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); auth.applyToParams(queryParams, headerParams, cookieParams); } } + + public static class AuthInfo { + + private final Map authentications = new LinkedHashMap<>();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + + public void add{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(String username, String password) { + HttpBasicAuth auth = new HttpBasicAuth(); + auth.setUsername(username); + auth.setPassword(password); + authentications.put("{{name}}", auth); + }{{/isBasicBasic}}{{^isBasicBasic}} + + public void add{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(String bearerToken) { + HttpBearerAuth auth = new + HttpBearerAuth("{{scheme}}"); + auth.setBearerToken(bearerToken); + authentications.put("{{name}}", auth); + }{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + + public void add{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(String apikey, String apiKeyPrefix) { + ApiKeyAuth auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}},"{{keyParamName}}"); + auth.setApiKey(apikey); + auth.setApiKeyPrefix(apiKeyPrefix); + authentications.put("{{name}}", auth); + }{{/isApiKey}}{{#isOAuth}} + + public void add{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(String accessToken) { + OAuth auth = new OAuth(); + auth.setAccessToken(accessToken); + authentications.put("{{name}}", auth); + }{{/isOAuth}}{{/authMethods}}{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + + public static AuthInfo for{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}(String username, String password) { + AuthInfo authInfo = new AuthInfo(); + authInfo.add{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(username, password); + return authInfo; + }{{/isBasicBasic}}{{^isBasicBasic}} + + public static AuthInfo for{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(String bearerToken) { + AuthInfo authInfo = new AuthInfo(); + authInfo.add{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(bearerToken); + return authInfo; + }{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + + public static AuthInfo for{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(String apikey, String apiKeyPrefix) { + AuthInfo authInfo = new AuthInfo(); + authInfo.add{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(apikey, apiKeyPrefix); + return authInfo; + }{{/isApiKey}}{{#isOAuth}} + + public static AuthInfo for{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(String accessToken) { + AuthInfo authInfo = new AuthInfo(); + authInfo.add{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(accessToken); + return authInfo; + }{{/isOAuth}}{{/authMethods}} + } } diff --git a/libraries/vertx/api.mustache b/libraries/vertx/api.mustache index dcf9df4cc70..8cb5bd95373 100644 --- a/libraries/vertx/api.mustache +++ b/libraries/vertx/api.mustache @@ -1,5 +1,6 @@ package {{package}}; +import {{invokerPackage}}.ApiClient; {{#imports}}import {{import}}; {{/imports}} import io.vertx.core.AsyncResult; @@ -14,6 +15,8 @@ public interface {{classname}} { {{#operation}} void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}Handler> handler); + void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}ApiClient.AuthInfo authInfo, Handler> handler); + {{/operation}} {{/operations}} } diff --git a/libraries/vertx/apiImpl.mustache b/libraries/vertx/apiImpl.mustache index 5ea569f4ab2..ed38fe79438 100644 --- a/libraries/vertx/apiImpl.mustache +++ b/libraries/vertx/apiImpl.mustache @@ -11,6 +11,9 @@ import io.vertx.core.json.JsonObject; import com.fasterxml.jackson.core.type.TypeReference; import java.util.*; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import {{invokerPackage}}.ApiClient; import {{invokerPackage}}.ApiException; @@ -41,14 +44,27 @@ public class {{classname}}Impl implements {{classname}} { {{#operation}} /** - * {{summary}} - * {{notes}} - {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} - {{/allParams}} - * @param resultHandler Asynchronous result handler - */ + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @param resultHandler Asynchronous result handler + */ public void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}Handler> resultHandler) { + {{operationId}}({{#allParams}}{{paramName}}, {{/allParams}}null, resultHandler); + } + + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @param authInfo per call authentication override. + * @param resultHandler Asynchronous result handler + */ + public void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}ApiClient.AuthInfo authInfo, Handler> resultHandler) { Object localVarBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set @@ -58,7 +74,7 @@ public class {{classname}}Impl implements {{classname}} { } {{/required}}{{/allParams}} // create path and map variables - String localVarPath = "{{{path}}}"{{#pathParams}}.replaceAll("\\{" + "{{baseName}}" + "\\}", {{{paramName}}}.toString()){{/pathParams}}; + String localVarPath = "{{{path}}}"{{#pathParams}}.replaceAll("\\{" + "{{baseName}}" + "\\}", encodeParameter({{{paramName}}}.toString())){{/pathParams}}; // query params List localVarQueryParams = new ArrayList<>(); @@ -89,9 +105,17 @@ public class {{classname}}Impl implements {{classname}} { String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; {{#returnType}} TypeReference<{{{returnType}}}> localVarReturnType = new TypeReference<{{{returnType}}}>() {}; - apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccepts, localVarContentTypes, localVarAuthNames, localVarReturnType, resultHandler);{{/returnType}}{{^returnType}} - apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccepts, localVarContentTypes, localVarAuthNames, null, resultHandler);{{/returnType}} + apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccepts, localVarContentTypes, localVarAuthNames, authInfo, localVarReturnType, resultHandler);{{/returnType}}{{^returnType}} + apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccepts, localVarContentTypes, localVarAuthNames, authInfo, null, resultHandler);{{/returnType}} } {{/operation}} + + private String encodeParameter(String parameter) { + try { + return URLEncoder.encode(parameter, StandardCharsets.UTF_8.name()); + } catch (UnsupportedEncodingException e) { + return parameter; + } + } } {{/operations}} diff --git a/libraries/vertx/api_test.mustache b/libraries/vertx/api_test.mustache index 77010f248c1..5eb2ec7276a 100644 --- a/libraries/vertx/api_test.mustache +++ b/libraries/vertx/api_test.mustache @@ -56,8 +56,8 @@ public class {{classname}}Test { * @param context Vertx test context for doing assertions */ @Test - public void {{operationId}}Test(TestContext context) { - Async async = context.async(); + public void {{operationId}}Test(TestContext testContext) { + Async async = testContext.async(); {{#allParams}} {{{dataType}}} {{paramName}} = null; {{/allParams}} diff --git a/libraries/vertx/rxApiImpl.mustache b/libraries/vertx/rxApiImpl.mustache index be144ff3eaa..abb6e8458d4 100644 --- a/libraries/vertx/rxApiImpl.mustache +++ b/libraries/vertx/rxApiImpl.mustache @@ -2,6 +2,7 @@ package {{package}}.rxjava; {{#imports}}import {{import}}; {{/imports}} +import {{invokerPackage}}.ApiClient; import java.util.*; @@ -13,41 +14,69 @@ import io.vertx.core.Handler; {{#operations}} public class {{classname}} { - private final {{package}}.{{classname}} delegate; + private final {{package}}.{{classname}} delegate; - public {{classname}}({{package}}.{{classname}} delegate) { - this.delegate = delegate; + public {{classname}}({{package}}.{{classname}} delegate) { + this.delegate = delegate; } - public {{package}}.{{classname}} getDelegate() { - return delegate; - } + public {{package}}.{{classname}} getDelegate() { + return delegate; + } {{#operation}} /** - * {{summary}} - * {{notes}} - {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} - {{/allParams}} - * @param resultHandler Asynchronous result handler - */ + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @param resultHandler Asynchronous result handler + */ public void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}Handler> resultHandler) { delegate.{{operationId}}({{#allParams}}{{paramName}}, {{/allParams}}resultHandler); } /** - * {{summary}} - * {{notes}} - {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} - {{/allParams}} - * @return Asynchronous result handler (RxJava Single) - */ + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @param authInfo call specific auth overrides + * @param resultHandler Asynchronous result handler + */ + public void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}ApiClient.AuthInfo authInfo, Handler> resultHandler) { + delegate.{{operationId}}({{#allParams}}{{paramName}}, {{/allParams}}authInfo, resultHandler); + } + + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @return Asynchronous result handler (RxJava Single) + */ public Single<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> rx{{operationIdCamelCase}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) { - return Single.create(new io.vertx.rx.java.SingleOnSubscribeAdapter<>(fut -> { - delegate.{{operationId}}({{#allParams}}{{paramName}}, {{/allParams}}fut); - })); + return Single.create(new io.vertx.rx.java.SingleOnSubscribeAdapter<>(fut -> + delegate.{{operationId}}({{#allParams}}{{paramName}}, {{/allParams}}fut) + )); + } + + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @param authInfo call specific auth overrides + * @return Asynchronous result handler (RxJava Single) + */ + public Single<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> rx{{operationIdCamelCase}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}ApiClient.AuthInfo authInfo) { + return Single.create(new io.vertx.rx.java.SingleOnSubscribeAdapter<>(fut -> + delegate.{{operationId}}({{#allParams}}{{paramName}}, {{/allParams}}authInfo, fut) + )); } {{/operation}} From 56b37a0081e534b12244263e26fb551fb8e77416 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Tue, 14 Jul 2020 12:36:05 +0800 Subject: [PATCH 278/370] minor fix to sample code (java jersey2) (#6921) --- libraries/jersey2/api_doc.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/jersey2/api_doc.mustache b/libraries/jersey2/api_doc.mustache index f162d1cc974..0e43b4af0bd 100644 --- a/libraries/jersey2/api_doc.mustache +++ b/libraries/jersey2/api_doc.mustache @@ -33,7 +33,7 @@ import {{{invokerPackage}}}.ApiClient; import {{{invokerPackage}}}.ApiException; import {{{invokerPackage}}}.Configuration;{{#hasAuthMethods}} import {{{invokerPackage}}}.auth.*;{{/hasAuthMethods}} -import {{{invokerPackage}}}.models.*; +import {{{invokerPackage}}}.model.*; import {{{package}}}.{{{classname}}}; public class Example { From 9e8a3ccf6f65c0ad36271038c8b2c99e54241852 Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Mon, 13 Jul 2020 23:03:04 -0700 Subject: [PATCH 279/370] fix typo (#6928) --- libraries/jersey2/ApiClient.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index dc15ec47491..4e934eb0e33 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -888,7 +888,7 @@ public class ApiClient { * @param obj Object * @param formParams Form parameters * @param contentType Context type - * @param isBodyNulalble True if the body is nullable + * @param isBodyNullable True if the body is nullable * @return String * @throws ApiException API exception */ From 563b75df2a7801f53209c5ff46960f670bb27aea Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Tue, 14 Jul 2020 09:19:55 -0700 Subject: [PATCH 280/370] [Java][jersey2] Fix format of Date header in HTTP signature (#6925) * Use RFC 1123 date format for Date header in HTTP signature * Use RFC 1123 date format for Date header in HTTP signature --- libraries/jersey2/auth/HttpSignatureAuth.mustache | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libraries/jersey2/auth/HttpSignatureAuth.mustache b/libraries/jersey2/auth/HttpSignatureAuth.mustache index 787bef3db0c..9ff63420883 100644 --- a/libraries/jersey2/auth/HttpSignatureAuth.mustache +++ b/libraries/jersey2/auth/HttpSignatureAuth.mustache @@ -12,10 +12,12 @@ import java.security.Key; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Base64; +import java.util.Calendar; import java.util.Date; import java.util.Locale; import java.util.Map; import java.util.List; +import java.util.TimeZone; import java.security.spec.AlgorithmParameterSpec; import java.security.InvalidKeyException; @@ -236,7 +238,9 @@ public class HttpSignatureAuth implements Authentication { } if (headers.contains("date")) { - headerParams.put("date", new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US).format(new Date())); + SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); + dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); + headerParams.put("date", dateFormat.format(Calendar.getInstance().getTime())); } if (headers.contains("digest")) { From d40f9d13aea925d58ba78c98c6009dc4f92fa685 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 15 Jul 2020 00:50:37 +0800 Subject: [PATCH 281/370] fix null payload in java jersey2 (#6933) --- libraries/jersey2/ApiClient.mustache | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 4e934eb0e33..a10302b183d 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -874,9 +874,9 @@ public class ApiClient { } else { // We let jersey handle the serialization if (isBodyNullable) { // payload is nullable - entity = Entity.entity(obj == null ? Entity.text("null") : obj, contentType); + entity = Entity.entity(obj == null ? "null" : obj, contentType); } else { - entity = Entity.entity(obj == null ? Entity.text("") : obj, contentType); + entity = Entity.entity(obj == null ? "" : obj, contentType); } } return entity; From 53f2ca4b39133b9cd09c2d4ae213636d867f0c70 Mon Sep 17 00:00:00 2001 From: bgong-mdsol Date: Fri, 17 Jul 2020 03:30:02 -0400 Subject: [PATCH 282/370] [Java][Native] added WithHttpInfo method for async-native (#6903) * [java-asyncNative] add withHttpInfo * update api template for async-native --- libraries/native/README.mustache | 16 +++-- libraries/native/api.mustache | 99 ++++++++++++++++++++----------- libraries/native/api_doc.mustache | 45 ++++++++------ 3 files changed, 106 insertions(+), 54 deletions(-) diff --git a/libraries/native/README.mustache b/libraries/native/README.mustache index 7257a26f95f..66924985507 100644 --- a/libraries/native/README.mustache +++ b/libraries/native/README.mustache @@ -99,12 +99,19 @@ public class {{{classname}}}Example { {{/allParams}} try { {{^vendorExtensions.x-group-parameters}} - {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} result = {{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture result = {{/asyncNative}}{{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}{{#hasParams}} + {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} result = {{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture result = {{/asyncNative}}{{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{/vendorExtensions.x-group-parameters}} + {{#vendorExtensions.x-group-parameters}} + {{#hasParams}} API{{operationId}}Request request = API{{operationId}}Request.newBuilder(){{#allParams}} .{{paramName}}({{paramName}}){{/allParams}} - .build();{{/hasParams}} - {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} result = {{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture result = {{/asyncNative}}{{/returnType}}apiInstance.{{operationId}}({{#hasParams}}request{{/hasParams}});{{/vendorExtensions.x-group-parameters}}{{#returnType}} - System.out.println(result);{{/returnType}} + .build(); + {{/hasParams}} + {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} result = {{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture result = {{/asyncNative}}{{/returnType}}apiInstance.{{operationId}}({{#hasParams}}request{{/hasParams}}); + {{/vendorExtensions.x-group-parameters}} + {{#returnType}} + System.out.println(result{{#asyncNative}}.get(){{/asyncNative}}); + {{/returnType}} } catch (ApiException e) { System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); System.err.println("Status code: " + e.getCode()); @@ -124,6 +131,7 @@ All URIs are relative to *{{basePath}}* Class | Method | HTTP request | Description ------------ | ------------- | ------------- | ------------- {{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +*{{classname}}* | [**{{operationId}}WithHttpInfo**]({{apiDocPath}}{{classname}}.md#{{operationId}}WithHttpInfo) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} {{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} ## Documentation for Models diff --git a/libraries/native/api.mustache b/libraries/native/api.mustache index 1fca3864396..d524d312f22 100644 --- a/libraries/native/api.mustache +++ b/libraries/native/api.mustache @@ -3,9 +3,7 @@ package {{package}}; import {{invokerPackage}}.ApiClient; import {{invokerPackage}}.ApiException; -{{^asyncNative}} import {{invokerPackage}}.ApiResponse; -{{/asyncNative}} import {{invokerPackage}}.Pair; {{#imports}} @@ -57,6 +55,15 @@ public class {{classname}} { memberVarReadTimeout = apiClient.getReadTimeout(); memberVarResponseInterceptor = apiClient.getResponseInterceptor(); } + {{#asyncNative}} + + private ApiException getApiException(String operationId, HttpResponselocalVarResponse) { + return new ApiException(localVarResponse.statusCode(), + operationId + " call received non-success response", + localVarResponse.headers(), + localVarResponse.body()); + } + {{/asyncNative}} {{#operation}} {{#vendorExtensions.x-group-parameters}} @@ -66,7 +73,7 @@ public class {{classname}} { * {{notes}} * @param {{operationId}}Request {@link API{{operationId}}Request} {{#returnType}} - * @return {{returnType}} + * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}{{returnType}}{{#asyncNative}}>{{/asyncNative}} {{/returnType}} * @throws ApiException if fails to make API call {{#isDeprecated}} @@ -86,13 +93,12 @@ public class {{classname}} { {{/allParams}} {{#returnType}}return {{/returnType}}{{^returnType}}{{#asyncNative}}return {{/asyncNative}}{{/returnType}}{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); } - {{^asyncNative}} /** * {{summary}} * {{notes}} * @param {{operationId}}Request {@link API{{operationId}}Request} - * @return ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} * @throws ApiException if fails to make API call {{#isDeprecated}} * @deprecated @@ -105,13 +111,12 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo(API{{operationId}}Request {{operationId}}Request) throws ApiException { + public {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}}WithHttpInfo(API{{operationId}}Request {{operationId}}Request) throws ApiException { {{#allParams}} {{{dataType}}} {{paramName}} = {{operationId}}Request.{{paramName}}(); {{/allParams}} return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); } - {{/asyncNative}} {{/hasParams}} {{/vendorExtensions.x-group-parameters}} @@ -122,7 +127,7 @@ public class {{classname}} { * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}}{{/required}} {{/allParams}} {{#returnType}} - * @return {{returnType}} + * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}{{returnType}}{{#asyncNative}}>{{/asyncNative}} {{/returnType}} * @throws ApiException if fails to make API call {{#isDeprecated}} @@ -147,28 +152,23 @@ public class {{classname}} { try { HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); return memberVarHttpClient.sendAsync( - localVarRequestBuilder.build(), - HttpResponse.BodyHandlers.ofString()).thenComposeAsync(localVarResponse -> { - if (localVarResponse.statusCode()/ 100 != 2) { - return CompletableFuture.failedFuture(new ApiException(localVarResponse.statusCode(), - "{{operationId}} call received non-success response", - localVarResponse.headers(), - localVarResponse.body()) + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofString()).thenComposeAsync(localVarResponse -> { + if (localVarResponse.statusCode()/ 100 != 2) { + return CompletableFuture.failedFuture(getApiException("{{operationId}}", localVarResponse)); + } + {{#returnType}} + try { + return CompletableFuture.completedFuture( + memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference<{{{returnType}}}>() {}) ); - } else { - {{#returnType}} - try { - return CompletableFuture.completedFuture( - memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference<{{{returnType}}}>() {}) - ); - } catch (IOException e) { - return CompletableFuture.failedFuture(new ApiException(e)); - } - {{/returnType}} - {{^returnType}} - return CompletableFuture.completedFuture(null); - {{/returnType}} - } + } catch (IOException e) { + return CompletableFuture.failedFuture(new ApiException(e)); + } + {{/returnType}} + {{^returnType}} + return CompletableFuture.completedFuture(null); + {{/returnType}} }); } catch (ApiException e) { @@ -176,7 +176,6 @@ public class {{classname}} { } {{/asyncNative}} } - {{^asyncNative}} /** * {{summary}} @@ -184,7 +183,7 @@ public class {{classname}} { {{#allParams}} * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}}{{/required}} {{/allParams}} - * @return ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} * @throws ApiException if fails to make API call {{#isDeprecated}} * @deprecated @@ -197,7 +196,8 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + public {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + {{^asyncNative}} HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); try { HttpResponse localVarResponse = memberVarHttpClient.send( @@ -224,8 +224,41 @@ public class {{classname}} { Thread.currentThread().interrupt(); throw new ApiException(e); } + {{/asyncNative}} + {{#asyncNative}} + try { + HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + return memberVarHttpClient.sendAsync( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofString()).thenComposeAsync(localVarResponse -> { + if (localVarResponse.statusCode()/ 100 != 2) { + return CompletableFuture.failedFuture(getApiException("{{operationId}}", localVarResponse)); + } + {{#returnType}} + try { + return CompletableFuture.completedFuture( + new ApiResponse<{{{returnType}}}>( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference<{{{returnType}}}>() {})) + ); + } catch (IOException e) { + return CompletableFuture.failedFuture(new ApiException(e)); + } + {{/returnType}} + {{^returnType}} + return CompletableFuture.completedFuture( + new ApiResponse(localVarResponse.statusCode(), localVarResponse.headers().map(), null) + ); + {{/returnType}} + } + ); + } + catch (ApiException e) { + return CompletableFuture.failedFuture(e); + } + {{/asyncNative}} } - {{/asyncNative}} private HttpRequest.Builder {{operationId}}RequestBuilder({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { {{#allParams}} diff --git a/libraries/native/api_doc.mustache b/libraries/native/api_doc.mustache index ff699f921e6..603f7886480 100644 --- a/libraries/native/api_doc.mustache +++ b/libraries/native/api_doc.mustache @@ -7,9 +7,7 @@ All URIs are relative to *{{basePath}}* Method | HTTP request | Description ------------- | ------------- | ------------- {{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} -{{^asyncNative}} -[**{{operationId}}WithHttpInfo**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} -{{/asyncNative}} +[**{{operationId}}WithHttpInfo**]({{classname}}.md#{{operationId}}WithHttpInfo) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} {{/operation}}{{/operations}} {{#operations}} @@ -81,8 +79,11 @@ public class Example { .{{paramName}}({{paramName}}){{/allParams}} .build(); {{/hasParams}} - {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} result = {{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture result = {{/asyncNative}}{{/returnType}}apiInstance.{{operationId}}({{#hasParams}}request{{/hasParams}});{{/vendorExtensions.x-group-parameters}}{{#returnType}} - System.out.println(result);{{/returnType}} + {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} result = {{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture result = {{/asyncNative}}{{/returnType}}apiInstance.{{operationId}}({{#hasParams}}request{{/hasParams}}); + {{/vendorExtensions.x-group-parameters}} + {{#returnType}} + System.out.println(result{{#asyncNative}}.get(){{/asyncNative}}); + {{/returnType}} } catch (ApiException e) { System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); System.err.println("Status code: " + e.getCode()); @@ -131,15 +132,14 @@ Name | Type | Description | Notes | **{{code}}** | {{message}} | {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}} | {{/responses}} {{/responses.0}} -{{^asyncNative}} ## {{operationId}}WithHttpInfo {{^vendorExtensions.x-group-parameters}} -> ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}} {{operationId}}WithHttpInfo({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) +> {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}} {{operationId}}WithHttpInfo({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) {{/vendorExtensions.x-group-parameters}} {{#vendorExtensions.x-group-parameters}} -> ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}} {{operationId}}WithHttpInfo({{#hasParams}}{{operationId}}Request{{/hasParams}}) +> {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}} {{operationId}}WithHttpInfo({{#hasParams}}{{operationId}}Request{{/hasParams}}) {{/vendorExtensions.x-group-parameters}} {{summary}}{{#notes}} @@ -158,6 +158,9 @@ import {{{invokerPackage}}}.auth.*;{{/hasAuthMethods}} import {{{invokerPackage}}}.models.*; import {{{package}}}.{{{classname}}};{{#vendorExtensions.x-group-parameters}} import {{{package}}}.{{{classname}}}.*;{{/vendorExtensions.x-group-parameters}} +{{#asyncNative}} +import java.util.concurrent.CompletableFuture; +{{/asyncNative}} public class Example { public static void main(String[] args) { @@ -189,7 +192,7 @@ public class Example { {{/allParams}} try { {{^vendorExtensions.x-group-parameters}} - ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> response = apiInstance.{{{operationId}}}WithHttpInfo({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} response = apiInstance.{{{operationId}}}WithHttpInfo({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); {{/vendorExtensions.x-group-parameters}} {{#vendorExtensions.x-group-parameters}} {{#hasParams}} @@ -197,18 +200,27 @@ public class Example { .{{paramName}}({{paramName}}){{/allParams}} .build(); {{/hasParams}} - ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> response = apiInstance.{{{operationId}}}WithHttpInfo({{#hasParams}}request{{/hasParams}}); + {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} response = apiInstance.{{{operationId}}}WithHttpInfo({{#hasParams}}request{{/hasParams}}); {{/vendorExtensions.x-group-parameters}} - System.out.println("Status code: " + response.getStatusCode()); - System.out.println("Response headers: " + response.getHeaders().toString()); + System.out.println("Status code: " + response{{#asyncNative}}.get(){{/asyncNative}}.getStatusCode()); + System.out.println("Response headers: " + response{{#asyncNative}}.get(){{/asyncNative}}.getHeaders()); {{#returnType}} - System.out.println("Response body: " + response.getData().toString()); + System.out.println("Response body: " + response{{#asyncNative}}.get(){{/asyncNative}}.getData()); {{/returnType}} + {{#asyncNative}} + } catch (InterruptedException | ExecutionException e) { + ApiException apiException = (ApiException)e.getCause(); + System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); + System.err.println("Status code: " + apiException.getCode()); + System.err.println("Response headers: " + apiException.getResponseHeaders()); + System.err.println("Reason: " + apiException.getResponseBody()); + e.printStackTrace(); + {{/asyncNative}} } catch (ApiException e) { System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); System.err.println("Status code: " + e.getCode()); - System.err.println("Reason: " + e.getResponseBody()); System.err.println("Response headers: " + e.getResponseHeaders()); + System.err.println("Reason: " + e.getResponseBody()); e.printStackTrace(); } } @@ -232,8 +244,8 @@ Name | Type | Description | Notes ### Return type -{{#returnType}}ApiResponse<{{#returnTypeIsPrimitive}}**{{returnType}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{returnType}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}>{{/returnType}} -{{^returnType}}ApiResponse{{/returnType}} +{{#returnType}}{{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnTypeIsPrimitive}}**{{returnType}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{returnType}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}>{{#asyncNative}}>{{/asyncNative}}{{/returnType}} +{{^returnType}}{{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse{{#asyncNative}}>{{/asyncNative}}{{/returnType}} ### Authorization @@ -252,7 +264,6 @@ Name | Type | Description | Notes | **{{code}}** | {{message}} | {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}} | {{/responses}} {{/responses.0}} -{{/asyncNative}} {{#vendorExtensions.x-group-parameters}}{{#hasParams}} From f98f1c8f701464691c8d681a097e50f09167f10a Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Sat, 18 Jul 2020 06:56:41 -0700 Subject: [PATCH 283/370] [Java][Jersey2] Add JsonTypeName annotation (#6551) * Mustache template should use invokerPackage tag to generate import * add JsonSubTypes annotation to handle scenario when OAS name has special characters * add JsonSubTypes annotation to handle scenario when OAS name has special characters. Add unit test * run sample scripts * fix unit test * run sample scripts * add minimal openapi document to show issue with special characters and discriminators * Add 'isClassnameSanitized' tag * Add 'isClassnameSanitized' tag * Add 'isClassnameSanitized' tag * Add 'isClassnameSanitized' tag * Add 'isClassnameSanitized' tag * Add 'isClassnameSanitized' tag * Add unit tests for unmarshaling of discriminators with special characters * Add unit tests for unmarshaling of discriminators with special characters * use JsonTypeName Co-authored-by: Vikrant Balyan (vvb) Co-authored-by: William Cheng --- typeInfoAnnotation.mustache | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/typeInfoAnnotation.mustache b/typeInfoAnnotation.mustache index 81c2ba05f90..63eb42ea500 100644 --- a/typeInfoAnnotation.mustache +++ b/typeInfoAnnotation.mustache @@ -1,8 +1,16 @@ {{#jackson}} @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "{{{discriminator.propertyBaseName}}}", visible = true) +{{#discriminator.mappedModels}} +{{#-first}} @JsonSubTypes({ - {{#discriminator.mappedModels}} +{{/-first}} @JsonSubTypes.Type(value = {{modelName}}.class, name = "{{^vendorExtensions.x-discriminator-value}}{{mappingName}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}"), - {{/discriminator.mappedModels}} -}){{/jackson}} +{{#-last}} +}) +{{/-last}} +{{/discriminator.mappedModels}} +{{#isClassnameSanitized}} +@JsonTypeName("{{name}}") +{{/isClassnameSanitized}} +{{/jackson}} From ca423018b0f250c9479b028bdb94e76f41879b68 Mon Sep 17 00:00:00 2001 From: Moshe Elisha Date: Mon, 20 Jul 2020 17:54:14 +0300 Subject: [PATCH 284/370] [Java][RestTemplate] Use abstraction for files (#6912) * Fix dir path in PR request template * Add "useAbstractionForFiles" config option for Java/RestTemplate to allow flexible options in generated client when a file is needed (#6715) * Add "useAbstractionForFiles" config option for Java/RestTemplate to allow flexible options in generated client when a file is needed (#6715) * Add "useAbstractionForFiles" config option for Java/RestTemplate to allow flexible options in generated client when a file is needed (#6715) * #6715 - Add "useAbstractionForFiles" config option for Java/RestTemplate to allow flexible options in generated client when a file is needed. --- libraries/resttemplate/api.mustache | 6 +++--- libraries/resttemplate/api_test.mustache | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/resttemplate/api.mustache b/libraries/resttemplate/api.mustache index 2f1ed68e996..9c7a4fc703c 100644 --- a/libraries/resttemplate/api.mustache +++ b/libraries/resttemplate/api.mustache @@ -73,7 +73,7 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.AbstractResource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { {{#returnType}} return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}).getBody(); {{/returnType}} @@ -101,7 +101,7 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public ResponseEntity<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { + public ResponseEntity<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.AbstractResource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { Object postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set @@ -131,7 +131,7 @@ public class {{classname}} { {{/hasMore}}{{/cookieParams}}{{/hasCookieParams}}{{#hasFormParams}} {{#formParams}}if ({{paramName}} != null) - formParams.{{^collectionFormat}}add{{/collectionFormat}}{{#collectionFormat}}put{{/collectionFormat}}("{{baseName}}", {{#isFile}}{{^collectionFormat}}new FileSystemResource({{paramName}}){{/collectionFormat}}{{/isFile}}{{#isFile}}{{#collectionFormat}}{{paramName}}.stream().map(FileSystemResource::new).collect(Collectors.toList()){{/collectionFormat}}{{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} + formParams.{{^collectionFormat}}add{{/collectionFormat}}{{#collectionFormat}}put{{/collectionFormat}}("{{baseName}}", {{#isFile}}{{^collectionFormat}}{{#useAbstractionForFiles}}{{paramName}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}new FileSystemResource({{paramName}}){{/useAbstractionForFiles}}{{/collectionFormat}}{{/isFile}}{{#isFile}}{{#collectionFormat}}{{paramName}}.stream(){{^useAbstractionForFiles}}.map(FileSystemResource::new){{/useAbstractionForFiles}}.collect(Collectors.toList()){{/collectionFormat}}{{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} {{/hasMore}}{{/formParams}}{{/hasFormParams}} final String[] accepts = { {{#hasProduces}} diff --git a/libraries/resttemplate/api_test.mustache b/libraries/resttemplate/api_test.mustache index 127ac2defc5..f69cf40ec3e 100644 --- a/libraries/resttemplate/api_test.mustache +++ b/libraries/resttemplate/api_test.mustache @@ -34,7 +34,7 @@ public class {{classname}}Test { @Test public void {{operationId}}Test() { {{#allParams}} - {{{dataType}}} {{paramName}} = null; + {{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.AbstractResource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}} = null; {{/allParams}} {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); From 1d8c289983bb768b22cf35362a7608fd4b40c468 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Tue, 21 Jul 2020 14:21:10 +0800 Subject: [PATCH 285/370] add JsonTypeName (#6995) --- pojo.mustache | 1 + 1 file changed, 1 insertion(+) diff --git a/pojo.mustache b/pojo.mustache index 653f44062d1..1754416a396 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -8,6 +8,7 @@ {{classname}}.JSON_PROPERTY_{{nameInSnakeCase}}{{^-last}},{{/-last}} {{/vars}} }) +@JsonTypeName("{{name}}") {{/jackson}} {{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{ From 82688c07c340bad6d0980d3c67596880e2e179b8 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 22 Jul 2020 21:21:11 +0800 Subject: [PATCH 286/370] rollback feign version to 10.11 (#7012) --- libraries/feign/build.gradle.mustache | 2 +- libraries/feign/build.sbt.mustache | 6 +++--- libraries/feign/pom.mustache | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index 075db4f0cdb..be03d172b21 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -126,7 +126,7 @@ ext { {{#threetenbp}} jackson_threetenbp_version = "2.9.10" {{/threetenbp}} - feign_version = "11.0" + feign_version = "10.11" feign_form_version = "3.8.0" junit_version = "4.13" oltu_version = "1.0.1" diff --git a/libraries/feign/build.sbt.mustache b/libraries/feign/build.sbt.mustache index 664cc67edfc..933c9137af0 100644 --- a/libraries/feign/build.sbt.mustache +++ b/libraries/feign/build.sbt.mustache @@ -10,9 +10,9 @@ lazy val root = (project in file(".")). resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( "io.swagger" % "swagger-annotations" % "1.5.24" % "compile", - "io.github.openfeign" % "feign-core" % "11.0" % "compile", - "io.github.openfeign" % "feign-jackson" % "11.0" % "compile", - "io.github.openfeign" % "feign-slf4j" % "11.0" % "compile", + "io.github.openfeign" % "feign-core" % "10.11" % "compile", + "io.github.openfeign" % "feign-jackson" % "10.11" % "compile", + "io.github.openfeign" % "feign-slf4j" % "10.11" % "compile", "io.github.openfeign.form" % "feign-form" % "3.8.0" % "compile", "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index 60581b5336f..57bf1040dfe 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -348,7 +348,7 @@ ${java.version} ${java.version} 1.5.24 - 11.0 + 10.11 3.8.0 2.10.3 0.2.1 From 1a5602853519b2284500eb25752f62039f7c9468 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Thu, 23 Jul 2020 10:39:04 +0800 Subject: [PATCH 287/370] [Java][jersey2] Fix `serializeToString` (#6956) * fix empty get body in serializeToString, add tests * add new file * fix serialize to better handle null string * update test comments --- libraries/jersey2/ApiClient.mustache | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index a10302b183d..48c9d986bb5 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -874,9 +874,17 @@ public class ApiClient { } else { // We let jersey handle the serialization if (isBodyNullable) { // payload is nullable - entity = Entity.entity(obj == null ? "null" : obj, contentType); + if (obj instanceof String) { + entity = Entity.entity(obj == null ? "null" : "\"" + ((String)obj).replaceAll("\"", Matcher.quoteReplacement("\\\"")) + "\"", contentType); + } else { + entity = Entity.entity(obj == null ? "null" : obj, contentType); + } } else { - entity = Entity.entity(obj == null ? "" : obj, contentType); + if (obj instanceof String) { + entity = Entity.entity(obj == null ? "" : "\"" + ((String)obj).replaceAll("\"", Matcher.quoteReplacement("\\\"")) + "\"", contentType); + } else { + entity = Entity.entity(obj == null ? "" : obj, contentType); + } } } return entity; @@ -911,7 +919,7 @@ public class ApiClient { if (isBodyNullable) { return obj == null ? "null" : json.getMapper().writeValueAsString(obj); } else { - return json.getMapper().writeValueAsString(obj); + return obj == null ? "" : json.getMapper().writeValueAsString(obj); } } } catch (Exception ex) { From 3e395c7bcc960d98d7be6cf958952b1a931f9929 Mon Sep 17 00:00:00 2001 From: Slavek Kabrda Date: Thu, 23 Jul 2020 10:33:15 +0200 Subject: [PATCH 288/370] [java][jersey2-client] Disable coercion of scalars (#6811) * [java][jersey2-client] Disable coercion of scalars * Respect the coercion objectmapper setting in deserializers * Update jackson in maven plugin to get version that has ALLOW_COERCION_OF_SCALARS --- libraries/jersey2/JSON.mustache | 1 + libraries/jersey2/oneof_model.mustache | 32 +++++++++++++++++++++----- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/libraries/jersey2/JSON.mustache b/libraries/jersey2/JSON.mustache index bcc075ac9fc..2820eaa4bb1 100644 --- a/libraries/jersey2/JSON.mustache +++ b/libraries/jersey2/JSON.mustache @@ -34,6 +34,7 @@ public class JSON implements ContextResolver { public JSON() { mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true); mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); diff --git a/libraries/jersey2/oneof_model.mustache b/libraries/jersey2/oneof_model.mustache index dedc9d634f7..f3a51dccdc0 100644 --- a/libraries/jersey2/oneof_model.mustache +++ b/libraries/jersey2/oneof_model.mustache @@ -10,10 +10,12 @@ import java.util.HashSet; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; @@ -73,16 +75,34 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im {{/discriminator}} {{/useOneOfDiscriminatorLookup}} + boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS); int match = 0; + JsonToken token = tree.traverse(jp.getCodec()).nextToken(); {{#oneOf}} // deserialize {{{.}}} try { - deserialized = tree.traverse(jp.getCodec()).readValueAs({{{.}}}.class); - // TODO: there is no validation against JSON schema constraints - // (min, max, enum, pattern...), this does not perform a strict JSON - // validation, which means the 'match' count may be higher than it should be. - match++; - log.log(Level.FINER, "Input data matches schema '{{{.}}}'"); + boolean attemptParsing = true; + // ensure that we respect type coercion as set on the client ObjectMapper + if ({{{.}}}.class.equals(Integer.class) || {{{.}}}.class.equals(Long.class) || {{{.}}}.class.equals(Float.class) || {{{.}}}.class.equals(Double.class) || {{{.}}}.class.equals(Boolean.class) || {{{.}}}.class.equals(String.class)) { + attemptParsing = typeCoercion; + if (!attemptParsing) { + attemptParsing |= (({{{.}}}.class.equals(Integer.class) || {{{.}}}.class.equals(Long.class)) && token == JsonToken.VALUE_NUMBER_INT); + attemptParsing |= (({{{.}}}.class.equals(Float.class) || {{{.}}}.class.equals(Double.class)) && token == JsonToken.VALUE_NUMBER_FLOAT); + attemptParsing |= ({{{.}}}.class.equals(Boolean.class) && (token == JsonToken.VALUE_FALSE || token == JsonToken.VALUE_TRUE)); + attemptParsing |= ({{{.}}}.class.equals(String.class) && token == JsonToken.VALUE_STRING); + {{#isNullable}} + attemptParsing |= (token == JsonToken.VALUE_NULL); + {{/isNullable}} + } + } + if (attemptParsing) { + deserialized = tree.traverse(jp.getCodec()).readValueAs({{{.}}}.class); + // TODO: there is no validation against JSON schema constraints + // (min, max, enum, pattern...), this does not perform a strict JSON + // validation, which means the 'match' count may be higher than it should be. + match++; + log.log(Level.FINER, "Input data matches schema '{{{.}}}'"); + } } catch (Exception e) { // deserialization failed, continue log.log(Level.FINER, "Input data does not match schema '{{{.}}}'", e); From ec52113208113b88c014e55474014327de5723b2 Mon Sep 17 00:00:00 2001 From: Ravisankar-Challa Date: Fri, 24 Jul 2020 14:08:30 +1000 Subject: [PATCH 289/370] Add property additionalModelTypeAnnotations on the top of pojo class (#6037) --- libraries/microprofile/pojo.mustache | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/microprofile/pojo.mustache b/libraries/microprofile/pojo.mustache index b69cf9dbfd6..a2bd33a4766 100644 --- a/libraries/microprofile/pojo.mustache +++ b/libraries/microprofile/pojo.mustache @@ -33,6 +33,7 @@ import javax.json.bind.annotation.JsonbProperty; * {{{description}}} **/ {{/description}} +{{>additionalModelTypeAnnotations}} public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}}{{#serializableModel}} implements Serializable{{/serializableModel}} { {{#vars}}{{#isEnum}}{{^isContainer}} {{>enumClass}}{{/isContainer}}{{#isContainer}}{{#mostInnerItems}} From 6cb40d504f8f99bb5879738ea25d6d687ec81553 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 24 Jul 2020 18:44:15 +0800 Subject: [PATCH 290/370] [Java][jersey2] fix query parameters in applyToParams (#7028) * fix query parameters in applyToParams * update samples --- libraries/jersey2/auth/HttpSignatureAuth.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/jersey2/auth/HttpSignatureAuth.mustache b/libraries/jersey2/auth/HttpSignatureAuth.mustache index 9ff63420883..b9fff30675f 100644 --- a/libraries/jersey2/auth/HttpSignatureAuth.mustache +++ b/libraries/jersey2/auth/HttpSignatureAuth.mustache @@ -257,7 +257,7 @@ public class HttpSignatureAuth implements Authentication { // Calling getRawPath and getRawQuery ensures the path is URL-encoded as it will be serialized // on the wire. The HTTP signature must use the encode URL as it is sent on the wire. String path = uri.getRawPath(); - if (uri.getRawQuery() != "") { + if (uri.getRawQuery() != null && !"".equals(uri.getRawQuery())) { path += "?" + uri.getRawQuery(); } From 9b0e71cc5bfe620ddb19719c3f43d4039c06b5c3 Mon Sep 17 00:00:00 2001 From: Moshe Elisha Date: Mon, 27 Jul 2020 17:54:00 +0300 Subject: [PATCH 291/370] #6715 - Use Resource interface instead of AbstractResource when useAbstractionForFiles=true. (#7051) --- libraries/resttemplate/api.mustache | 4 ++-- libraries/resttemplate/api_test.mustache | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/resttemplate/api.mustache b/libraries/resttemplate/api.mustache index 9c7a4fc703c..c139c9b534f 100644 --- a/libraries/resttemplate/api.mustache +++ b/libraries/resttemplate/api.mustache @@ -73,7 +73,7 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.AbstractResource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { {{#returnType}} return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}).getBody(); {{/returnType}} @@ -101,7 +101,7 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public ResponseEntity<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.AbstractResource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { + public ResponseEntity<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { Object postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set diff --git a/libraries/resttemplate/api_test.mustache b/libraries/resttemplate/api_test.mustache index f69cf40ec3e..a82e352f6fc 100644 --- a/libraries/resttemplate/api_test.mustache +++ b/libraries/resttemplate/api_test.mustache @@ -34,7 +34,7 @@ public class {{classname}}Test { @Test public void {{operationId}}Test() { {{#allParams}} - {{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.AbstractResource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}} = null; + {{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}} = null; {{/allParams}} {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); From b6160fedfe14a61895d46750ce77d5269b0fa241 Mon Sep 17 00:00:00 2001 From: Benjamin Seiller Date: Tue, 28 Jul 2020 04:22:46 +0200 Subject: [PATCH 292/370] [Java][okhttp-gson] prevent UnsupportedOperationException by removal from ImmutableList on setDebugging(false) (#7024) * fix https://github.com/OpenAPITools/openapi-generator/issues/6934 * fix https://github.com/OpenAPITools/openapi-generator/issues/6934 * update samples Co-authored-by: William Cheng --- libraries/okhttp-gson/ApiClient.mustache | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index 0b74114ac5e..087a4a54edb 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -530,7 +530,9 @@ public class ApiClient { loggingInterceptor.setLevel(Level.BODY); httpClient = httpClient.newBuilder().addInterceptor(loggingInterceptor).build(); } else { - httpClient.interceptors().remove(loggingInterceptor); + final OkHttpClient.Builder builder = httpClient.newBuilder(); + builder.interceptors().remove(loggingInterceptor); + httpClient = builder.build(); loggingInterceptor = null; } } From 053d4e444c389f547bdc9abd030fbd2f5119614c Mon Sep 17 00:00:00 2001 From: TIm Clark Date: Sun, 2 Aug 2020 04:18:44 -0400 Subject: [PATCH 293/370] [Java][jersey2]Fix gradle HttpSignatureAuth dependencies (#7096) * Corrects tag for including HttpSignatureAuth in gradle builds * Updates version of org.tomitribe:tomitribe-http-signatures in gradle template to match version from maven template * Updates samples --- libraries/jersey2/build.gradle.mustache | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index fa00d428c3f..b2f37d720e9 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -137,9 +137,9 @@ ext { {{#hasOAuthMethods}} scribejava_apis_version = "6.9.0" {{/hasOAuthMethods}} - {{#hasHttpBasicMethods}} - tomitribe_http_signatures_version = "1.3" - {{/hasHttpBasicMethods}} + {{#hasHttpSignatureMethods}} + tomitribe_http_signatures_version = "1.5" + {{/hasHttpSignatureMethods}} } dependencies { @@ -161,9 +161,9 @@ dependencies { {{#hasOAuthMethods}} compile "com.github.scribejava:scribejava-apis:$scribejava_apis_version" {{/hasOAuthMethods}} - {{#hasHttpBasicMethods}} + {{#hasHttpSignatureMethods}} compile "org.tomitribe:tomitribe-http-signatures:$tomitribe_http_signatures_version" - {{/hasHttpBasicMethods}} + {{/hasHttpSignatureMethods}} {{#supportJava6}} compile "commons-io:commons-io:$commons_io_version" compile "org.apache.commons:commons-lang3:$commons_lang3_version" From 9b5f0ea463697fcfdd72c84517b2550ae4f1b3ad Mon Sep 17 00:00:00 2001 From: William Cheng Date: Mon, 3 Aug 2020 10:10:47 +0800 Subject: [PATCH 294/370] fix http signaure auth in build.sbt (#7110) --- libraries/jersey2/build.sbt.mustache | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/jersey2/build.sbt.mustache b/libraries/jersey2/build.sbt.mustache index d4262ef3fdd..db857d5ea4d 100644 --- a/libraries/jersey2/build.sbt.mustache +++ b/libraries/jersey2/build.sbt.mustache @@ -28,9 +28,9 @@ lazy val root = (project in file(".")). {{#hasOAuthMethods}} "com.github.scribejava" % "scribejava-apis" % "6.9.0" % "compile", {{/hasOAuthMethods}} - {{#hasHttpBasicMethods}} - "org.tomitribe" % "tomitribe-http-signatures" % "1.3" % "compile", - {{/hasHttpBasicMethods}} + {{#hasHttpSignatureMethods}} + "org.tomitribe" % "tomitribe-http-signatures" % "1.5" % "compile", + {{/hasHttpSignatureMethods}} {{^java8}} "com.brsanthu" % "migbase64" % "2.2", {{/java8}} From 8fa8ac96d2f0c61f7d70ec2c6738f31fcf15f32a Mon Sep 17 00:00:00 2001 From: mikesaurus <64160787+mikesaurus@users.noreply.github.com> Date: Mon, 3 Aug 2020 21:52:16 -0400 Subject: [PATCH 295/370] ISSUE-4222: Prevent conflicts with accept(s) local variables in generated Java RestTemplate ApiClient (#7101) * ISSUE-4222: Change accept(s) to localVarAccept(s) in Java/resttemplate/api.mustache * ISSUE-4222: Regenerate samples --- libraries/resttemplate/api.mustache | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/resttemplate/api.mustache b/libraries/resttemplate/api.mustache index c139c9b534f..0ac5c6df753 100644 --- a/libraries/resttemplate/api.mustache +++ b/libraries/resttemplate/api.mustache @@ -134,19 +134,19 @@ public class {{classname}} { formParams.{{^collectionFormat}}add{{/collectionFormat}}{{#collectionFormat}}put{{/collectionFormat}}("{{baseName}}", {{#isFile}}{{^collectionFormat}}{{#useAbstractionForFiles}}{{paramName}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}new FileSystemResource({{paramName}}){{/useAbstractionForFiles}}{{/collectionFormat}}{{/isFile}}{{#isFile}}{{#collectionFormat}}{{paramName}}.stream(){{^useAbstractionForFiles}}.map(FileSystemResource::new){{/useAbstractionForFiles}}.collect(Collectors.toList()){{/collectionFormat}}{{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} {{/hasMore}}{{/formParams}}{{/hasFormParams}} - final String[] accepts = { {{#hasProduces}} + final String[] localVarAccepts = { {{#hasProduces}} {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} - {{/hasProduces}}}; - final List accept = apiClient.selectHeaderAccept(accepts); + {{/hasProduces}} }; + final List localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); final String[] contentTypes = { {{#hasConsumes}} {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} - {{/hasConsumes}}}; + {{/hasConsumes}} }; final MediaType contentType = apiClient.selectHeaderContentType(contentTypes); String[] authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; {{#returnType}}ParameterizedTypeReference<{{{returnType}}}> returnType = new ParameterizedTypeReference<{{{returnType}}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference returnType = new ParameterizedTypeReference() {};{{/returnType}} - return apiClient.invokeAPI(path, HttpMethod.{{httpMethod}}, queryParams, postBody, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType); + return apiClient.invokeAPI(path, HttpMethod.{{httpMethod}}, queryParams, postBody, headerParams, cookieParams, formParams, localVarAccept, contentType, authNames, returnType); } {{/operation}} } From 730b1dbe7384f3f21a5c926b06f96870f34d1d0f Mon Sep 17 00:00:00 2001 From: Dmitry Mavrichev <68993831+dmavrichev@users.noreply.github.com> Date: Tue, 4 Aug 2020 07:44:18 +0400 Subject: [PATCH 296/370] [BUG][JAVA] Fix error handling in okhttp-gson async api client (#7089) * Fix error handling in okhttp-gson async api client * update samples Co-authored-by: William Cheng --- libraries/okhttp-gson/ApiClient.mustache | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index 087a4a54edb..37572c1b4a7 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -1083,6 +1083,9 @@ public class ApiClient { } catch (ApiException e) { callback.onFailure(e, response.code(), response.headers().toMultimap()); return; + } catch (Exception e) { + callback.onFailure(new ApiException(e), response.code(), response.headers().toMultimap()); + return; } callback.onSuccess(result, response.code(), response.headers().toMultimap()); } From ca123be5b236d2e29b9073dcd69aaa755bc2ae94 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 5 Aug 2020 10:27:38 +0800 Subject: [PATCH 297/370] [Java][jersey2] Add helper methods for oneOf Java classes (#7115) * add helper methods for oneOf java class * better test comment --- libraries/jersey2/oneof_model.mustache | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/libraries/jersey2/oneof_model.mustache b/libraries/jersey2/oneof_model.mustache index f3a51dccdc0..64da76c849d 100644 --- a/libraries/jersey2/oneof_model.mustache +++ b/libraries/jersey2/oneof_model.mustache @@ -183,7 +183,8 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im /** * Set the instance that matches the oneOf child schema, check - * the instance parameter is valid against the oneOf child schemas. + * the instance parameter is valid against the oneOf child schemas: + * {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}} * * It could be an instance of the 'oneOf' schemas. * The oneOf child schemas may themselves be a composed schema (allOf, anyOf, oneOf). @@ -207,6 +208,28 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im throw new RuntimeException("Invalid instance type. Must be {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}"); } + /** + * Get the actual instance, which can be the following: + * {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}} + * + * @return The actual instance ({{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}) + */ + @Override + public Object getActualInstance() { + return super.getActualInstance(); + } + {{#oneOf}} + /** + * Get the actual instance of `{{{.}}}`. If the actual instanct is not `{{{.}}}`, + * the ClassCastException will be thrown. + * + * @return The actual instance of `{{{.}}}` + * @throws ClassCastException if the instance is not `{{{.}}}` + */ + public {{{.}}} get{{{.}}}() throws ClassCastException { + return ({{{.}}})super.getActualInstance(); + } + {{/oneOf}} } From 14363fc38d84133512735cbae847cdd19eb8c172 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Thu, 6 Aug 2020 15:12:44 +0800 Subject: [PATCH 298/370] add helper methods to anyOf in java models (#7130) --- libraries/jersey2/anyof_model.mustache | 33 ++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/libraries/jersey2/anyof_model.mustache b/libraries/jersey2/anyof_model.mustache index e23cece67dd..668200778ea 100644 --- a/libraries/jersey2/anyof_model.mustache +++ b/libraries/jersey2/anyof_model.mustache @@ -148,6 +148,14 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im return {{classname}}.schemas; } + /** + * Set the instance that matches the anyOf child schema, check + * the instance parameter is valid against the anyOf child schemas: + * {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}} + * + * It could be an instance of the 'anyOf' schemas. + * The anyOf child schemas may themselves be a composed schema (allOf, anyOf, anyOf). + */ @Override public void setActualInstance(Object instance) { {{#isNullable}} @@ -166,4 +174,29 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im {{/anyOf}} throw new RuntimeException("Invalid instance type. Must be {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}"); } + + /** + * Get the actual instance, which can be the following: + * {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}} + * + * @return The actual instance ({{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}) + */ + @Override + public Object getActualInstance() { + return super.getActualInstance(); + } + + {{#anyOf}} + /** + * Get the actual instance of `{{{.}}}`. If the actual instanct is not `{{{.}}}`, + * the ClassCastException will be thrown. + * + * @return The actual instance of `{{{.}}}` + * @throws ClassCastException if the instance is not `{{{.}}}` + */ + public {{{.}}} get{{{.}}}() throws ClassCastException { + return ({{{.}}})super.getActualInstance(); + } + + {{/anyOf}} } From a3e88a903cdb10f6ba690f7efc56ab00c295f3a8 Mon Sep 17 00:00:00 2001 From: beytun Date: Wed, 12 Aug 2020 08:29:50 +0200 Subject: [PATCH 299/370] [Java] Update templates not to add @Pattern on byte array property (#7153) * Update Java templates to skip generating @Pattern on byte array properties * Revert separator changes * Revert separator changes --- beanValidationCore.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beanValidationCore.mustache b/beanValidationCore.mustache index ae26b2739f1..1f9f43e7b86 100644 --- a/beanValidationCore.mustache +++ b/beanValidationCore.mustache @@ -1,4 +1,4 @@ -{{#pattern}} @Pattern(regexp="{{{pattern}}}"){{/pattern}}{{! +{{#pattern}}{{^isByteArray}} @Pattern(regexp="{{{pattern}}}"){{/isByteArray}}{{/pattern}}{{! minLength && maxLength set }}{{#minLength}}{{#maxLength}} @Size(min={{minLength}},max={{maxLength}}){{/maxLength}}{{/minLength}}{{! minLength set, maxLength not From 01c0bbcb5d950a331e14721bc7b903ac101558ba Mon Sep 17 00:00:00 2001 From: Jon Freedman Date: Wed, 12 Aug 2020 08:55:53 +0100 Subject: [PATCH 300/370] [Java] parameterize formParams (#5784) * parameterize formParams fixes #5782 * sync generated code * update to latest version of spring, replace MultiValueMap#put with #addAll, remove unused imports * restore java.util.HashMap import * update spring version in pom/gradle templates * re-generate resttemplate samples * fix test * fix test * parameterize an additional usage of LinkedMultiValueMap * re-generate resttemplate samples * re-generate webclient samples * manually edit FILES to replace \ with / --- libraries/resttemplate/api.mustache | 8 +++----- libraries/resttemplate/build.gradle.mustache | 15 ++++++++------- libraries/resttemplate/pom.mustache | 9 +++++++-- libraries/webclient/ApiClient.mustache | 2 +- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/libraries/resttemplate/api.mustache b/libraries/resttemplate/api.mustache index 0ac5c6df753..21a86a96a4a 100644 --- a/libraries/resttemplate/api.mustache +++ b/libraries/resttemplate/api.mustache @@ -5,8 +5,7 @@ import {{invokerPackage}}.ApiClient; {{#imports}}import {{import}}; {{/imports}} -{{^fullJavaUtil}}import java.util.ArrayList; -import java.util.Collections; +{{^fullJavaUtil}}import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -19,7 +18,6 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestClientException; import org.springframework.web.client.HttpClientErrorException; -import org.springframework.web.util.UriComponentsBuilder; import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.io.FileSystemResource; import org.springframework.http.HttpHeaders; @@ -117,7 +115,7 @@ public class {{classname}} { final MultiValueMap queryParams = new LinkedMultiValueMap(); final HttpHeaders headerParams = new HttpHeaders(); final MultiValueMap cookieParams = new LinkedMultiValueMap(); - final MultiValueMap formParams = new LinkedMultiValueMap();{{#hasQueryParams}} + final MultiValueMap formParams = new LinkedMultiValueMap();{{#hasQueryParams}} {{#queryParams}}queryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{#hasMore}} {{/hasMore}}{{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}} @@ -131,7 +129,7 @@ public class {{classname}} { {{/hasMore}}{{/cookieParams}}{{/hasCookieParams}}{{#hasFormParams}} {{#formParams}}if ({{paramName}} != null) - formParams.{{^collectionFormat}}add{{/collectionFormat}}{{#collectionFormat}}put{{/collectionFormat}}("{{baseName}}", {{#isFile}}{{^collectionFormat}}{{#useAbstractionForFiles}}{{paramName}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}new FileSystemResource({{paramName}}){{/useAbstractionForFiles}}{{/collectionFormat}}{{/isFile}}{{#isFile}}{{#collectionFormat}}{{paramName}}.stream(){{^useAbstractionForFiles}}.map(FileSystemResource::new){{/useAbstractionForFiles}}.collect(Collectors.toList()){{/collectionFormat}}{{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} + formParams.{{^collectionFormat}}add{{/collectionFormat}}{{#collectionFormat}}addAll{{/collectionFormat}}("{{baseName}}", {{#isFile}}{{^collectionFormat}}{{#useAbstractionForFiles}}{{paramName}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}new FileSystemResource({{paramName}}){{/useAbstractionForFiles}}{{/collectionFormat}}{{/isFile}}{{#isFile}}{{#collectionFormat}}{{paramName}}.stream(){{^useAbstractionForFiles}}.map(FileSystemResource::new){{/useAbstractionForFiles}}.collect(Collectors.toList()){{/collectionFormat}}{{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} {{/hasMore}}{{/formParams}}{{/hasFormParams}} final String[] localVarAccepts = { {{#hasProduces}} diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index 7190f95a95f..c7e1fca9aa6 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -24,7 +24,7 @@ if(hasProperty('target') && target == 'android') { apply plugin: 'com.android.library' apply plugin: 'com.github.dcendents.android-maven' - + android { compileSdkVersion 23 buildToolsVersion '23.0.2' @@ -48,7 +48,7 @@ if(hasProperty('target') && target == 'android') { {{/java8}} {{/supportJava6}} } - + // Rename the aar correctly libraryVariants.all { variant -> variant.outputs.each { output -> @@ -64,7 +64,7 @@ if(hasProperty('target') && target == 'android') { provided 'javax.annotation:jsr250-api:1.0' } } - + afterEvaluate { android.libraryVariants.all { variant -> def task = project.tasks.create "jar${variant.name.capitalize()}", Jar @@ -76,12 +76,12 @@ if(hasProperty('target') && target == 'android') { artifacts.add('archives', task); } } - + task sourcesJar(type: Jar) { from android.sourceSets.main.java.srcDirs classifier = 'sources' } - + artifacts { archives sourcesJar } @@ -111,7 +111,7 @@ if(hasProperty('target') && target == 'android') { pom.artifactId = '{{artifactId}}' } } - + task execute(type:JavaExec) { main = System.getProperty('mainClass') classpath = sourceSets.main.runtimeClasspath @@ -123,7 +123,7 @@ ext { jackson_version = "2.10.4" jackson_databind_version = "2.10.4" jackson_databind_nullable_version = "0.2.1" - spring_web_version = "4.3.9.RELEASE" + spring_web_version = "5.2.5.RELEASE" jodatime_version = "2.9.9" junit_version = "4.13" {{#threetenbp}} @@ -135,6 +135,7 @@ dependencies { compile "io.swagger:swagger-annotations:$swagger_annotations_version" compile "com.google.code.findbugs:jsr305:3.0.2" compile "org.springframework:spring-web:$spring_web_version" + compile "org.springframework:spring-context:$spring_web_version" compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache index f3a1f0abda9..f95a520f5b6 100644 --- a/libraries/resttemplate/pom.mustache +++ b/libraries/resttemplate/pom.mustache @@ -222,7 +222,7 @@ swagger-annotations ${swagger-annotations-version}
- + com.google.code.findbugs @@ -236,6 +236,11 @@ spring-web ${spring-web-version} + + org.springframework + spring-context + ${spring-web-version} + @@ -317,7 +322,7 @@ UTF-8 1.5.22 - 4.3.9.RELEASE + 5.2.5.RELEASE 2.10.4 2.10.4 0.2.1 diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index f38a9b8c450..712ac17c637 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -492,7 +492,7 @@ public class ApiClient { */ protected BodyInserter selectBody(Object obj, MultiValueMap formParams, MediaType contentType) { if(MediaType.APPLICATION_FORM_URLENCODED.equals(contentType)) { - MultiValueMap map = new LinkedMultiValueMap(); + MultiValueMap map = new LinkedMultiValueMap<>(); formParams .toSingleValueMap() From df81afc51a32d0e01a7e1dbef78355e01b78306c Mon Sep 17 00:00:00 2001 From: Oleh Kurpiak Date: Wed, 12 Aug 2020 11:31:03 +0300 Subject: [PATCH 301/370] [REQ][Java] Additional annotations with String params (#7117) * Additional annotations with String params * Additional annotations with String params. Missed sample update * Additional annotations with String params. Use Jackson annotations * insert unescaped content * fix imports * fix imports --- additionalModelTypeAnnotations.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/additionalModelTypeAnnotations.mustache b/additionalModelTypeAnnotations.mustache index e5dc1ac1295..f4871c02cc2 100644 --- a/additionalModelTypeAnnotations.mustache +++ b/additionalModelTypeAnnotations.mustache @@ -1,2 +1,2 @@ -{{#additionalModelTypeAnnotations}}{{.}} +{{#additionalModelTypeAnnotations}}{{{.}}} {{/additionalModelTypeAnnotations}} \ No newline at end of file From 720d94084413b4d8b1b95e5e65512eb4c745804e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alja=C5=BE=20Pavi=C5=A1i=C4=8D?= Date: Thu, 20 Aug 2020 04:25:05 +0200 Subject: [PATCH 302/370] Support for KumuluzEE microprofile runtime (#5944) * Added library and edited generator to support server stub generation with Kumuluzee framework. * Trimmed and tweaked pom.xml template and removed unnecessary template files from generator and library. * minor edits * Added new library to Java client codegen (microprofile-kumuluzee). A functional KumuluzEE REST client can now be generated. * Edited README for microprofile-kumuluzee * Edited docs to include new KumuluzEE library options. * Updated kee-rest-client client POM dependency version to latest * fixed pom, edited REAMDE * Trimmed redundant dependencies from KEE client pom * Removed unnecessary DefaultGenerator edit, modified config template accordingly. * Made mp framework an additional property for microprofile instead of being another library option, removed now redundant library files. * Updated documentation with microprofile framework * Fixed errors caused by removed functions and variables * update doc Co-authored-by: Chuckledog Co-authored-by: Jan Meznaric Co-authored-by: William Cheng --- .../microprofile/kumuluzee.beans.xml.mustache | 5 + .../kumuluzee.config.yaml.mustache | 10 ++ libraries/microprofile/kumuluzee.pom.mustache | 98 +++++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 libraries/microprofile/kumuluzee.beans.xml.mustache create mode 100644 libraries/microprofile/kumuluzee.config.yaml.mustache create mode 100644 libraries/microprofile/kumuluzee.pom.mustache diff --git a/libraries/microprofile/kumuluzee.beans.xml.mustache b/libraries/microprofile/kumuluzee.beans.xml.mustache new file mode 100644 index 00000000000..29549d01d2c --- /dev/null +++ b/libraries/microprofile/kumuluzee.beans.xml.mustache @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/libraries/microprofile/kumuluzee.config.yaml.mustache b/libraries/microprofile/kumuluzee.config.yaml.mustache new file mode 100644 index 00000000000..90f5237eb99 --- /dev/null +++ b/libraries/microprofile/kumuluzee.config.yaml.mustache @@ -0,0 +1,10 @@ +kumuluzee: + server: + http: + port: 8081 + + rest-client: + registrations: + {{#apiInfo}}{{#apis}}{{#operations}}- class: {{{invokerPackage}}}.{{{classname}}} + url: http://localhost:8080/v2 + {{/operations}}{{/apis}}{{/apiInfo}} \ No newline at end of file diff --git a/libraries/microprofile/kumuluzee.pom.mustache b/libraries/microprofile/kumuluzee.pom.mustache new file mode 100644 index 00000000000..ac235b7edf5 --- /dev/null +++ b/libraries/microprofile/kumuluzee.pom.mustache @@ -0,0 +1,98 @@ + + 4.0.0 + + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + 1.0.0-SNAPSHOT + + + 1.8 + 1.8 + UTF-8 + + 3.9.0 + 1.2.3 + 1.4.1 + 3.2.6 + 4.13 + 2.28 + + + + + + com.kumuluz.ee + kumuluzee-bom + ${kumuluzee.version} + pom + import + + + + + + + com.kumuluz.ee + kumuluzee-core + + + com.kumuluz.ee + kumuluzee-servlet-jetty + + + com.kumuluz.ee + kumuluzee-jax-rs-jersey + + + com.kumuluz.ee + kumuluzee-cdi-weld + + + com.kumuluz.ee + kumuluzee-json-p-jsonp + + + com.kumuluz.ee + kumuluzee-json-b-yasson + + + com.kumuluz.ee.rest-client + kumuluzee-rest-client + ${kumuluzee-rest-client.version} + + + org.apache.cxf + cxf-rt-rs-extension-providers + ${cxf-rt-rs-extension-providers.version} + + + junit + junit + ${junit-version} + test + + + + + + + com.kumuluz.ee + kumuluzee-maven-plugin + ${kumuluzee.version} + + + package + + repackage + + + + + + + + \ No newline at end of file From 33f2a6626959b222fe55849a2b04d05de2e4dc86 Mon Sep 17 00:00:00 2001 From: TIm Clark Date: Fri, 21 Aug 2020 04:51:11 -0400 Subject: [PATCH 303/370] [Java][jersey2] Add jersey injection dependencies (#7240) * Adds the jersey injection dependency to gradle and sbt to match the maven dependency. * Update jersey version in sbt --- libraries/jersey2/build.gradle.mustache | 1 + libraries/jersey2/build.sbt.mustache | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index b2f37d720e9..c8747cca6db 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -146,6 +146,7 @@ dependencies { compile "io.swagger:swagger-annotations:$swagger_annotations_version" compile "com.google.code.findbugs:jsr305:3.0.2" compile "org.glassfish.jersey.core:jersey-client:$jersey_version" + compile "org.glassfish.jersey.inject:jersey-hk2:$jersey_version" compile "org.glassfish.jersey.media:jersey-media-multipart:$jersey_version" compile "org.glassfish.jersey.media:jersey-media-json-jackson:$jersey_version" compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" diff --git a/libraries/jersey2/build.sbt.mustache b/libraries/jersey2/build.sbt.mustache index db857d5ea4d..be3b7595eb3 100644 --- a/libraries/jersey2/build.sbt.mustache +++ b/libraries/jersey2/build.sbt.mustache @@ -10,9 +10,10 @@ lazy val root = (project in file(".")). resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( "io.swagger" % "swagger-annotations" % "1.5.22", - "org.glassfish.jersey.core" % "jersey-client" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, - "org.glassfish.jersey.media" % "jersey-media-multipart" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, - "org.glassfish.jersey.media" % "jersey-media-json-jackson" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, + "org.glassfish.jersey.core" % "jersey-client" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.27"{{/supportJava6}},{{^supportJava6}} + "org.glassfish.jersey.inject" % "jersey-hk2" % "2.27",{{/supportJava6}} + "org.glassfish.jersey.media" % "jersey-media-multipart" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.27"{{/supportJava6}}, + "org.glassfish.jersey.media" % "jersey-media-json-jackson" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.27"{{/supportJava6}}, "com.fasterxml.jackson.core" % "jackson-core" % "2.10.4" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.4" % "compile", "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.4" % "compile", From 50d26a4ff9f2d52a3160b3499d9d1d022855685e Mon Sep 17 00:00:00 2001 From: Niels Pardon Date: Tue, 25 Aug 2020 04:06:19 +0200 Subject: [PATCH 304/370] [Java][clients] remove java.lang prefix from Object (#6806) --- libraries/jersey2/AbstractOpenApiSchema.mustache | 2 +- libraries/jersey2/pojo.mustache | 6 +++--- libraries/microprofile/pojo.mustache | 2 +- pojo.mustache | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/jersey2/AbstractOpenApiSchema.mustache b/libraries/jersey2/AbstractOpenApiSchema.mustache index d51d4497283..6eb87a90b9b 100644 --- a/libraries/jersey2/AbstractOpenApiSchema.mustache +++ b/libraries/jersey2/AbstractOpenApiSchema.mustache @@ -95,7 +95,7 @@ public abstract class AbstractOpenApiSchema { * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ - private String toIndentedString(java.lang.Object o) { + private String toIndentedString(Object o) { if (o == null) { return "null"; } diff --git a/libraries/jersey2/pojo.mustache b/libraries/jersey2/pojo.mustache index a74a9d35f4a..67e753a0a2d 100644 --- a/libraries/jersey2/pojo.mustache +++ b/libraries/jersey2/pojo.mustache @@ -236,7 +236,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE * Return true if this {{name}} object is equal to o. */ @Override - public boolean equals(java.lang.Object o) { + public boolean equals(Object o) { {{#useReflectionEqualsHashCode}} return EqualsBuilder.reflectionEquals(this, o, false, null, true); {{/useReflectionEqualsHashCode}} @@ -269,7 +269,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{/supportJava6}} {{#supportJava6}} @Override - public boolean equals(java.lang.Object o) { + public boolean equals(Object o) { if (this == o) { return true; } @@ -311,7 +311,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ - private String toIndentedString(java.lang.Object o) { + private String toIndentedString(Object o) { if (o == null) { return "null"; } diff --git a/libraries/microprofile/pojo.mustache b/libraries/microprofile/pojo.mustache index a2bd33a4766..675813a088d 100644 --- a/libraries/microprofile/pojo.mustache +++ b/libraries/microprofile/pojo.mustache @@ -138,7 +138,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}}{{#serializ * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ - private static String toIndentedString(java.lang.Object o) { + private static String toIndentedString(Object o) { if (o == null) { return "null"; } diff --git a/pojo.mustache b/pojo.mustache index 1754416a396..e6749289b7c 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -230,7 +230,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{^supportJava6}} @Override - public boolean equals(java.lang.Object o) { + public boolean equals(Object o) { {{#useReflectionEqualsHashCode}} return EqualsBuilder.reflectionEquals(this, o, false, null, true); {{/useReflectionEqualsHashCode}} @@ -262,7 +262,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{/supportJava6}} {{#supportJava6}} @Override - public boolean equals(java.lang.Object o) { + public boolean equals(Object o) { if (this == o) { return true; } @@ -301,7 +301,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ - private String toIndentedString(java.lang.Object o) { + private String toIndentedString(Object o) { if (o == null) { return "null"; } From 325189f5fd6b2bf39fe39fa59da284ae46da72cb Mon Sep 17 00:00:00 2001 From: William Cheng Date: Thu, 27 Aug 2020 11:42:48 +0800 Subject: [PATCH 305/370] [Java][jersey2]Support enum discriminator value in child objects (#7267) * support enum discriminator value in child (java jersey2) * update samples * add tests, use public --- libraries/jersey2/pojo.mustache | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/libraries/jersey2/pojo.mustache b/libraries/jersey2/pojo.mustache index 67e753a0a2d..a32b23d6cb7 100644 --- a/libraries/jersey2/pojo.mustache +++ b/libraries/jersey2/pojo.mustache @@ -18,7 +18,9 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{#vars}} {{#isEnum}} {{^isContainer}} + {{^vendorExtensions.x-enum-as-string}} {{>modelInnerEnum}} + {{/vendorExtensions.x-enum-as-string}} {{/isContainer}} {{#isContainer}} {{#mostInnerItems}} @@ -98,7 +100,19 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{#vars}} {{^isReadOnly}} + {{#vendorExtensions.x-enum-as-string}} + public static final Set {{{nameInSnakeCase}}}_VALUES = new HashSet<>(Arrays.asList( + {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}} + )); + + {{/vendorExtensions.x-enum-as-string}} public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-enum-as-string}} + if (!{{{nameInSnakeCase}}}_VALUES.contains({{name}})) { + throw new IllegalArgumentException({{name}} + " is invalid. Possible values for {{name}}: " + String.join(", ", {{{nameInSnakeCase}}}_VALUES)); + } + + {{/vendorExtensions.x-enum-as-string}} {{#vendorExtensions.x-is-jackson-optional-nullable}} this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); {{/vendorExtensions.x-is-jackson-optional-nullable}} @@ -220,6 +234,12 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{^isReadOnly}} public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-enum-as-string}} + if (!{{{nameInSnakeCase}}}_VALUES.contains({{name}})) { + throw new IllegalArgumentException({{name}} + " is invalid. Possible values for {{name}}: " + String.join(", ", {{{nameInSnakeCase}}}_VALUES)); + } + + {{/vendorExtensions.x-enum-as-string}} {{#vendorExtensions.x-is-jackson-optional-nullable}} this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); {{/vendorExtensions.x-is-jackson-optional-nullable}} From 6babb9a0f05cce275395bc23f05650d02c09f9ab Mon Sep 17 00:00:00 2001 From: William Cheng Date: Thu, 27 Aug 2020 23:13:56 +0800 Subject: [PATCH 306/370] [Java] remove deprecated jackson classes (#7304) * [java/resttemplate] Generate valid code if no Authentication implementations present Take the logic used to decide which instances to add to the authentications map and re-use to not import classes or offer non-functional util methods * parameterize formParams fixes #5782 * replace use of ISO8601DateFormat and ISO8601Utils with StdDateFormat fixes #5779 * add constructor to intialise calendar * Revert "[java/resttemplate] Generate valid code if no Authentication implementations present" This reverts commit 6e450907bae1d831a4a8c9b66f6b707424f0a39a. * Revert "parameterize formParams" This reverts commit 7a26ce5dd21ce147ed33728cd0091a29175367a4. * also override single arg parse method to avoid throwing exception * also override single arg parse method to avoid throwing exception * update samples * update samples * fix jersey1 tests * fix jersey2 test * update resteasy dependencies * fix java jersey2 oas3 tests * use java8 in springboot-beanvalidation Co-authored-by: Jon Freedman --- RFC3339DateFormat.mustache | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/RFC3339DateFormat.mustache b/RFC3339DateFormat.mustache index 16fd2a495a7..cacd793e738 100644 --- a/RFC3339DateFormat.mustache +++ b/RFC3339DateFormat.mustache @@ -1,21 +1,44 @@ {{>licenseInfo}} package {{invokerPackage}}; -import com.fasterxml.jackson.databind.util.ISO8601DateFormat; -import com.fasterxml.jackson.databind.util.ISO8601Utils; +import com.fasterxml.jackson.databind.util.StdDateFormat; +import java.text.DateFormat; import java.text.FieldPosition; +import java.text.ParsePosition; import java.util.Date; +import java.util.GregorianCalendar; +import java.util.TimeZone; +public class RFC3339DateFormat extends DateFormat { + private static final long serialVersionUID = 1L; + private static final TimeZone TIMEZONE_Z = TimeZone.getTimeZone("UTC"); -public class RFC3339DateFormat extends ISO8601DateFormat { + private final StdDateFormat fmt = new StdDateFormat() + .withTimeZone(TIMEZONE_Z) + .withColonInTimeZone(true); + + public RFC3339DateFormat() { + this.calendar = new GregorianCalendar(); + } + + @Override + public Date parse(String source) { + return parse(source, new ParsePosition(0)); + } + + @Override + public Date parse(String source, ParsePosition pos) { + return fmt.parse(source, pos); + } - // Same as ISO8601DateFormat but serializing milliseconds. @Override public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { - String value = ISO8601Utils.format(date, true); - toAppendTo.append(value); - return toAppendTo; + return fmt.format(date, toAppendTo, fieldPosition); } + @Override + public Object clone() { + return this; + } } \ No newline at end of file From a1d2065ea6863543fbccde0fd551bfe13386bcee Mon Sep 17 00:00:00 2001 From: Patouche Date: Mon, 31 Aug 2020 15:25:18 +0200 Subject: [PATCH 307/370] [java] Intro openApiNullable property to enable/disable OpenAPI Jackson Nullable library (#6154) * Add option to prevent usage of jackson-nullable (#2901) Add a option for all java client and server to prevent usage of third party library (jackson-databind-nullable) which may be forbidden in some company Add samples for Vertx, Spring MVC, Spring Cloud, Feign and Play Upgrade dependencies for org.openapitools:jackson-databind-nullable * Samples - Remove dependency org.openapitools:jackson-databind-nullable (#2901) * Fix generation of gradle file for vertx (#2901) * Regenerate samples (#2901) * Fix documentation and up to date (#2901) * Fix forgotten regeneration of vertx after dependency integration (#2901) * Regenerate template after rebase (#2901) * Use yaml config files introduce in #6509 to manage samples (#2901) * Regenerate template using the config (#2901) * Fix bad version during testing generated samples (#2901) * Regenerate template after fix bad version (#2901) * Fix merge, allow for set importing on codegen model Co-authored-by: Jim Schubert --- build.gradle.mustache | 4 ++++ libraries/feign/ApiClient.mustache | 4 ++++ libraries/feign/build.gradle.mustache | 4 ++++ libraries/feign/pom.mustache | 4 ++++ libraries/google-api-client/ApiClient.mustache | 4 ++++ libraries/google-api-client/build.gradle.mustache | 4 ++++ libraries/google-api-client/pom.mustache | 4 ++++ libraries/jersey2/JSON.mustache | 4 ++++ libraries/jersey2/build.gradle.mustache | 4 ++++ libraries/jersey2/pom.mustache | 2 ++ libraries/native/ApiClient.mustache | 4 ++++ libraries/rest-assured/JacksonObjectMapper.mustache | 4 ++++ libraries/rest-assured/build.gradle.mustache | 4 ++++ libraries/rest-assured/build.sbt.mustache | 2 ++ libraries/resteasy/JSON.mustache | 4 ++++ libraries/resteasy/build.gradle.mustache | 4 ++++ libraries/resteasy/pom.mustache | 2 ++ libraries/resttemplate/ApiClient.mustache | 6 ++++++ libraries/resttemplate/build.gradle.mustache | 4 ++++ libraries/retrofit2/build.gradle.mustache | 4 ++++ libraries/retrofit2/play24/ApiClient.mustache | 4 ++++ libraries/retrofit2/play25/ApiClient.mustache | 4 ++++ libraries/retrofit2/play26/ApiClient.mustache | 4 ++++ libraries/retrofit2/pom.mustache | 4 ++++ libraries/vertx/ApiClient.mustache | 4 ++++ libraries/vertx/build.gradle.mustache | 9 ++++++++- libraries/vertx/pom.mustache | 2 ++ libraries/webclient/ApiClient.mustache | 4 ++++ libraries/webclient/pom.mustache | 2 ++ 29 files changed, 112 insertions(+), 1 deletion(-) diff --git a/build.gradle.mustache b/build.gradle.mustache index fd3ca0ede28..e5874c4c6ba 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -138,7 +138,9 @@ ext { swagger_annotations_version = "1.5.22" jackson_version = "2.10.3" jackson_databind_version = "2.10.4" + {{#openApiNullable}} jackson_databind_nullable_version = "0.2.1" + {{/openApiNullable}} {{#threetenbp}} jackson_threetenbp_version = "2.9.10" {{/threetenbp}} @@ -156,7 +158,9 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + {{#openApiNullable}} compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} {{#joda}} compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} diff --git a/libraries/feign/ApiClient.mustache b/libraries/feign/ApiClient.mustache index 47e993012f2..48119b3d66b 100644 --- a/libraries/feign/ApiClient.mustache +++ b/libraries/feign/ApiClient.mustache @@ -15,7 +15,9 @@ import org.threeten.bp.*; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; +{{#openApiNullable}} import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} {{#joda}} import com.fasterxml.jackson.datatype.joda.JodaModule; {{/joda}} @@ -181,8 +183,10 @@ public class ApiClient { module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); objectMapper.registerModule(module); {{/threetenbp}} + {{#openApiNullable}} JsonNullableModule jnm = new JsonNullableModule(); objectMapper.registerModule(jnm); + {{/openApiNullable}} return objectMapper; } diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index be03d172b21..42631b3ff42 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -122,7 +122,9 @@ ext { swagger_annotations_version = "1.5.24" jackson_version = "2.10.3" jackson_databind_version = "2.10.3" + {{#openApiNullable}} jackson_databind_nullable_version = "0.2.1" + {{/openApiNullable}} {{#threetenbp}} jackson_threetenbp_version = "2.9.10" {{/threetenbp}} @@ -142,7 +144,9 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + {{#openApiNullable}} compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} {{#joda}} compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index 57bf1040dfe..c0c30c370c6 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -274,11 +274,13 @@ jackson-databind ${jackson-databind-version} + {{#openApiNullable}} org.openapitools jackson-databind-nullable ${jackson-databind-nullable-version} + {{/openApiNullable}} {{#withXml}} @@ -351,7 +353,9 @@ 10.11 3.8.0 2.10.3 + {{#openApiNullable}} 0.2.1 + {{/openApiNullable}} 2.10.3 {{#threetenbp}} 2.9.10 diff --git a/libraries/google-api-client/ApiClient.mustache b/libraries/google-api-client/ApiClient.mustache index 9df560415d0..aa91362ba13 100644 --- a/libraries/google-api-client/ApiClient.mustache +++ b/libraries/google-api-client/ApiClient.mustache @@ -4,7 +4,9 @@ import {{apiPackage}}.*; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; +{{#openApiNullable}} import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} {{#joda}} import com.fasterxml.jackson.datatype.joda.JodaModule; {{/joda}} @@ -54,8 +56,10 @@ public class ApiClient { module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); objectMapper.registerModule(module); {{/threetenbp}} + {{#openApiNullable}} JsonNullableModule jnm = new JsonNullableModule(); objectMapper.registerModule(jnm); + {{/openApiNullable}} return objectMapper; } diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache index d6e5035dc5d..c1b9bd86676 100644 --- a/libraries/google-api-client/build.gradle.mustache +++ b/libraries/google-api-client/build.gradle.mustache @@ -122,7 +122,9 @@ ext { swagger_annotations_version = "1.5.22" jackson_version = "2.10.1" jackson_databind_version = "2.10.4" + {{#openApiNullable}} jackson_databind_nullable_version = "0.2.1" + {{/openApiNullable}} google_api_client_version = "1.23.0" jersey_common_version = "2.25.1" jodatime_version = "2.9.9" @@ -141,7 +143,9 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + {{#openApiNullable}} compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} {{#java8}} compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index 203685fe6b6..69eb025014d 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -267,11 +267,13 @@ jackson-databind ${jackson-version} + {{#openApiNullable}} org.openapitools jackson-databind-nullable ${jackson-databind-nullable-version} + {{/openApiNullable}} {{#withXml}} @@ -328,7 +330,9 @@ 2.25.1 2.10.4 2.10.4 + {{#openApiNullable}} 0.2.1 + {{/openApiNullable}} {{#joda}} 2.9.9 {{/joda}} diff --git a/libraries/jersey2/JSON.mustache b/libraries/jersey2/JSON.mustache index 2820eaa4bb1..0edeb48b264 100644 --- a/libraries/jersey2/JSON.mustache +++ b/libraries/jersey2/JSON.mustache @@ -5,7 +5,9 @@ import org.threeten.bp.*; {{/threetenbp}} import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; +{{#openApiNullable}} import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} {{#java8}} import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; {{/java8}} @@ -54,8 +56,10 @@ public class JSON implements ContextResolver { module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); mapper.registerModule(module); {{/threetenbp}} + {{#openApiNullable}} JsonNullableModule jnm = new JsonNullableModule(); mapper.registerModule(jnm); + {{/openApiNullable}} } /** diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index c8747cca6db..6b0921f30e7 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -121,7 +121,9 @@ ext { swagger_annotations_version = "1.5.22" jackson_version = "2.10.3" jackson_databind_version = "2.10.4" + {{#openApiNullable}} jackson_databind_nullable_version = "0.2.1" + {{/openApiNullable}} {{#supportJava6}} jersey_version = "2.6" commons_io_version=2.5 @@ -152,7 +154,9 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + {{#openApiNullable}} compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} {{#joda}} compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 4b6850ff230..6ba181b60cf 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -296,11 +296,13 @@ jackson-databind ${jackson-databind-version} + {{#openApiNullable}} org.openapitools jackson-databind-nullable ${jackson-databind-nullable-version} + {{/openApiNullable}} {{#withXml}} diff --git a/libraries/native/ApiClient.mustache b/libraries/native/ApiClient.mustache index fb83d919b93..4fff8b5e962 100644 --- a/libraries/native/ApiClient.mustache +++ b/libraries/native/ApiClient.mustache @@ -6,7 +6,9 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{#openApiNullable}} import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} import java.io.InputStream; import java.net.URI; @@ -155,8 +157,10 @@ public class ApiClient { mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); mapper.registerModule(new JavaTimeModule()); + {{#openApiNullable}} JsonNullableModule jnm = new JsonNullableModule(); mapper.registerModule(jnm); + {{/openApiNullable}} URI baseURI = URI.create("{{{basePath}}}"); scheme = baseURI.getScheme(); host = baseURI.getHost(); diff --git a/libraries/rest-assured/JacksonObjectMapper.mustache b/libraries/rest-assured/JacksonObjectMapper.mustache index 9d87ce9ef46..6af705a9d9d 100644 --- a/libraries/rest-assured/JacksonObjectMapper.mustache +++ b/libraries/rest-assured/JacksonObjectMapper.mustache @@ -7,7 +7,9 @@ import org.threeten.bp.*; {{/threetenbp}} import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; +{{#openApiNullable}} import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} {{#java8}} import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; {{/java8}} @@ -52,8 +54,10 @@ public class JacksonObjectMapper extends Jackson2Mapper { module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); mapper.registerModule(module); {{/threetenbp}} + {{#openApiNullable}} JsonNullableModule jnm = new JsonNullableModule(); mapper.registerModule(jnm); + {{/openApiNullable}} return mapper; }; } diff --git a/libraries/rest-assured/build.gradle.mustache b/libraries/rest-assured/build.gradle.mustache index 2e94cb0e0b4..16b485ac436 100644 --- a/libraries/rest-assured/build.gradle.mustache +++ b/libraries/rest-assured/build.gradle.mustache @@ -101,7 +101,9 @@ ext { {{#jackson}} jackson_version = "2.10.3" jackson_databind_version = "2.10.3" + {{#openApiNullable}} jackson_databind_nullable_version = "0.2.1" + {{/openApiNullable}} {{#threetenbp}} jackson_threetenbp_version = "2.10.0" {{/threetenbp}} @@ -128,7 +130,9 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + {{#openApiNullable}} compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} {{#withXml}} compile "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jackson_version" {{/withXml}} diff --git a/libraries/rest-assured/build.sbt.mustache b/libraries/rest-assured/build.sbt.mustache index 7b506a49b23..7fa941f9348 100644 --- a/libraries/rest-assured/build.sbt.mustache +++ b/libraries/rest-assured/build.sbt.mustache @@ -17,7 +17,9 @@ lazy val root = (project in file(".")). "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3", "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3", + {{#openApiNullable}} "org.openapitools" % "jackson-databind-nullable" % "0.2.1", + {{/openApiNullable}} {{#withXml}} "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.10.3", {{/withXml}} diff --git a/libraries/resteasy/JSON.mustache b/libraries/resteasy/JSON.mustache index 22888421d82..338d0455d14 100644 --- a/libraries/resteasy/JSON.mustache +++ b/libraries/resteasy/JSON.mustache @@ -2,7 +2,9 @@ package {{invokerPackage}}; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; +{{#openApiNullable}} import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} {{#java8}} import com.fasterxml.jackson.datatype.jsr310.*; {{/java8}} @@ -27,8 +29,10 @@ public class JSON implements ContextResolver { mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); mapper.setDateFormat(new RFC3339DateFormat()); + {{#openApiNullable}} JsonNullableModule jnm = new JsonNullableModule(); mapper.registerModule(jnm); + {{/openApiNullable}} {{#java8}} mapper.registerModule(new JavaTimeModule()); {{/java8}} diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index 302b1839d51..e2b6913c672 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -121,7 +121,9 @@ ext { swagger_annotations_version = "1.5.22" jackson_version = "2.10.4" jackson_databind_version = "2.10.4" + {{#openApiNullable}} jackson_databind_nullable_version = "0.2.1" + {{/openApiNullable}} threetenbp_version = "2.9.10" resteasy_version = "3.1.3.Final" {{^java8}} @@ -144,7 +146,9 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$threetenbp_version" + {{#openApiNullable}} compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} {{#java8}} compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index 35c915d45fb..579a0f28be1 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -226,11 +226,13 @@ jackson-databind ${jackson-databind-version} + {{#openApiNullable}} org.openapitools jackson-databind-nullable ${jackson-databind-nullable-version} + {{/openApiNullable}} {{#withXml}} diff --git a/libraries/resttemplate/ApiClient.mustache b/libraries/resttemplate/ApiClient.mustache index f4add57c3e1..f1a9541a443 100644 --- a/libraries/resttemplate/ApiClient.mustache +++ b/libraries/resttemplate/ApiClient.mustache @@ -39,7 +39,9 @@ import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter; import com.fasterxml.jackson.databind.ObjectMapper; +{{#openApiNullable}} import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} {{/threetenbp}} import java.io.BufferedReader; @@ -702,7 +704,9 @@ public class ApiClient { messageConverters.add(new MappingJackson2HttpMessageConverter()); XmlMapper xmlMapper = new XmlMapper(); xmlMapper.configure(ToXmlGenerator.Feature.WRITE_XML_DECLARATION, true); + {{#openApiNullable}} xmlMapper.registerModule(new JsonNullableModule()); + {{/openApiNullable}} messageConverters.add(new MappingJackson2XmlHttpMessageConverter(xmlMapper)); RestTemplate restTemplate = new RestTemplate(messageConverters); @@ -716,7 +720,9 @@ public class ApiClient { module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); mapper.registerModule(module); + {{#openApiNullable}} mapper.registerModule(new JsonNullableModule()); + {{/openApiNullable}} } } {{/threetenbp}} diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index c7e1fca9aa6..343e51fc3e5 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -122,7 +122,9 @@ ext { swagger_annotations_version = "1.5.22" jackson_version = "2.10.4" jackson_databind_version = "2.10.4" + {{#openApiNullable}} jackson_databind_nullable_version = "0.2.1" + {{/openApiNullable}} spring_web_version = "5.2.5.RELEASE" jodatime_version = "2.9.9" junit_version = "4.13" @@ -140,7 +142,9 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + {{#openApiNullable}} compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} {{#java8}} compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index c0c622fa034..bf385dad75b 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -124,7 +124,9 @@ ext { {{#usePlayWS}} jackson_version = "2.10.4" jackson_databind_version = "2.10.4" + {{#openApiNullable}} jackson_databind_nullable_version = "0.2.1" + {{/openApiNullable}} {{#play24}} play_version = "2.4.11" {{/play24}} @@ -195,7 +197,9 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + {{#openApiNullable}} compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} compile "com.fasterxml.jackson.datatype:jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}:$jackson_version" {{/usePlayWS}} compile 'javax.annotation:javax.annotation-api:1.3.2' diff --git a/libraries/retrofit2/play24/ApiClient.mustache b/libraries/retrofit2/play24/ApiClient.mustache index 2c1f1f7bbe6..a80cefc31dc 100644 --- a/libraries/retrofit2/play24/ApiClient.mustache +++ b/libraries/retrofit2/play24/ApiClient.mustache @@ -9,7 +9,9 @@ import retrofit2.Retrofit; import retrofit2.converter.scalars.ScalarsConverterFactory; import retrofit2.converter.jackson.JacksonConverterFactory; import com.fasterxml.jackson.databind.ObjectMapper; +{{#openApiNullable}} import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} import play.libs.Json; import play.libs.ws.WSClient; @@ -72,8 +74,10 @@ public class ApiClient { } ObjectMapper mapper = Json.mapper(); + {{#openApiNullable}} JsonNullableModule jnm = new JsonNullableModule(); mapper.registerModule(jnm); + {{/openApiNullable}} return new Retrofit.Builder() .baseUrl(basePath) diff --git a/libraries/retrofit2/play25/ApiClient.mustache b/libraries/retrofit2/play25/ApiClient.mustache index 90f439091cc..dcb9e2c58e0 100644 --- a/libraries/retrofit2/play25/ApiClient.mustache +++ b/libraries/retrofit2/play25/ApiClient.mustache @@ -9,7 +9,9 @@ import retrofit2.Retrofit; import retrofit2.converter.scalars.ScalarsConverterFactory; import retrofit2.converter.jackson.JacksonConverterFactory; import com.fasterxml.jackson.databind.ObjectMapper; +{{#openApiNullable}} import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} import play.libs.Json; import play.libs.ws.WSClient; @@ -71,8 +73,10 @@ public class ApiClient { } ObjectMapper mapper = Json.mapper(); + {{#openApiNullable}} JsonNullableModule jnm = new JsonNullableModule(); mapper.registerModule(jnm); + {{/openApiNullable}} return new Retrofit.Builder() .baseUrl(basePath) diff --git a/libraries/retrofit2/play26/ApiClient.mustache b/libraries/retrofit2/play26/ApiClient.mustache index 1346ae85694..55db0729449 100644 --- a/libraries/retrofit2/play26/ApiClient.mustache +++ b/libraries/retrofit2/play26/ApiClient.mustache @@ -13,7 +13,9 @@ import retrofit2.Converter; import retrofit2.Retrofit; import retrofit2.converter.scalars.ScalarsConverterFactory; import retrofit2.converter.jackson.JacksonConverterFactory; +{{#openApiNullable}} import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} import play.libs.Json; import play.libs.ws.WSClient; @@ -91,8 +93,10 @@ public class ApiClient { } if (defaultMapper == null) { defaultMapper = Json.mapper(); + {{#openApiNullable}} JsonNullableModule jnm = new JsonNullableModule(); defaultMapper.registerModule(jnm); + {{/openApiNullable}} } return new Retrofit.Builder() diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index c8591422ae8..327734d7944 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -342,11 +342,13 @@ jackson-databind ${jackson-version} + {{#openApiNullable}} org.openapitools jackson-databind-nullable ${jackson-databind-nullable-version} + {{/openApiNullable}} com.fasterxml.jackson.datatype jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}} @@ -428,7 +430,9 @@ {{#play26}} 2.6.7 {{/play26}} + {{#openApiNullable}} 0.2.1 + {{/openApiNullable}} {{/usePlayWS}} 2.5.0 {{#useRxJava}} diff --git a/libraries/vertx/ApiClient.mustache b/libraries/vertx/ApiClient.mustache index c7d0056fef8..1b8e32b6399 100644 --- a/libraries/vertx/ApiClient.mustache +++ b/libraries/vertx/ApiClient.mustache @@ -15,7 +15,9 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{#openApiNullable}} import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} import io.vertx.core.*; import io.vertx.core.buffer.Buffer; import io.vertx.core.file.AsyncFile; @@ -81,8 +83,10 @@ public class ApiClient { this.objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); this.objectMapper.registerModule(new JavaTimeModule()); this.objectMapper.setDateFormat(dateFormat); + {{#openApiNullable}} JsonNullableModule jnm = new JsonNullableModule(); this.objectMapper.registerModule(jnm); + {{/openApiNullable}} // Setup authentications (key: authentication name, value: authentication). this.authentications = new HashMap<>();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} diff --git a/libraries/vertx/build.gradle.mustache b/libraries/vertx/build.gradle.mustache index 742f19fd1cf..0c2c9363e3c 100644 --- a/libraries/vertx/build.gradle.mustache +++ b/libraries/vertx/build.gradle.mustache @@ -32,7 +32,12 @@ ext { jackson_databind_version = "2.10.4" vertx_version = "3.4.2" junit_version = "4.13" + {{#openApiNullable}} jackson_databind_nullable_version = "0.2.1" + {{/openApiNullable}} + {{#threetenbp}} + jackson_threeten_version = "2.9.10" + {{/threetenbp}} } dependencies { @@ -50,9 +55,11 @@ dependencies { compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_version" + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:jackson_threeten_version" {{/threetenbp}} + {{#openApiNullable}} compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} compile 'javax.annotation:javax.annotation-api:1.3.2' testCompile "junit:junit:$junit_version" testCompile "io.vertx:vertx-unit:$vertx_version" diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache index 310db959c48..49a4f8a0ad7 100644 --- a/libraries/vertx/pom.mustache +++ b/libraries/vertx/pom.mustache @@ -257,11 +257,13 @@ jackson-databind ${jackson-databind} + {{#openApiNullable}} org.openapitools jackson-databind-nullable ${jackson-databind-nullable-version} + {{/openApiNullable}} {{#joda}} com.fasterxml.jackson.datatype diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index 712ac17c637..7ee5fb8cdab 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -3,7 +3,9 @@ package {{invokerPackage}}; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{#openApiNullable}} import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.core.ParameterizedTypeReference; @@ -98,8 +100,10 @@ public class ApiClient { mapper.setDateFormat(dateFormat); mapper.registerModule(new JavaTimeModule()); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + {{#openApiNullable}} JsonNullableModule jnm = new JsonNullableModule(); mapper.registerModule(jnm); + {{/openApiNullable}} this.webClient = buildWebClient(mapper); this.init(); diff --git a/libraries/webclient/pom.mustache b/libraries/webclient/pom.mustache index b3bcdc1ecc4..e07c355e775 100644 --- a/libraries/webclient/pom.mustache +++ b/libraries/webclient/pom.mustache @@ -105,11 +105,13 @@ jackson-databind ${jackson-databind-version} + {{#openApiNullable}} org.openapitools jackson-databind-nullable ${jackson-databind-nullable-version} + {{/openApiNullable}} {{#java8}} From 91d23337f6a559975db68f5f09baa937aa4d7610 Mon Sep 17 00:00:00 2001 From: Oleh Kurpiak Date: Mon, 31 Aug 2020 17:31:28 +0300 Subject: [PATCH 308/370] [Java][Client] Use java8 OffsetDateTime for clients (#7190) * use java8 OffsetDateTime for clients * use java8 OffsetDateTime for clients * fix javadoc * add javadoc to JavaTimeFormatter.mustache * add javadoc to JavaTimeFormatter.mustache * add javadoc to JavaTimeFormatter.mustache --- ApiClient.mustache | 7 ++- JavaTimeFormatter.mustache | 53 +++++++++++++++++++++++ libraries/jersey2/ApiClient.mustache | 9 +++- libraries/resteasy/ApiClient.mustache | 9 +++- libraries/resttemplate/ApiClient.mustache | 9 +++- libraries/vertx/ApiClient.mustache | 9 +++- libraries/webclient/ApiClient.mustache | 9 +++- 7 files changed, 93 insertions(+), 12 deletions(-) create mode 100644 JavaTimeFormatter.mustache diff --git a/ApiClient.mustache b/ApiClient.mustache index b2e3b198651..262110a2992 100644 --- a/ApiClient.mustache +++ b/ApiClient.mustache @@ -12,6 +12,7 @@ import com.fasterxml.jackson.datatype.joda.JodaModule; {{/joda}} {{#java8}} import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import java.time.OffsetDateTime; {{/java8}} {{#threetenbp}} import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; @@ -67,7 +68,7 @@ import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} {{>generatedAnnotation}} -public class ApiClient { +public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { private Map defaultHeaderMap = new HashMap(); private Map defaultCookieMap = new HashMap(); private String basePath = "{{{basePath}}}"; @@ -499,7 +500,9 @@ public class ApiClient { return ""; } else if (param instanceof Date) { return formatDate((Date) param); - } else if (param instanceof Collection) { + } {{#java8}}else if (param instanceof OffsetDateTime) { + return formatOffsetDateTime((OffsetDateTime) param); + } {{/java8}}else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); for(Object o : (Collection)param) { if(b.length() > 0) { diff --git a/JavaTimeFormatter.mustache b/JavaTimeFormatter.mustache new file mode 100644 index 00000000000..f3fb34e559c --- /dev/null +++ b/JavaTimeFormatter.mustache @@ -0,0 +1,53 @@ +{{>licenseInfo}} +package {{invokerPackage}}; + +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; + +/** + * Class that add parsing/formatting support for Java 8+ {@code OffsetDateTime} class. + * It's generated for java clients when {@code AbstractJavaCodegen#dateLibrary} specified as {@code java8}. + */ +{{>generatedAnnotation}} +public class JavaTimeFormatter { + + private DateTimeFormatter offsetDateTimeFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME; + + /** + * Get the date format used to parse/format {@code OffsetDateTime} parameters. + * @return DateTimeFormatter + */ + public DateTimeFormatter getOffsetDateTimeFormatter() { + return offsetDateTimeFormatter; + } + + /** + * Set the date format used to parse/format {@code OffsetDateTime} parameters. + * @param offsetDateTimeFormatter {@code DateTimeFormatter} + */ + public void setOffsetDateTimeFormatter(DateTimeFormatter offsetDateTimeFormatter) { + this.offsetDateTimeFormatter = offsetDateTimeFormatter; + } + + /** + * Parse the given string into {@code OffsetDateTime} object. + * @param str String + * @return {@code OffsetDateTime} + */ + public OffsetDateTime parseOffsetDateTime(String str) { + try { + return OffsetDateTime.parse(str, offsetDateTimeFormatter); + } catch (DateTimeParseException e) { + throw new RuntimeException(e); + } + } + /** + * Format the given {@code OffsetDateTime} object into string. + * @param offsetDateTime {@code OffsetDateTime} + * @return {@code OffsetDateTime} in string format + */ + public String formatOffsetDateTime(OffsetDateTime offsetDateTime) { + return offsetDateTimeFormatter.format(offsetDateTime); + } +} diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 48c9d986bb5..4ccf4e9cb09 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -55,6 +55,9 @@ import java.util.List; import java.util.Arrays; import java.util.ArrayList; import java.util.Date; +{{#java8}} +import java.time.OffsetDateTime; +{{/java8}} import java.net.URLEncoder; @@ -77,7 +80,7 @@ import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} {{>generatedAnnotation}} -public class ApiClient { +public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { protected Map defaultHeaderMap = new HashMap(); protected Map defaultCookieMap = new HashMap(); protected String basePath = "{{{basePath}}}"; @@ -695,7 +698,9 @@ public class ApiClient { return ""; } else if (param instanceof Date) { return formatDate((Date) param); - } else if (param instanceof Collection) { + } {{#java8}}else if (param instanceof OffsetDateTime) { + return formatOffsetDateTime((OffsetDateTime) param); + } {{/java8}}else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); for(Object o : (Collection)param) { if(b.length() > 0) { diff --git a/libraries/resteasy/ApiClient.mustache b/libraries/resteasy/ApiClient.mustache index 16ec4c4508f..8f3486eb5db 100644 --- a/libraries/resteasy/ApiClient.mustache +++ b/libraries/resteasy/ApiClient.mustache @@ -22,6 +22,9 @@ import java.util.Map.Entry; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; +{{#java8}} +import java.time.OffsetDateTime; +{{/java8}} import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; @@ -48,7 +51,7 @@ import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} {{>generatedAnnotation}} -public class ApiClient { +public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { private Map defaultHeaderMap = new HashMap(); private Map defaultCookieMap = new HashMap(); private String basePath = "{{{basePath}}}"; @@ -333,7 +336,9 @@ public class ApiClient { return ""; } else if (param instanceof Date) { return formatDate((Date) param); - } else if (param instanceof Collection) { + } {{#java8}}else if (param instanceof OffsetDateTime) { + return formatOffsetDateTime((OffsetDateTime) param); + } {{/java8}}else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); for(Object o : (Collection)param) { if(b.length() > 0) { diff --git a/libraries/resttemplate/ApiClient.mustache b/libraries/resttemplate/ApiClient.mustache index f1a9541a443..03d01134193 100644 --- a/libraries/resttemplate/ApiClient.mustache +++ b/libraries/resttemplate/ApiClient.mustache @@ -66,6 +66,9 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.TimeZone; +{{#java8}} +import java.time.OffsetDateTime; +{{/java8}} import {{invokerPackage}}.auth.Authentication; {{#hasHttpBasicMethods}} @@ -83,7 +86,7 @@ import {{invokerPackage}}.auth.OAuth; {{>generatedAnnotation}} @Component("{{invokerPackage}}.ApiClient") -public class ApiClient { +public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { public enum CollectionFormat { CSV(","), TSV("\t"), SSV(" "), PIPES("|"), MULTI(null); @@ -404,7 +407,9 @@ public class ApiClient { return ""; } else if (param instanceof Date) { return formatDate( (Date) param); - } else if (param instanceof Collection) { + } {{#java8}}else if (param instanceof OffsetDateTime) { + return formatOffsetDateTime((OffsetDateTime) param); + } {{/java8}}else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); for(Object o : (Collection) param) { if(b.length() > 0) { diff --git a/libraries/vertx/ApiClient.mustache b/libraries/vertx/ApiClient.mustache index 1b8e32b6399..3c17645d6c8 100644 --- a/libraries/vertx/ApiClient.mustache +++ b/libraries/vertx/ApiClient.mustache @@ -33,6 +33,9 @@ import io.vertx.ext.web.client.HttpResponse; import io.vertx.ext.web.client.WebClient; import io.vertx.ext.web.client.WebClientOptions; +{{#java8}} +import java.time.OffsetDateTime; +{{/java8}} import java.text.DateFormat; import java.util.*; import java.util.function.Consumer; @@ -42,7 +45,7 @@ import java.util.regex.Pattern; import static java.util.stream.Collectors.toMap; {{>generatedAnnotation}} -public class ApiClient { +public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { private static final Pattern CONTENT_DISPOSITION_PATTERN = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?"); private static final OpenOptions FILE_DOWNLOAD_OPTIONS = new OpenOptions().setCreate(true).setTruncateExisting(true); @@ -295,7 +298,9 @@ public class ApiClient { return ""; } else if (param instanceof Date) { return formatDate((Date) param); - } else if (param instanceof Collection) { + } {{#java8}}else if (param instanceof OffsetDateTime) { + return formatOffsetDateTime((OffsetDateTime) param); + } {{/java8}}else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); for (Object o : (Collection) param) { if (b.length() > 0) { diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index 7ee5fb8cdab..ff952386f81 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -59,6 +59,9 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.TimeZone; +{{#java8}} +import java.time.OffsetDateTime; +{{/java8}} import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; @@ -69,7 +72,7 @@ import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} {{>generatedAnnotation}} -public class ApiClient { +public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { public enum CollectionFormat { CSV(","), TSV("\t"), SSV(" "), PIPES("|"), MULTI(null); @@ -354,7 +357,9 @@ public class ApiClient { return ""; } else if (param instanceof Date) { return formatDate( (Date) param); - } else if (param instanceof Collection) { + } {{#java8}}else if (param instanceof OffsetDateTime) { + return formatOffsetDateTime((OffsetDateTime) param); + } {{/java8}}else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); for(Object o : (Collection) param) { if(b.length() > 0) { From 9bf54ff3f5d890dd7b577be1df04bc0ce24243fb Mon Sep 17 00:00:00 2001 From: Robin Eggenkamp Date: Fri, 4 Sep 2020 15:35:13 +0200 Subject: [PATCH 309/370] Remove duplicate jackson-datatype-jsr310 dependency (#7338) --- libraries/resteasy/pom.mustache | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index 579a0f28be1..738f438da60 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -243,13 +243,6 @@ {{/withXml}} - {{#java8}} - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - ${jackson-version} - - {{/java8}} {{^java8}} com.fasterxml.jackson.datatype From 34b5724eb2a190c8b8c4afe7988c24c28f3d8d6a Mon Sep 17 00:00:00 2001 From: dtiller <3858971+dtiller@users.noreply.github.com> Date: Sat, 19 Sep 2020 00:07:35 -0400 Subject: [PATCH 310/370] [TYPO] [WEBCLIENT] Issue 7425: Fixed comments that referred to RestTemplate. (#7445) * Issue 7425: Fixed comments that referred to RestTemplate. * Ran genreate-samples.sh * Re-ran generate-samples.sh against all configs. * update samples Co-authored-by: William Cheng --- libraries/webclient/ApiClient.mustache | 4 ++-- libraries/webclient/pom.mustache | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index ff952386f81..98f4bfb2004 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -144,8 +144,8 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { } /** - * Build the RestTemplate used to make HTTP requests. - * @return RestTemplate + * Build the WebClient used to make HTTP requests. + * @return WebClient */ public static WebClient buildWebClient(ObjectMapper mapper) { ExchangeStrategies strategies = ExchangeStrategies diff --git a/libraries/webclient/pom.mustache b/libraries/webclient/pom.mustache index e07c355e775..2b8da13b027 100644 --- a/libraries/webclient/pom.mustache +++ b/libraries/webclient/pom.mustache @@ -86,7 +86,7 @@ ${reactor-version} - + org.springframework spring-webflux From 03863c5951c0ac5715d5c9b84a2c2171a877799b Mon Sep 17 00:00:00 2001 From: Philipp Paris Date: Mon, 21 Sep 2020 03:18:07 +0200 Subject: [PATCH 311/370] [java] jaxrs (all) add usetags option (#6130) * Adds "useTags" option to all jaxrs code generators (AbstractJAXRSServerCodegen): - jaxrs-jersey - jaxrs-spec - jaxrs-cxf-cdi - jaxrs-resteasy - jaxrs-cxf - jaxrs-cxf-extended - java-msf4j - jaxrs-resteasy-eap * jaxrs-spec - Changed handling of root paths: e.g "/:", "/{id}:" to simplify code and create a more consistent behaviour -- old: use tag for classname -- new: use tag only if useTags is enabled, use "DefaultApi" if not * @path class level annotation - for all generators above and the microprofile generator (uses same jaxrs postprocessing) - extended the "commonPath" to contain more than only the root path if possible - e.g. "/group1/subgroup1/op1" -> "/group1/subgroup1" is moved to class level annotation --- README.mustache | 2 +- api_doc.mustache | 2 +- libraries/microprofile/api.mustache | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.mustache b/README.mustache index 85fd77af642..5f2e5943a49 100644 --- a/README.mustache +++ b/README.mustache @@ -150,7 +150,7 @@ All URIs are relative to *{{basePath}}* Class | Method | HTTP request | Description ------------ | ------------- | ------------- | ------------- -{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{commonPath}}{{path}} | {{#summary}}{{summary}}{{/summary}} {{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} ## Documentation for Models diff --git a/api_doc.mustache b/api_doc.mustache index edc837f486e..63e7a490012 100644 --- a/api_doc.mustache +++ b/api_doc.mustache @@ -6,7 +6,7 @@ All URIs are relative to *{{basePath}}* Method | HTTP request | Description ------------- | ------------- | ------------- -{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{commonPath}}{{path}} | {{#summary}}{{summary}}{{/summary}} {{/operation}}{{/operations}} {{#operations}} diff --git a/libraries/microprofile/api.mustache b/libraries/microprofile/api.mustache index 1830838da8e..d481f96ea0b 100644 --- a/libraries/microprofile/api.mustache +++ b/libraries/microprofile/api.mustache @@ -31,7 +31,7 @@ import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; @RegisterRestClient @RegisterProvider(ApiExceptionMapper.class) -@Path("{{^useAnnotatedBasePath}}/{{/useAnnotatedBasePath}}{{#useAnnotatedBasePath}}{{contextPath}}{{/useAnnotatedBasePath}}") +@Path("{{#useAnnotatedBasePath}}{{contextPath}}{{/useAnnotatedBasePath}}{{commonPath}}") public interface {{classname}} { {{#operations}} {{#operation}} From b4e7ce44468739cf40e5514c43103a589cc1d536 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 30 Sep 2020 16:46:24 +0800 Subject: [PATCH 312/370] update microprofile default license info file (#7550) --- libraries/microprofile/licenseInfo.mustache | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/libraries/microprofile/licenseInfo.mustache b/libraries/microprofile/licenseInfo.mustache index d148ab0a419..9866f297a4d 100644 --- a/libraries/microprofile/licenseInfo.mustache +++ b/libraries/microprofile/licenseInfo.mustache @@ -8,16 +8,4 @@ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * https://openapi-generator.tech * Do not edit the class manually. - * - * 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 - * - * https://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. */ From 5ffe7cdc2607c8ce05b70bd3196f8227ac5d7d6f Mon Sep 17 00:00:00 2001 From: William Cheng Date: Thu, 8 Oct 2020 23:00:36 +0800 Subject: [PATCH 313/370] replace tab with spaces (#7625) --- libraries/jersey2/ApiResponse.mustache | 2 +- libraries/jersey2/apiException.mustache | 6 +++--- libraries/jersey2/oneof_model.mustache | 4 ++-- libraries/microprofile/api_test.mustache | 2 +- libraries/microprofile/enumClass.mustache | 8 ++++---- libraries/native/ApiResponse.mustache | 2 +- libraries/okhttp-gson/ApiResponse.mustache | 2 +- libraries/okhttp-gson/apiException.mustache | 6 +++--- libraries/rest-assured/build.sbt.mustache | 2 +- libraries/resteasy/build.sbt.mustache | 2 +- libraries/resttemplate/ApiClient.mustache | 2 +- libraries/retrofit2/ApiClient.mustache | 2 +- 12 files changed, 20 insertions(+), 20 deletions(-) diff --git a/libraries/jersey2/ApiResponse.mustache b/libraries/jersey2/ApiResponse.mustache index 5dae9dc1fdf..86c889b0f67 100644 --- a/libraries/jersey2/ApiResponse.mustache +++ b/libraries/jersey2/ApiResponse.mustache @@ -5,7 +5,7 @@ package {{invokerPackage}}; import java.util.List; import java.util.Map; {{#caseInsensitiveResponseHeaders}} -import java.util.Map.Entry; +import java.util.Map.Entry; import java.util.TreeMap; {{/caseInsensitiveResponseHeaders}} diff --git a/libraries/jersey2/apiException.mustache b/libraries/jersey2/apiException.mustache index f0079c7bbec..74a419aacf1 100644 --- a/libraries/jersey2/apiException.mustache +++ b/libraries/jersey2/apiException.mustache @@ -5,7 +5,7 @@ package {{invokerPackage}}; import java.util.Map; import java.util.List; {{#caseInsensitiveResponseHeaders}} -import java.util.Map.Entry; +import java.util.Map.Entry; import java.util.TreeMap; {{/caseInsensitiveResponseHeaders}} @@ -34,7 +34,7 @@ public class ApiException extends{{#useRuntimeException}} RuntimeException {{/us {{#caseInsensitiveResponseHeaders}} Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER); for(Entry> entry : responseHeaders.entrySet()){ - headers.put(entry.getKey().toLowerCase(), entry.getValue()); + headers.put(entry.getKey().toLowerCase(), entry.getValue()); } {{/caseInsensitiveResponseHeaders}} this.responseHeaders = {{#caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}; @@ -63,7 +63,7 @@ public class ApiException extends{{#useRuntimeException}} RuntimeException {{/us {{#caseInsensitiveResponseHeaders}} Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER); for(Entry> entry : responseHeaders.entrySet()){ - headers.put(entry.getKey().toLowerCase(), entry.getValue()); + headers.put(entry.getKey().toLowerCase(), entry.getValue()); } {{/caseInsensitiveResponseHeaders}} this.responseHeaders = {{#caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}; diff --git a/libraries/jersey2/oneof_model.mustache b/libraries/jersey2/oneof_model.mustache index 64da76c849d..ca2dc49a2e0 100644 --- a/libraries/jersey2/oneof_model.mustache +++ b/libraries/jersey2/oneof_model.mustache @@ -63,12 +63,12 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im Map result2 = tree.traverse(jp.getCodec()).readValueAs(new TypeReference>() {}); String discriminatorValue = (String)result2.get("{{{propertyBaseName}}}"); switch (discriminatorValue) { - {{#mappedModels}} + {{#mappedModels}} case "{{{mappingName}}}": deserialized = tree.traverse(jp.getCodec()).readValueAs({{{modelName}}}.class); new{{classname}}.setActualInstance(deserialized); return new{{classname}}; - {{/mappedModels}} + {{/mappedModels}} default: log.log(Level.WARNING, String.format("Failed to lookup discriminator value `%s` for {{classname}}. Possible values:{{#mappedModels}} {{{mappingName}}}{{/mappedModels}}", discriminatorValue)); } diff --git a/libraries/microprofile/api_test.mustache b/libraries/microprofile/api_test.mustache index 8177ac16dad..d2cb03f2798 100644 --- a/libraries/microprofile/api_test.mustache +++ b/libraries/microprofile/api_test.mustache @@ -62,7 +62,7 @@ public class {{classname}}Test { */ @Test public void {{operationId}}Test() { - // TODO: test validations + // TODO: test validations {{#allParams}} {{^isFile}}{{{dataType}}} {{paramName}} = null;{{/isFile}}{{#isFile}}org.apache.cxf.jaxrs.ext.multipart.Attachment {{paramName}} = null;{{/isFile}} {{/allParams}} diff --git a/libraries/microprofile/enumClass.mustache b/libraries/microprofile/enumClass.mustache index ee3c5901fe4..67e776cbf59 100644 --- a/libraries/microprofile/enumClass.mustache +++ b/libraries/microprofile/enumClass.mustache @@ -11,10 +11,10 @@ {{#allowableValues}} {{#withXml}} {{#enumVars}}@XmlEnumValue({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) {{name}}({{dataType}}.valueOf({{{value}}})){{^-last}}, {{/-last}}{{#-last}};{{/-last}}{{/enumVars}} - {{/withXml}} - {{^withXml}} - {{#enumVars}}{{name}}({{dataType}}.valueOf({{{value}}})){{^-last}}, {{/-last}}{{#-last}};{{/-last}}{{/enumVars}} - {{/withXml}} + {{/withXml}} + {{^withXml}} + {{#enumVars}}{{name}}({{dataType}}.valueOf({{{value}}})){{^-last}}, {{/-last}}{{#-last}};{{/-last}}{{/enumVars}} + {{/withXml}} {{/allowableValues}} diff --git a/libraries/native/ApiResponse.mustache b/libraries/native/ApiResponse.mustache index 1f3f3a31981..1e277319a93 100644 --- a/libraries/native/ApiResponse.mustache +++ b/libraries/native/ApiResponse.mustache @@ -5,7 +5,7 @@ package {{invokerPackage}}; import java.util.List; import java.util.Map; {{#caseInsensitiveResponseHeaders}} -import java.util.Map.Entry; +import java.util.Map.Entry; import java.util.TreeMap; {{/caseInsensitiveResponseHeaders}} diff --git a/libraries/okhttp-gson/ApiResponse.mustache b/libraries/okhttp-gson/ApiResponse.mustache index 1f3f3a31981..1e277319a93 100644 --- a/libraries/okhttp-gson/ApiResponse.mustache +++ b/libraries/okhttp-gson/ApiResponse.mustache @@ -5,7 +5,7 @@ package {{invokerPackage}}; import java.util.List; import java.util.Map; {{#caseInsensitiveResponseHeaders}} -import java.util.Map.Entry; +import java.util.Map.Entry; import java.util.TreeMap; {{/caseInsensitiveResponseHeaders}} diff --git a/libraries/okhttp-gson/apiException.mustache b/libraries/okhttp-gson/apiException.mustache index e8952456591..d28b1bd9630 100644 --- a/libraries/okhttp-gson/apiException.mustache +++ b/libraries/okhttp-gson/apiException.mustache @@ -5,7 +5,7 @@ package {{invokerPackage}}; import java.util.Map; import java.util.List; {{#caseInsensitiveResponseHeaders}} -import java.util.Map.Entry; +import java.util.Map.Entry; import java.util.TreeMap; {{/caseInsensitiveResponseHeaders}} @@ -31,7 +31,7 @@ public class ApiException extends{{#useRuntimeException}} RuntimeException {{/us {{#caseInsensitiveResponseHeaders}} Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER); for(Entry> entry : responseHeaders.entrySet()){ - headers.put(entry.getKey().toLowerCase(), entry.getValue()); + headers.put(entry.getKey().toLowerCase(), entry.getValue()); } {{/caseInsensitiveResponseHeaders}} this.responseHeaders = {{#caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}; @@ -60,7 +60,7 @@ public class ApiException extends{{#useRuntimeException}} RuntimeException {{/us {{#caseInsensitiveResponseHeaders}} Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER); for(Entry> entry : responseHeaders.entrySet()){ - headers.put(entry.getKey().toLowerCase(), entry.getValue()); + headers.put(entry.getKey().toLowerCase(), entry.getValue()); } {{/caseInsensitiveResponseHeaders}} this.responseHeaders = {{#caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}; diff --git a/libraries/rest-assured/build.sbt.mustache b/libraries/rest-assured/build.sbt.mustache index 7fa941f9348..06f439c70ab 100644 --- a/libraries/rest-assured/build.sbt.mustache +++ b/libraries/rest-assured/build.sbt.mustache @@ -50,7 +50,7 @@ lazy val root = (project in file(".")). {{#performBeanValidation}} "org.hibernate" % "hibernate-validator" % "6.0.19.Final" % "compile", {{/performBeanValidation}} - "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", + "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) diff --git a/libraries/resteasy/build.sbt.mustache b/libraries/resteasy/build.sbt.mustache index 4c079bcffd8..721e4620057 100644 --- a/libraries/resteasy/build.sbt.mustache +++ b/libraries/resteasy/build.sbt.mustache @@ -29,7 +29,7 @@ lazy val root = (project in file(".")). "org.apache.commons" % "commons-lang3" % "3.5" % "compile", "commons-io" % "commons-io" % "2.5" % "compile", {{/supportJava6}} - "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", + "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) diff --git a/libraries/resttemplate/ApiClient.mustache b/libraries/resttemplate/ApiClient.mustache index 03d01134193..a6687d778cd 100644 --- a/libraries/resttemplate/ApiClient.mustache +++ b/libraries/resttemplate/ApiClient.mustache @@ -623,7 +623,7 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { builder.queryParams(queryParams); } - URI uri; + URI uri; try { uri = new URI(builder.build().toUriString()); } catch(URISyntaxException ex) { diff --git a/libraries/retrofit2/ApiClient.mustache b/libraries/retrofit2/ApiClient.mustache index 6c16a948610..645727db3c0 100644 --- a/libraries/retrofit2/ApiClient.mustache +++ b/libraries/retrofit2/ApiClient.mustache @@ -366,7 +366,7 @@ public class ApiClient { } apiAuthorizations.put(authName, authorization); if(okBuilder == null){ - throw new RuntimeException("The ApiClient was created with a built OkHttpClient so it's not possible to add an authorization interceptor to it"); + throw new RuntimeException("The ApiClient was created with a built OkHttpClient so it's not possible to add an authorization interceptor to it"); } okBuilder.addInterceptor(authorization); From fd717f162acfcf1eb1d94ab5e27d5ac315d16690 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 9 Oct 2020 17:11:23 +0800 Subject: [PATCH 314/370] java jersey2: remove trailing whitespaces (#7632) --- libraries/jersey2/JSON.mustache | 2 +- libraries/jersey2/auth/HttpSignatureAuth.mustache | 4 ++-- libraries/jersey2/pom.mustache | 2 +- travis.mustache | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/jersey2/JSON.mustache b/libraries/jersey2/JSON.mustache index 0edeb48b264..3297c77e49b 100644 --- a/libraries/jersey2/JSON.mustache +++ b/libraries/jersey2/JSON.mustache @@ -205,7 +205,7 @@ public class JSON implements ContextResolver { return false; } visitedClasses.add(modelClass); - + // Traverse the oneOf/anyOf composed schemas. Map descendants = modelDescendants.get(modelClass); if (descendants != null) { diff --git a/libraries/jersey2/auth/HttpSignatureAuth.mustache b/libraries/jersey2/auth/HttpSignatureAuth.mustache index b9fff30675f..ac0a77db8ac 100644 --- a/libraries/jersey2/auth/HttpSignatureAuth.mustache +++ b/libraries/jersey2/auth/HttpSignatureAuth.mustache @@ -1,5 +1,5 @@ {{>licenseInfo}} - + package {{invokerPackage}}.auth; import {{invokerPackage}}.Pair; @@ -51,7 +51,7 @@ public class HttpSignatureAuth implements Authentication { // The digest algorithm which is used to calculate a cryptographic digest of the HTTP request body. private String digestAlgorithm; - // The maximum validity duration of the HTTP signature. + // The maximum validity duration of the HTTP signature. private Long maxSignatureValidity; /** diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 6ba181b60cf..b305b75c80b 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -255,7 +255,7 @@ jsr305 3.0.2 - + org.glassfish.jersey.core diff --git a/travis.mustache b/travis.mustache index e3bdf2af1be..1b6741c083c 100644 --- a/travis.mustache +++ b/travis.mustache @@ -18,5 +18,5 @@ script: #- mvn test # test using gradle - gradle test - # test using sbt + # test using sbt # - sbt test From 2decfec4df0362bca896a1e3b4be7c36d93a6466 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Mon, 12 Oct 2020 09:12:37 -0700 Subject: [PATCH 315/370] Unifies naming for isMap in Schema class properties (#7640) * Updates isMapModel + isMapContainer -> isMap * Removes git conflict characters --- jackson_annotations.mustache | 2 +- libraries/jersey2/pojo.mustache | 4 ++-- libraries/microprofile/pojo.mustache | 14 +++++++------- libraries/okhttp-gson/api.mustache | 2 +- pojo.mustache | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/jackson_annotations.mustache b/jackson_annotations.mustache index ac01b293cc1..3819d3d2dd2 100644 --- a/jackson_annotations.mustache +++ b/jackson_annotations.mustache @@ -5,7 +5,7 @@ * Else use custom behaviour, IOW use whatever is defined on the object mapper }} @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) - @JsonInclude({{#isMapContainer}}{{#items.isNullable}}content = JsonInclude.Include.ALWAYS, {{/items.isNullable}}{{/isMapContainer}}value = JsonInclude.Include.{{#required}}ALWAYS{{/required}}{{^required}}USE_DEFAULTS{{/required}}) + @JsonInclude({{#isMap}}{{#items.isNullable}}content = JsonInclude.Include.ALWAYS, {{/items.isNullable}}{{/isMap}}value = JsonInclude.Include.{{#required}}ALWAYS{{/required}}{{^required}}USE_DEFAULTS{{/required}}) {{#withXml}} {{^isContainer}} @JacksonXmlProperty({{#isXmlAttribute}}isAttribute = true, {{/isXmlAttribute}}{{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}localName = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") diff --git a/libraries/jersey2/pojo.mustache b/libraries/jersey2/pojo.mustache index a32b23d6cb7..6ac2083704a 100644 --- a/libraries/jersey2/pojo.mustache +++ b/libraries/jersey2/pojo.mustache @@ -146,7 +146,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{/vendorExtensions.x-is-jackson-optional-nullable}} } {{/isListContainer}} - {{#isMapContainer}} + {{#isMap}} public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { {{#vendorExtensions.x-is-jackson-optional-nullable}} @@ -170,7 +170,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE return this; {{/vendorExtensions.x-is-jackson-optional-nullable}} } - {{/isMapContainer}} + {{/isMap}} {{/isReadOnly}} /** diff --git a/libraries/microprofile/pojo.mustache b/libraries/microprofile/pojo.mustache index 675813a088d..c250bd2a36d 100644 --- a/libraries/microprofile/pojo.mustache +++ b/libraries/microprofile/pojo.mustache @@ -76,18 +76,18 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}}{{#serializ {{#vendorExtensions.x-extra-annotation}} {{{vendorExtensions.x-extra-annotation}}} {{/vendorExtensions.x-extra-annotation}} -{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} {{#withXml}}{{#isEnum}}{{^isListContainer}}{{^isMapContainer}}public {{dataType}} {{getter}}() { +{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} {{#withXml}}{{#isEnum}}{{^isListContainer}}{{^isMap}}public {{dataType}} {{getter}}() { if ({{name}} == null) { return null; } return {{name}}.value(); - }{{/isMapContainer}}{{/isListContainer}}{{/isEnum}}{{/withXml}}{{^withXml}}{{#isEnum}}{{^isListContainer}}{{^isMapContainer}}public {{datatypeWithEnum}} {{getter}}() { + }{{/isMap}}{{/isListContainer}}{{/isEnum}}{{/withXml}}{{^withXml}}{{#isEnum}}{{^isListContainer}}{{^isMap}}public {{datatypeWithEnum}} {{getter}}() { return {{name}}; - }{{/isMapContainer}}{{/isListContainer}}{{/isEnum}}{{/withXml}}{{#isEnum}}{{#isListContainer}}public {{{datatypeWithEnum}}} {{getter}}() { + }{{/isMap}}{{/isListContainer}}{{/isEnum}}{{/withXml}}{{#isEnum}}{{#isListContainer}}public {{{datatypeWithEnum}}} {{getter}}() { return {{name}}; - }{{/isListContainer}}{{/isEnum}}{{#isEnum}}{{#isMapContainer}}public {{{datatypeWithEnum}}} {{getter}}() { + }{{/isListContainer}}{{/isEnum}}{{#isEnum}}{{#isMap}}public {{{datatypeWithEnum}}} {{getter}}() { return {{name}}; - }{{/isMapContainer}}{{/isEnum}}{{^isEnum}}public {{{datatypeWithEnum}}} {{getter}}() { + }{{/isMap}}{{/isEnum}}{{^isEnum}}public {{{datatypeWithEnum}}} {{getter}}() { return {{name}}; }{{/isEnum}} @@ -110,13 +110,13 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}}{{#serializ return this; } {{/isListContainer}} - {{#isMapContainer}} + {{#isMap}} public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { this.{{name}}.put(key, {{name}}Item); return this; } - {{/isMapContainer}} + {{/isMap}} {{/isReadOnly}} {{/vars}} diff --git a/libraries/okhttp-gson/api.mustache b/libraries/okhttp-gson/api.mustache index 98bcd3d4654..821972f3391 100644 --- a/libraries/okhttp-gson/api.mustache +++ b/libraries/okhttp-gson/api.mustache @@ -166,7 +166,7 @@ public class {{classname}} { ExecutableValidator executableValidator = factory.getValidator().forExecutables(); Object[] parameterValues = { {{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}} }; - Method method = this.getClass().getMethod("{{operationId}}WithHttpInfo"{{#allParams}}, {{#isListContainer}}java.util.List{{/isListContainer}}{{#isMapContainer}}java.util.Map{{/isMapContainer}}{{^isListContainer}}{{^isMapContainer}}{{{dataType}}}{{/isMapContainer}}{{/isListContainer}}.class{{/allParams}}); + Method method = this.getClass().getMethod("{{operationId}}WithHttpInfo"{{#allParams}}, {{#isListContainer}}java.util.List{{/isListContainer}}{{#isMap}}java.util.Map{{/isMap}}{{^isListContainer}}{{^isMap}}{{{dataType}}}{{/isMap}}{{/isListContainer}}.class{{/allParams}}); Set> violations = executableValidator.validateParameters(this, method, parameterValues); diff --git a/pojo.mustache b/pojo.mustache index e6749289b7c..a442eb4e182 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -129,7 +129,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{/vendorExtensions.x-is-jackson-optional-nullable}} } {{/isListContainer}} - {{#isMapContainer}} + {{#isMap}} public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { {{#vendorExtensions.x-is-jackson-optional-nullable}} @@ -153,7 +153,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE return this; {{/vendorExtensions.x-is-jackson-optional-nullable}} } - {{/isMapContainer}} + {{/isMap}} {{/isReadOnly}} /** From 7cada351cd59ab548ef6e7c9e899a07c72294343 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 14 Oct 2020 10:10:32 +0800 Subject: [PATCH 316/370] Update junit to newer version (4.13.1) (#7690) * update junit to newer version * update junit to newer version --- build.gradle.mustache | 2 +- libraries/feign/build.gradle.mustache | 2 +- libraries/feign/build.sbt.mustache | 2 +- libraries/feign/pom.mustache | 2 +- libraries/google-api-client/build.gradle.mustache | 2 +- libraries/google-api-client/build.sbt.mustache | 2 +- libraries/google-api-client/pom.mustache | 2 +- libraries/jersey2/build.gradle.mustache | 2 +- libraries/jersey2/build.sbt.mustache | 2 +- libraries/jersey2/pom.mustache | 2 +- libraries/microprofile/pom.mustache | 2 +- libraries/native/build.gradle.mustache | 2 +- libraries/native/pom.mustache | 2 +- libraries/okhttp-gson/build.gradle.mustache | 2 +- libraries/okhttp-gson/build.sbt.mustache | 2 +- libraries/okhttp-gson/pom.mustache | 2 +- libraries/rest-assured/build.gradle.mustache | 2 +- libraries/rest-assured/build.sbt.mustache | 2 +- libraries/rest-assured/pom.mustache | 2 +- libraries/resttemplate/build.gradle.mustache | 2 +- libraries/resttemplate/pom.mustache | 2 +- libraries/retrofit/build.gradle.mustache | 2 +- libraries/retrofit/build.sbt.mustache | 2 +- libraries/retrofit/pom.mustache | 2 +- libraries/retrofit2/build.gradle.mustache | 2 +- libraries/retrofit2/build.sbt.mustache | 2 +- libraries/retrofit2/pom.mustache | 2 +- libraries/vertx/build.gradle.mustache | 2 +- libraries/vertx/pom.mustache | 2 +- libraries/webclient/pom.mustache | 2 +- 30 files changed, 30 insertions(+), 30 deletions(-) diff --git a/build.gradle.mustache b/build.gradle.mustache index e5874c4c6ba..4f408644a9b 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -146,7 +146,7 @@ ext { {{/threetenbp}} jersey_version = "1.19.4" jodatime_version = "2.9.9" - junit_version = "4.13" + junit_version = "4.13.1" } dependencies { diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index 42631b3ff42..3f9664b221a 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -130,7 +130,7 @@ ext { {{/threetenbp}} feign_version = "10.11" feign_form_version = "3.8.0" - junit_version = "4.13" + junit_version = "4.13.1" oltu_version = "1.0.1" } diff --git a/libraries/feign/build.sbt.mustache b/libraries/feign/build.sbt.mustache index 933c9137af0..322abb2a5cb 100644 --- a/libraries/feign/build.sbt.mustache +++ b/libraries/feign/build.sbt.mustache @@ -22,7 +22,7 @@ lazy val root = (project in file(".")). "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", "com.brsanthu" % "migbase64" % "2.2" % "compile", "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", - "junit" % "junit" % "4.13" % "test", + "junit" % "junit" % "4.13.1" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) ) diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index c0c30c370c6..e9abe7dbaad 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -361,7 +361,7 @@ 2.9.10 {{/threetenbp}} 1.3.2 - 4.13 + 4.13.1 1.0.0 1.0.1 diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache index c1b9bd86676..6537bf62f99 100644 --- a/libraries/google-api-client/build.gradle.mustache +++ b/libraries/google-api-client/build.gradle.mustache @@ -128,7 +128,7 @@ ext { google_api_client_version = "1.23.0" jersey_common_version = "2.25.1" jodatime_version = "2.9.9" - junit_version = "4.13" + junit_version = "4.13.1" {{#threetenbp}} jackson_threeten_version = "2.9.10" {{/threetenbp}} diff --git a/libraries/google-api-client/build.sbt.mustache b/libraries/google-api-client/build.sbt.mustache index de076de7db2..f22448cb04f 100644 --- a/libraries/google-api-client/build.sbt.mustache +++ b/libraries/google-api-client/build.sbt.mustache @@ -28,7 +28,7 @@ lazy val root = (project in file(".")). "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", {{/threetenbp}} "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", - "junit" % "junit" % "4.13" % "test", + "junit" % "junit" % "4.13.1" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) ) diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index 69eb025014d..17a87a012d4 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -341,6 +341,6 @@ {{/threetenbp}} 1.3.2 1.0.0 - 4.13 + 4.13.1 diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index 6b0921f30e7..bcbfba97447 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -132,7 +132,7 @@ ext { {{^supportJava6}} jersey_version = "2.27" {{/supportJava6}} - junit_version = "4.13" + junit_version = "4.13.1" {{#threetenbp}} threetenbp_version = "2.9.10" {{/threetenbp}} diff --git a/libraries/jersey2/build.sbt.mustache b/libraries/jersey2/build.sbt.mustache index be3b7595eb3..d4f17f702c2 100644 --- a/libraries/jersey2/build.sbt.mustache +++ b/libraries/jersey2/build.sbt.mustache @@ -40,7 +40,7 @@ lazy val root = (project in file(".")). "commons-io" % "commons-io" % "2.5", {{/supportJava6}} "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", - "junit" % "junit" % "4.13" % "test", + "junit" % "junit" % "4.13.1" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) ) diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index b305b75c80b..907c3317664 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -407,7 +407,7 @@ 2.9.10 {{/threetenbp}} 1.3.2 - 4.13 + 4.13.1 {{#hasHttpSignatureMethods}} 1.5 {{/hasHttpSignatureMethods}} diff --git a/libraries/microprofile/pom.mustache b/libraries/microprofile/pom.mustache index f57a1f77234..63321ae28bb 100644 --- a/libraries/microprofile/pom.mustache +++ b/libraries/microprofile/pom.mustache @@ -169,7 +169,7 @@ ${java.version} 1.5.18 9.2.9.v20150224 - 4.13 + 4.13.1 1.1.7 2.5 {{#useBeanValidation}} diff --git a/libraries/native/build.gradle.mustache b/libraries/native/build.gradle.mustache index f3d5335ad5f..bfa40bdcea4 100644 --- a/libraries/native/build.gradle.mustache +++ b/libraries/native/build.gradle.mustache @@ -52,7 +52,7 @@ artifacts { ext { swagger_annotations_version = "1.5.22" jackson_version = "2.9.9" - junit_version = "4.13" + junit_version = "4.13.1" } dependencies { diff --git a/libraries/native/pom.mustache b/libraries/native/pom.mustache index d9f160341c2..ad2a10ae96f 100644 --- a/libraries/native/pom.mustache +++ b/libraries/native/pom.mustache @@ -223,6 +223,6 @@ 2.9.9 0.2.1 1.3.2 - 4.13 + 4.13.1 diff --git a/libraries/okhttp-gson/build.gradle.mustache b/libraries/okhttp-gson/build.gradle.mustache index 405261e7600..b263167cb55 100644 --- a/libraries/okhttp-gson/build.gradle.mustache +++ b/libraries/okhttp-gson/build.gradle.mustache @@ -143,7 +143,7 @@ dependencies { compile 'org.threeten:threetenbp:1.4.3' {{/threetenbp}} compile 'javax.annotation:javax.annotation-api:1.3.2' - testCompile 'junit:junit:4.13' + testCompile 'junit:junit:4.13.1' } javadoc { diff --git a/libraries/okhttp-gson/build.sbt.mustache b/libraries/okhttp-gson/build.sbt.mustache index 12783935f16..16c3f694b93 100644 --- a/libraries/okhttp-gson/build.sbt.mustache +++ b/libraries/okhttp-gson/build.sbt.mustache @@ -27,7 +27,7 @@ lazy val root = (project in file(".")). "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", "com.google.code.findbugs" % "jsr305" % "3.0.2" % "compile", "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", - "junit" % "junit" % "4.13" % "test", + "junit" % "junit" % "4.13.1" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) ) diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index 41bbd03864b..b97d8ccba01 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -335,7 +335,7 @@ 1.4.3 {{/threetenbp}} 1.3.2 - 4.13 + 4.13.1 UTF-8 diff --git a/libraries/rest-assured/build.gradle.mustache b/libraries/rest-assured/build.gradle.mustache index 16b485ac436..47d9a13ea3e 100644 --- a/libraries/rest-assured/build.gradle.mustache +++ b/libraries/rest-assured/build.gradle.mustache @@ -97,7 +97,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.21" rest_assured_version = "4.3.0" - junit_version = "4.13" + junit_version = "4.13.1" {{#jackson}} jackson_version = "2.10.3" jackson_databind_version = "2.10.3" diff --git a/libraries/rest-assured/build.sbt.mustache b/libraries/rest-assured/build.sbt.mustache index 06f439c70ab..48a8c8dfcb7 100644 --- a/libraries/rest-assured/build.sbt.mustache +++ b/libraries/rest-assured/build.sbt.mustache @@ -51,7 +51,7 @@ lazy val root = (project in file(".")). "org.hibernate" % "hibernate-validator" % "6.0.19.Final" % "compile", {{/performBeanValidation}} "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", - "junit" % "junit" % "4.13" % "test", + "junit" % "junit" % "4.13.1" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) ) diff --git a/libraries/rest-assured/pom.mustache b/libraries/rest-assured/pom.mustache index 4009b48e876..57d94de93ef 100644 --- a/libraries/rest-assured/pom.mustache +++ b/libraries/rest-assured/pom.mustache @@ -365,6 +365,6 @@ {{/jackson}} 1.3.2 1.17.5 - 4.13 + 4.13.1 diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index 343e51fc3e5..57606f07311 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -127,7 +127,7 @@ ext { {{/openApiNullable}} spring_web_version = "5.2.5.RELEASE" jodatime_version = "2.9.9" - junit_version = "4.13" + junit_version = "4.13.1" {{#threetenbp}} jackson_threeten_version = "2.9.10" {{/threetenbp}} diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache index f95a520f5b6..2fdd99cf76f 100644 --- a/libraries/resttemplate/pom.mustache +++ b/libraries/resttemplate/pom.mustache @@ -334,6 +334,6 @@ 2.9.10 {{/threetenbp}} 1.0.0 - 4.13 + 4.13.1 diff --git a/libraries/retrofit/build.gradle.mustache b/libraries/retrofit/build.gradle.mustache index e610846f49d..14ce3d1dafd 100644 --- a/libraries/retrofit/build.gradle.mustache +++ b/libraries/retrofit/build.gradle.mustache @@ -111,7 +111,7 @@ ext { oltu_version = "1.0.1" retrofit_version = "1.9.0" swagger_annotations_version = "1.5.21" - junit_version = "4.13" + junit_version = "4.13.1" jodatime_version = "2.9.3" {{#threetenbp}} threetenbp_version = "1.4.0" diff --git a/libraries/retrofit/build.sbt.mustache b/libraries/retrofit/build.sbt.mustache index d55bb7c78b4..cef4b1c048d 100644 --- a/libraries/retrofit/build.sbt.mustache +++ b/libraries/retrofit/build.sbt.mustache @@ -18,7 +18,7 @@ lazy val root = (project in file(".")). "org.threeten" % "threetenbp" % "1.4.0" % "compile", {{/threetenbp}} "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", - "junit" % "junit" % "4.13" % "test", + "junit" % "junit" % "4.13.1" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) ) diff --git a/libraries/retrofit/pom.mustache b/libraries/retrofit/pom.mustache index d7cd63d9e12..d2d5bf60249 100644 --- a/libraries/retrofit/pom.mustache +++ b/libraries/retrofit/pom.mustache @@ -301,6 +301,6 @@ 1.0.1 1.3.2 1.0.0 - 4.13 + 4.13.1 diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index bf385dad75b..3ea42a41dc3 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -138,7 +138,7 @@ ext { {{/play26}} {{/usePlayWS}} swagger_annotations_version = "1.5.22" - junit_version = "4.13" + junit_version = "4.13.1" {{#useRxJava}} rx_java_version = "1.3.0" {{/useRxJava}} diff --git a/libraries/retrofit2/build.sbt.mustache b/libraries/retrofit2/build.sbt.mustache index c7785d9e392..8d386e34d84 100644 --- a/libraries/retrofit2/build.sbt.mustache +++ b/libraries/retrofit2/build.sbt.mustache @@ -52,7 +52,7 @@ lazy val root = (project in file(".")). {{/threetenbp}} "io.gsonfire" % "gson-fire" % "1.8.0" % "compile", "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", - "junit" % "junit" % "4.13" % "test", + "junit" % "junit" % "4.13.1" % "test", "com.novocode" % "junit-interface" % "0.11" % "test" ) ) diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index 327734d7944..7cb390987b3 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -452,6 +452,6 @@ {{/threetenbp}} 1.3.2 1.0.1 - 4.13 + 4.13.1 diff --git a/libraries/vertx/build.gradle.mustache b/libraries/vertx/build.gradle.mustache index 0c2c9363e3c..3166da0d84a 100644 --- a/libraries/vertx/build.gradle.mustache +++ b/libraries/vertx/build.gradle.mustache @@ -31,7 +31,7 @@ ext { jackson_version = "2.10.4" jackson_databind_version = "2.10.4" vertx_version = "3.4.2" - junit_version = "4.13" + junit_version = "4.13.1" {{#openApiNullable}} jackson_databind_nullable_version = "0.2.1" {{/openApiNullable}} diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache index 49a4f8a0ad7..d9882a1866c 100644 --- a/libraries/vertx/pom.mustache +++ b/libraries/vertx/pom.mustache @@ -315,6 +315,6 @@ 2.10.4 0.2.1 1.3.2 - 4.13 + 4.13.1 diff --git a/libraries/webclient/pom.mustache b/libraries/webclient/pom.mustache index 2b8da13b027..eadc109da4a 100644 --- a/libraries/webclient/pom.mustache +++ b/libraries/webclient/pom.mustache @@ -155,7 +155,7 @@ 2.10.3 0.2.1 1.3.2 - 4.13 + 4.13.1 3.1.8.RELEASE 0.7.8.RELEASE {{#joda}} From 0dba6543e750d71c2782cd44f72176953756fded Mon Sep 17 00:00:00 2001 From: bgong-mdsol Date: Thu, 15 Oct 2020 05:29:51 -0400 Subject: [PATCH 317/370] [Java][Native] Support oneOf/anyOf schemas (#7263) * Java-native add models of oneOf/anyOf * Java-native refresh samples * Java-native add a sample project for openapi3 --- .../native/AbstractOpenApiSchema.mustache | 138 +++++++ libraries/native/ApiResponse.mustache | 2 +- libraries/native/JSON.mustache | 276 +++++++++++++ .../native/additional_properties.mustache | 39 ++ libraries/native/anyof_model.mustache | 202 +++++++++ libraries/native/api.mustache | 12 +- libraries/native/build.gradle.mustache | 10 +- libraries/native/model.mustache | 61 +++ libraries/native/model_anyof_doc.mustache | 38 ++ libraries/native/model_doc.mustache | 19 + libraries/native/model_oneof_doc.mustache | 38 ++ libraries/native/oneof_model.mustache | 235 +++++++++++ libraries/native/pojo.mustache | 386 ++++++++++++++++++ libraries/native/pom.mustache | 21 +- 14 files changed, 1468 insertions(+), 9 deletions(-) create mode 100644 libraries/native/AbstractOpenApiSchema.mustache create mode 100644 libraries/native/JSON.mustache create mode 100644 libraries/native/additional_properties.mustache create mode 100644 libraries/native/anyof_model.mustache create mode 100644 libraries/native/model.mustache create mode 100644 libraries/native/model_anyof_doc.mustache create mode 100644 libraries/native/model_doc.mustache create mode 100644 libraries/native/model_oneof_doc.mustache create mode 100644 libraries/native/oneof_model.mustache create mode 100644 libraries/native/pojo.mustache diff --git a/libraries/native/AbstractOpenApiSchema.mustache b/libraries/native/AbstractOpenApiSchema.mustache new file mode 100644 index 00000000000..5b2198dedb5 --- /dev/null +++ b/libraries/native/AbstractOpenApiSchema.mustache @@ -0,0 +1,138 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.model; + +import {{invokerPackage}}.ApiException; +import java.util.Objects; +import java.lang.reflect.Type; +import java.util.Map; +import javax.ws.rs.core.GenericType; + +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Abstract class for oneOf,anyOf schemas defined in OpenAPI spec + */ +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}} +public abstract class AbstractOpenApiSchema { + + // store the actual instance of the schema/object + private Object instance; + + // is nullable + private Boolean isNullable; + + // schema type (e.g. oneOf, anyOf) + private final String schemaType; + + public AbstractOpenApiSchema(String schemaType, Boolean isNullable) { + this.schemaType = schemaType; + this.isNullable = isNullable; + } + + /** + * Get the list of oneOf/anyOf composed schemas allowed to be stored in this object + * + * @return an instance of the actual schema/object + */ + public abstract Map getSchemas(); + + /** + * Get the actual instance + * + * @return an instance of the actual schema/object + */ + @JsonValue + public Object getActualInstance() {return instance;} + + /** + * Set the actual instance + * + * @param instance the actual instance of the schema/object + */ + public void setActualInstance(Object instance) {this.instance = instance;} + + /** + * Get the instant recursively when the schemas defined in oneOf/anyof happen to be oneOf/anyOf schema as well + * + * @return an instance of the actual schema/object + */ + public Object getActualInstanceRecursively() { + return getActualInstanceRecursively(this); + } + + private Object getActualInstanceRecursively(AbstractOpenApiSchema object) { + if (object.getActualInstance() == null) { + return null; + } else if (object.getActualInstance() instanceof AbstractOpenApiSchema) { + return getActualInstanceRecursively((AbstractOpenApiSchema)object.getActualInstance()); + } else { + return object.getActualInstance(); + } + } + + /** + * Get the schema type (e.g. anyOf, oneOf) + * + * @return the schema type + */ + public String getSchemaType() { + return schemaType; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ").append(getClass()).append(" {\n"); + sb.append(" instance: ").append(toIndentedString(instance)).append("\n"); + sb.append(" isNullable: ").append(toIndentedString(isNullable)).append("\n"); + sb.append(" schemaType: ").append(toIndentedString(schemaType)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AbstractOpenApiSchema a = (AbstractOpenApiSchema) o; + return Objects.equals(this.instance, a.instance) && + Objects.equals(this.isNullable, a.isNullable) && + Objects.equals(this.schemaType, a.schemaType); + } + + @Override + public int hashCode() { + return Objects.hash(instance, isNullable, schemaType); + } + + /** + * Is nullalble + * + * @return true if it's nullable + */ + public Boolean isNullable() { + if (Boolean.TRUE.equals(isNullable)) { + return Boolean.TRUE; + } else { + return Boolean.FALSE; + } + } + +{{>libraries/native/additional_properties}} + +} diff --git a/libraries/native/ApiResponse.mustache b/libraries/native/ApiResponse.mustache index 1e277319a93..1f3f3a31981 100644 --- a/libraries/native/ApiResponse.mustache +++ b/libraries/native/ApiResponse.mustache @@ -5,7 +5,7 @@ package {{invokerPackage}}; import java.util.List; import java.util.Map; {{#caseInsensitiveResponseHeaders}} -import java.util.Map.Entry; +import java.util.Map.Entry; import java.util.TreeMap; {{/caseInsensitiveResponseHeaders}} diff --git a/libraries/native/JSON.mustache b/libraries/native/JSON.mustache new file mode 100644 index 00000000000..16aa21e1403 --- /dev/null +++ b/libraries/native/JSON.mustache @@ -0,0 +1,276 @@ +package {{invokerPackage}}; + +{{#threetenbp}} +import org.threeten.bp.*; +{{/threetenbp}} +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.*; +{{#openApiNullable}} +import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} +{{#java8}} +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{/java8}} +{{#joda}} +import com.fasterxml.jackson.datatype.joda.JodaModule; +{{/joda}} +{{#threetenbp}} +import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; +{{/threetenbp}} +{{#models.0}} +import {{modelPackage}}.*; +{{/models.0}} + +import java.text.DateFormat; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.ext.ContextResolver; + +{{>generatedAnnotation}} +public class JSON implements ContextResolver { + private ObjectMapper mapper; + + public JSON() { + mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.setDateFormat(new RFC3339DateFormat()); + {{#java8}} + mapper.registerModule(new JavaTimeModule()); + {{/java8}} + {{#joda}} + mapper.registerModule(new JodaModule()); + {{/joda}} + {{#threetenbp}} + ThreeTenModule module = new ThreeTenModule(); + module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); + module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); + module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); + mapper.registerModule(module); + {{/threetenbp}} + {{#openApiNullable}} + JsonNullableModule jnm = new JsonNullableModule(); + mapper.registerModule(jnm); + {{/openApiNullable}} + } + + /** + * Set the date format for JSON (de)serialization with Date properties. + * @param dateFormat Date format + */ + public void setDateFormat(DateFormat dateFormat) { + mapper.setDateFormat(dateFormat); + } + + @Override + public ObjectMapper getContext(Class type) { + return mapper; + } + + /** + * Get the object mapper + * + * @return object mapper + */ + public ObjectMapper getMapper() { return mapper; } + + /** + * Returns the target model class that should be used to deserialize the input data. + * The discriminator mappings are used to determine the target model class. + * + * @param node The input data. + * @param modelClass The class that contains the discriminator mappings. + */ + public static Class getClassForElement(JsonNode node, Class modelClass) { + ClassDiscriminatorMapping cdm = modelDiscriminators.get(modelClass); + if (cdm != null) { + return cdm.getClassForElement(node, new HashSet>()); + } + return null; + } + + /** + * Helper class to register the discriminator mappings. + */ + private static class ClassDiscriminatorMapping { + // The model class name. + Class modelClass; + // The name of the discriminator property. + String discriminatorName; + // The discriminator mappings for a model class. + Map> discriminatorMappings; + + // Constructs a new class discriminator. + ClassDiscriminatorMapping(Class cls, String propertyName, Map> mappings) { + modelClass = cls; + discriminatorName = propertyName; + discriminatorMappings = new HashMap>(); + if (mappings != null) { + discriminatorMappings.putAll(mappings); + } + } + + // Return the name of the discriminator property for this model class. + String getDiscriminatorPropertyName() { + return discriminatorName; + } + + // Return the discriminator value or null if the discriminator is not + // present in the payload. + String getDiscriminatorValue(JsonNode node) { + // Determine the value of the discriminator property in the input data. + if (discriminatorName != null) { + // Get the value of the discriminator property, if present in the input payload. + node = node.get(discriminatorName); + if (node != null && node.isValueNode()) { + String discrValue = node.asText(); + if (discrValue != null) { + return discrValue; + } + } + } + return null; + } + + /** + * Returns the target model class that should be used to deserialize the input data. + * This function can be invoked for anyOf/oneOf composed models with discriminator mappings. + * The discriminator mappings are used to determine the target model class. + * + * @param node The input data. + * @param visitedClasses The set of classes that have already been visited. + */ + Class getClassForElement(JsonNode node, Set> visitedClasses) { + if (visitedClasses.contains(modelClass)) { + // Class has already been visited. + return null; + } + // Determine the value of the discriminator property in the input data. + String discrValue = getDiscriminatorValue(node); + if (discrValue == null) { + return null; + } + Class cls = discriminatorMappings.get(discrValue); + // It may not be sufficient to return this cls directly because that target class + // may itself be a composed schema, possibly with its own discriminator. + visitedClasses.add(modelClass); + for (Class childClass : discriminatorMappings.values()) { + ClassDiscriminatorMapping childCdm = modelDiscriminators.get(childClass); + if (childCdm == null) { + continue; + } + if (!discriminatorName.equals(childCdm.discriminatorName)) { + discrValue = getDiscriminatorValue(node); + if (discrValue == null) { + continue; + } + } + if (childCdm != null) { + // Recursively traverse the discriminator mappings. + Class childDiscr = childCdm.getClassForElement(node, visitedClasses); + if (childDiscr != null) { + return childDiscr; + } + } + } + return cls; + } + } + + /** + * Returns true if inst is an instance of modelClass in the OpenAPI model hierarchy. + * + * The Java class hierarchy is not implemented the same way as the OpenAPI model hierarchy, + * so it's not possible to use the instanceof keyword. + * + * @param modelClass A OpenAPI model class. + * @param inst The instance object. + */ + public static boolean isInstanceOf(Class modelClass, Object inst, Set> visitedClasses) { + if (modelClass.isInstance(inst)) { + // This handles the 'allOf' use case with single parent inheritance. + return true; + } + if (visitedClasses.contains(modelClass)) { + // This is to prevent infinite recursion when the composed schemas have + // a circular dependency. + return false; + } + visitedClasses.add(modelClass); + + // Traverse the oneOf/anyOf composed schemas. + Map descendants = modelDescendants.get(modelClass); + if (descendants != null) { + for (GenericType childType : descendants.values()) { + if (isInstanceOf(childType.getRawType(), inst, visitedClasses)) { + return true; + } + } + } + return false; + } + + /** + * A map of discriminators for all model classes. + */ + private static Map, ClassDiscriminatorMapping> modelDiscriminators = new HashMap, ClassDiscriminatorMapping>(); + + /** + * A map of oneOf/anyOf descendants for each model class. + */ + private static Map, Map> modelDescendants = new HashMap, Map>(); + + /** + * Register a model class discriminator. + * + * @param modelClass the model class + * @param discriminatorPropertyName the name of the discriminator property + * @param mappings a map with the discriminator mappings. + */ + public static void registerDiscriminator(Class modelClass, String discriminatorPropertyName, Map> mappings) { + ClassDiscriminatorMapping m = new ClassDiscriminatorMapping(modelClass, discriminatorPropertyName, mappings); + modelDiscriminators.put(modelClass, m); + } + + /** + * Register the oneOf/anyOf descendants of the modelClass. + * + * @param modelClass the model class + * @param descendants a map of oneOf/anyOf descendants. + */ + public static void registerDescendants(Class modelClass, Map descendants) { + modelDescendants.put(modelClass, descendants); + } + + private static JSON json; + + static { + json = new JSON(); + } + + /** + * Get the default JSON instance. + * + * @return the default JSON instance + */ + public static JSON getDefault() { + return json; + } + + /** + * Set the default JSON instance. + * + * @param json JSON instance to be used + */ + public static void setDefault(JSON json) { + JSON.json = json; + } +} diff --git a/libraries/native/additional_properties.mustache b/libraries/native/additional_properties.mustache new file mode 100644 index 00000000000..61973dc24fa --- /dev/null +++ b/libraries/native/additional_properties.mustache @@ -0,0 +1,39 @@ +{{#additionalPropertiesType}} + /** + * A container for additional, undeclared properties. + * This is a holder for any undeclared properties as specified with + * the 'additionalProperties' keyword in the OAS document. + */ + private Map additionalProperties; + + /** + * Set the additional (undeclared) property with the specified name and value. + * If the property does not already exist, create it otherwise replace it. + */ + @JsonAnySetter + public {{classname}} putAdditionalProperty(String key, {{{.}}} value) { + if (this.additionalProperties == null) { + this.additionalProperties = new HashMap(); + } + this.additionalProperties.put(key, value); + return this; + } + + /** + * Return the additional (undeclared) property. + */ + @JsonAnyGetter + public Map getAdditionalProperties() { + return additionalProperties; + } + + /** + * Return the additional (undeclared) property with the specified name. + */ + public {{{.}}} getAdditionalProperty(String key) { + if (this.additionalProperties == null) { + return null; + } + return this.additionalProperties.get(key); + } +{{/additionalPropertiesType}} diff --git a/libraries/native/anyof_model.mustache b/libraries/native/anyof_model.mustache new file mode 100644 index 00000000000..8cba2615105 --- /dev/null +++ b/libraries/native/anyof_model.mustache @@ -0,0 +1,202 @@ +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.Response; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import {{invokerPackage}}.JSON; + +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} +@JsonDeserialize(using={{classname}}.{{classname}}Deserializer.class) +@JsonSerialize(using = {{classname}}.{{classname}}Serializer.class) +public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}}, {{{.}}}{{/vendorExtensions.x-implements}} { + private static final Logger log = Logger.getLogger({{classname}}.class.getName()); + + public static class {{classname}}Serializer extends StdSerializer<{{classname}}> { + public {{classname}}Serializer(Class<{{classname}}> t) { + super(t); + } + + public {{classname}}Serializer() { + this(null); + } + + @Override + public void serialize({{classname}} value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeObject(value.getActualInstance()); + } + } + + public static class {{classname}}Deserializer extends StdDeserializer<{{classname}}> { + public {{classname}}Deserializer() { + this({{classname}}.class); + } + + public {{classname}}Deserializer(Class vc) { + super(vc); + } + + @Override + public {{classname}} deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + JsonNode tree = jp.readValueAsTree(); + + Object deserialized = null; + {{#discriminator}} + Class cls = JSON.getClassForElement(tree, {{classname}}.class); + if (cls != null) { + // When the OAS schema includes a discriminator, use the discriminator value to + // discriminate the anyOf schemas. + // Get the discriminator mapping value to get the class. + deserialized = tree.traverse(jp.getCodec()).readValueAs(cls); + {{classname}} ret = new {{classname}}(); + ret.setActualInstance(deserialized); + return ret; + } + {{/discriminator}} + {{#anyOf}} + // deserialize {{{.}}} + try { + deserialized = tree.traverse(jp.getCodec()).readValueAs({{{.}}}.class); + {{classname}} ret = new {{classname}}(); + ret.setActualInstance(deserialized); + return ret; + } catch (Exception e) { + // deserialization failed, continue, log to help debugging + log.log(Level.FINER, "Input data does not match '{{classname}}'", e); + } + + {{/anyOf}} + throw new IOException(String.format("Failed deserialization for {{classname}}: no match found")); + } + + /** + * Handle deserialization of the 'null' value. + */ + @Override + public {{classname}} getNullValue(DeserializationContext ctxt) throws JsonMappingException { + {{#isNullable}} + return null; + {{/isNullable}} + {{^isNullable}} + throw new JsonMappingException(ctxt.getParser(), "{{classname}} cannot be null"); + {{/isNullable}} + } + } + + // store a list of schema names defined in anyOf + public final static Map schemas = new HashMap(); + + public {{classname}}() { + super("anyOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + } +{{> libraries/native/additional_properties }} + {{#additionalPropertiesType}} + /** + * Return true if this {{name}} object is equal to o. + */ + @Override + public boolean equals(Object o) { + return super.equals(o) && Objects.equals(this.additionalProperties, (({{classname}})o).additionalProperties); + } + + @Override + public int hashCode() { + return Objects.hash(getActualInstance(), isNullable(), getSchemaType(), additionalProperties); + } + {{/additionalPropertiesType}} + {{#anyOf}} + public {{classname}}({{{.}}} o) { + super("anyOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + setActualInstance(o); + } + + {{/anyOf}} + static { + {{#anyOf}} + schemas.put("{{{.}}}", new GenericType<{{{.}}}>() { + }); + {{/anyOf}} + JSON.registerDescendants({{classname}}.class, Collections.unmodifiableMap(schemas)); + {{#discriminator}} + // Initialize and register the discriminator mappings. + Map> mappings = new HashMap>(); + {{#mappedModels}} + mappings.put("{{mappingName}}", {{modelName}}.class); + {{/mappedModels}} + mappings.put("{{name}}", {{classname}}.class); + JSON.registerDiscriminator({{classname}}.class, "{{propertyBaseName}}", mappings); + {{/discriminator}} + } + + @Override + public Map getSchemas() { + return {{classname}}.schemas; + } + + /** + * Set the instance that matches the anyOf child schema, check + * the instance parameter is valid against the anyOf child schemas: + * {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}} + * + * It could be an instance of the 'anyOf' schemas. + * The anyOf child schemas may themselves be a composed schema (allOf, anyOf, anyOf). + */ + @Override + public void setActualInstance(Object instance) { + {{#isNullable}} + if (instance == null) { + super.setActualInstance(instance); + return; + } + + {{/isNullable}} + {{#anyOf}} + if (JSON.isInstanceOf({{{.}}}.class, instance, new HashSet>())) { + super.setActualInstance(instance); + return; + } + + {{/anyOf}} + throw new RuntimeException("Invalid instance type. Must be {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}"); + } + + /** + * Get the actual instance, which can be the following: + * {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}} + * + * @return The actual instance ({{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}) + */ + @Override + public Object getActualInstance() { + return super.getActualInstance(); + } + + {{#anyOf}} + /** + * Get the actual instance of `{{{.}}}`. If the actual instanct is not `{{{.}}}`, + * the ClassCastException will be thrown. + * + * @return The actual instance of `{{{.}}}` + * @throws ClassCastException if the instance is not `{{{.}}}` + */ + public {{{.}}} get{{{.}}}() throws ClassCastException { + return ({{{.}}})super.getActualInstance(); + } + + {{/anyOf}} +} diff --git a/libraries/native/api.mustache b/libraries/native/api.mustache index d524d312f22..75910062985 100644 --- a/libraries/native/api.mustache +++ b/libraries/native/api.mustache @@ -71,7 +71,7 @@ public class {{classname}} { /** * {{summary}} * {{notes}} - * @param {{operationId}}Request {@link API{{operationId}}Request} + * @param apiRequest {@link API{{operationId}}Request} {{#returnType}} * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}{{returnType}}{{#asyncNative}}>{{/asyncNative}} {{/returnType}} @@ -87,9 +87,9 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}(API{{operationId}}Request {{operationId}}Request) throws ApiException { + public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}(API{{operationId}}Request apiRequest) throws ApiException { {{#allParams}} - {{{dataType}}} {{paramName}} = {{operationId}}Request.{{paramName}}(); + {{{dataType}}} {{paramName}} = apiRequest.{{paramName}}(); {{/allParams}} {{#returnType}}return {{/returnType}}{{^returnType}}{{#asyncNative}}return {{/asyncNative}}{{/returnType}}{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); } @@ -97,7 +97,7 @@ public class {{classname}} { /** * {{summary}} * {{notes}} - * @param {{operationId}}Request {@link API{{operationId}}Request} + * @param apiRequest {@link API{{operationId}}Request} * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} * @throws ApiException if fails to make API call {{#isDeprecated}} @@ -111,9 +111,9 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}}WithHttpInfo(API{{operationId}}Request {{operationId}}Request) throws ApiException { + public {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}}WithHttpInfo(API{{operationId}}Request apiRequest) throws ApiException { {{#allParams}} - {{{dataType}}} {{paramName}} = {{operationId}}Request.{{paramName}}(); + {{{dataType}}} {{paramName}} = apiRequest.{{paramName}}(); {{/allParams}} return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); } diff --git a/libraries/native/build.gradle.mustache b/libraries/native/build.gradle.mustache index bfa40bdcea4..312d1f5db1f 100644 --- a/libraries/native/build.gradle.mustache +++ b/libraries/native/build.gradle.mustache @@ -51,8 +51,12 @@ artifacts { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.9.9" + jackson_version = "2.10.4" junit_version = "4.13.1" + ws_rs_version = "2.1.1" + {{#threetenbp}} + threetenbp_version = "2.9.10" + {{/threetenbp}} } dependencies { @@ -64,5 +68,9 @@ dependencies { compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" compile "org.openapitools:jackson-databind-nullable:0.2.1" compile 'javax.annotation:javax.annotation-api:1.3.2' + compile "javax.ws.rs:javax.ws.rs-api:$ws_rs_version" + {{#threetenbp}} + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$threetenbp_version" + {{/threetenbp}} testCompile "junit:junit:$junit_version" } diff --git a/libraries/native/model.mustache b/libraries/native/model.mustache new file mode 100644 index 00000000000..18ee1211785 --- /dev/null +++ b/libraries/native/model.mustache @@ -0,0 +1,61 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#useReflectionEqualsHashCode}} +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +{{/useReflectionEqualsHashCode}} +{{#models}} +{{#model}} +{{#additionalPropertiesType}} +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +{{/additionalPropertiesType}} +{{/model}} +{{/models}} +import java.util.Objects; +import java.util.Arrays; +import java.util.Map; +import java.util.HashMap; +{{#imports}} +import {{import}}; +{{/imports}} +{{#serializableModel}} +import java.io.Serializable; +{{/serializableModel}} +{{#jackson}} +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +{{#withXml}} +import com.fasterxml.jackson.dataformat.xml.annotation.*; +{{/withXml}} +{{/jackson}} +{{#withXml}} +import javax.xml.bind.annotation.*; +{{/withXml}} +{{#parcelableModel}} +import android.os.Parcelable; +import android.os.Parcel; +{{/parcelableModel}} +{{#useBeanValidation}} +import javax.validation.constraints.*; +import javax.validation.Valid; +{{/useBeanValidation}} +{{#performBeanValidation}} +import org.hibernate.validator.constraints.*; +{{/performBeanValidation}} +import {{invokerPackage}}.JSON; + +{{#models}} +{{#model}} +{{#oneOf}} +{{#-first}} +import com.fasterxml.jackson.core.type.TypeReference; +{{/-first}} +{{/oneOf}} + +{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{#oneOf}}{{#-first}}{{>oneof_model}}{{/-first}}{{/oneOf}}{{^oneOf}}{{#anyOf}}{{#-first}}{{>anyof_model}}{{/-first}}{{/anyOf}}{{^anyOf}}{{>pojo}}{{/anyOf}}{{/oneOf}}{{/isEnum}} +{{/model}} +{{/models}} diff --git a/libraries/native/model_anyof_doc.mustache b/libraries/native/model_anyof_doc.mustache new file mode 100644 index 00000000000..e360aa56e6c --- /dev/null +++ b/libraries/native/model_anyof_doc.mustache @@ -0,0 +1,38 @@ +# {{classname}} + +{{#description}} +{{&description}} + +{{/description}} +## anyOf schemas +{{#anyOf}} +* [{{{.}}}]({{{.}}}.md) +{{/anyOf}} + +{{#isNullable}} +NOTE: this class is nullable. + +{{/isNullable}} +## Example +```java +// Import classes: +import {{{package}}}.{{{classname}}}; +{{#anyOf}} +import {{{package}}}.{{{.}}}; +{{/anyOf}} + +public class Example { + public static void main(String[] args) { + {{classname}} example{{classname}} = new {{classname}}(); + {{#anyOf}} + + // create a new {{{.}}} + {{{.}}} example{{{.}}} = new {{{.}}}(); + // set {{{classname}}} to {{{.}}} + example{{classname}}.setActualInstance(example{{{.}}}); + // to get back the {{{.}}} set earlier + {{{.}}} test{{{.}}} = ({{{.}}}) example{{classname}}.getActualInstance(); + {{/anyOf}} + } +} +``` diff --git a/libraries/native/model_doc.mustache b/libraries/native/model_doc.mustache new file mode 100644 index 00000000000..be1aedcf2f3 --- /dev/null +++ b/libraries/native/model_doc.mustache @@ -0,0 +1,19 @@ +{{#models}}{{#model}} + +{{#isEnum}} +{{>enum_outer_doc}} +{{/isEnum}} +{{^isEnum}} +{{^oneOf.isEmpty}} +{{>model_oneof_doc}} +{{/oneOf.isEmpty}} +{{^anyOf.isEmpty}} +{{>model_anyof_doc}} +{{/anyOf.isEmpty}} +{{^anyOf}} +{{^oneOf}} +{{>pojo_doc}} +{{/oneOf}} +{{/anyOf}} +{{/isEnum}} +{{/model}}{{/models}} diff --git a/libraries/native/model_oneof_doc.mustache b/libraries/native/model_oneof_doc.mustache new file mode 100644 index 00000000000..5fff76c9efa --- /dev/null +++ b/libraries/native/model_oneof_doc.mustache @@ -0,0 +1,38 @@ +# {{classname}} + +{{#description}} +{{&description}} + +{{/description}} +## oneOf schemas +{{#oneOf}} +* [{{{.}}}]({{{.}}}.md) +{{/oneOf}} + +{{#isNullable}} +NOTE: this class is nullable. + +{{/isNullable}} +## Example +```java +// Import classes: +import {{{package}}}.{{{classname}}}; +{{#oneOf}} +import {{{package}}}.{{{.}}}; +{{/oneOf}} + +public class Example { + public static void main(String[] args) { + {{classname}} example{{classname}} = new {{classname}}(); + {{#oneOf}} + + // create a new {{{.}}} + {{{.}}} example{{{.}}} = new {{{.}}}(); + // set {{{classname}}} to {{{.}}} + example{{classname}}.setActualInstance(example{{{.}}}); + // to get back the {{{.}}} set earlier + {{{.}}} test{{{.}}} = ({{{.}}}) example{{classname}}.getActualInstance(); + {{/oneOf}} + } +} +``` diff --git a/libraries/native/oneof_model.mustache b/libraries/native/oneof_model.mustache new file mode 100644 index 00000000000..f130362ea3d --- /dev/null +++ b/libraries/native/oneof_model.mustache @@ -0,0 +1,235 @@ +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.Response; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import {{invokerPackage}}.JSON; + +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} +@JsonDeserialize(using = {{classname}}.{{classname}}Deserializer.class) +@JsonSerialize(using = {{classname}}.{{classname}}Serializer.class) +public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}}, {{{.}}}{{/vendorExtensions.x-implements}} { + private static final Logger log = Logger.getLogger({{classname}}.class.getName()); + + public static class {{classname}}Serializer extends StdSerializer<{{classname}}> { + public {{classname}}Serializer(Class<{{classname}}> t) { + super(t); + } + + public {{classname}}Serializer() { + this(null); + } + + @Override + public void serialize({{classname}} value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeObject(value.getActualInstance()); + } + } + + public static class {{classname}}Deserializer extends StdDeserializer<{{classname}}> { + public {{classname}}Deserializer() { + this({{classname}}.class); + } + + public {{classname}}Deserializer(Class vc) { + super(vc); + } + + @Override + public {{classname}} deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + JsonNode tree = jp.readValueAsTree(); + Object deserialized = null; + {{#useOneOfDiscriminatorLookup}} + {{#discriminator}} + {{classname}} new{{classname}} = new {{classname}}(); + Map result2 = tree.traverse(jp.getCodec()).readValueAs(new TypeReference>() {}); + String discriminatorValue = (String)result2.get("{{{propertyBaseName}}}"); + switch (discriminatorValue) { + {{#mappedModels}} + case "{{{mappingName}}}": + deserialized = tree.traverse(jp.getCodec()).readValueAs({{{modelName}}}.class); + new{{classname}}.setActualInstance(deserialized); + return new{{classname}}; + {{/mappedModels}} + default: + log.log(Level.WARNING, String.format("Failed to lookup discriminator value `%s` for {{classname}}. Possible values:{{#mappedModels}} {{{mappingName}}}{{/mappedModels}}", discriminatorValue)); + } + + {{/discriminator}} + {{/useOneOfDiscriminatorLookup}} + boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS); + int match = 0; + JsonToken token = tree.traverse(jp.getCodec()).nextToken(); + {{#oneOf}} + // deserialize {{{.}}} + try { + boolean attemptParsing = true; + // ensure that we respect type coercion as set on the client ObjectMapper + if ({{{.}}}.class.equals(Integer.class) || {{{.}}}.class.equals(Long.class) || {{{.}}}.class.equals(Float.class) || {{{.}}}.class.equals(Double.class) || {{{.}}}.class.equals(Boolean.class) || {{{.}}}.class.equals(String.class)) { + attemptParsing = typeCoercion; + if (!attemptParsing) { + attemptParsing |= (({{{.}}}.class.equals(Integer.class) || {{{.}}}.class.equals(Long.class)) && token == JsonToken.VALUE_NUMBER_INT); + attemptParsing |= (({{{.}}}.class.equals(Float.class) || {{{.}}}.class.equals(Double.class)) && token == JsonToken.VALUE_NUMBER_FLOAT); + attemptParsing |= ({{{.}}}.class.equals(Boolean.class) && (token == JsonToken.VALUE_FALSE || token == JsonToken.VALUE_TRUE)); + attemptParsing |= ({{{.}}}.class.equals(String.class) && token == JsonToken.VALUE_STRING); + {{#isNullable}} + attemptParsing |= (token == JsonToken.VALUE_NULL); + {{/isNullable}} + } + } + if (attemptParsing) { + deserialized = tree.traverse(jp.getCodec()).readValueAs({{{.}}}.class); + // TODO: there is no validation against JSON schema constraints + // (min, max, enum, pattern...), this does not perform a strict JSON + // validation, which means the 'match' count may be higher than it should be. + match++; + log.log(Level.FINER, "Input data matches schema '{{{.}}}'"); + } + } catch (Exception e) { + // deserialization failed, continue + log.log(Level.FINER, "Input data does not match schema '{{{.}}}'", e); + } + + {{/oneOf}} + if (match == 1) { + {{classname}} ret = new {{classname}}(); + ret.setActualInstance(deserialized); + return ret; + } + throw new IOException(String.format("Failed deserialization for {{classname}}: %d classes match result, expected 1", match)); + } + + /** + * Handle deserialization of the 'null' value. + */ + @Override + public {{classname}} getNullValue(DeserializationContext ctxt) throws JsonMappingException { + {{#isNullable}} + return null; + {{/isNullable}} + {{^isNullable}} + throw new JsonMappingException(ctxt.getParser(), "{{classname}} cannot be null"); + {{/isNullable}} + } + } + + // store a list of schema names defined in oneOf + public final static Map schemas = new HashMap(); + + public {{classname}}() { + super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + } +{{> libraries/native/additional_properties }} + {{#additionalPropertiesType}} + /** + * Return true if this {{name}} object is equal to o. + */ + @Override + public boolean equals(Object o) { + return super.equals(o) && Objects.equals(this.additionalProperties, (({{classname}})o).additionalProperties); + } + + @Override + public int hashCode() { + return Objects.hash(getActualInstance(), isNullable(), getSchemaType(), additionalProperties); + } + {{/additionalPropertiesType}} + {{#oneOf}} + public {{classname}}({{{.}}} o) { + super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + setActualInstance(o); + } + + {{/oneOf}} + static { + {{#oneOf}} + schemas.put("{{{.}}}", new GenericType<{{{.}}}>() { + }); + {{/oneOf}} + JSON.registerDescendants({{classname}}.class, Collections.unmodifiableMap(schemas)); + {{#discriminator}} + // Initialize and register the discriminator mappings. + Map> mappings = new HashMap>(); + {{#mappedModels}} + mappings.put("{{mappingName}}", {{modelName}}.class); + {{/mappedModels}} + mappings.put("{{name}}", {{classname}}.class); + JSON.registerDiscriminator({{classname}}.class, "{{propertyBaseName}}", mappings); + {{/discriminator}} + } + + @Override + public Map getSchemas() { + return {{classname}}.schemas; + } + + /** + * Set the instance that matches the oneOf child schema, check + * the instance parameter is valid against the oneOf child schemas: + * {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}} + * + * It could be an instance of the 'oneOf' schemas. + * The oneOf child schemas may themselves be a composed schema (allOf, anyOf, oneOf). + */ + @Override + public void setActualInstance(Object instance) { + {{#isNullable}} + if (instance == null) { + super.setActualInstance(instance); + return; + } + + {{/isNullable}} + {{#oneOf}} + if (JSON.isInstanceOf({{{.}}}.class, instance, new HashSet>())) { + super.setActualInstance(instance); + return; + } + + {{/oneOf}} + throw new RuntimeException("Invalid instance type. Must be {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}"); + } + + /** + * Get the actual instance, which can be the following: + * {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}} + * + * @return The actual instance ({{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}) + */ + @Override + public Object getActualInstance() { + return super.getActualInstance(); + } + + {{#oneOf}} + /** + * Get the actual instance of `{{{.}}}`. If the actual instanct is not `{{{.}}}`, + * the ClassCastException will be thrown. + * + * @return The actual instance of `{{{.}}}` + * @throws ClassCastException if the instance is not `{{{.}}}` + */ + public {{{.}}} get{{{.}}}() throws ClassCastException { + return ({{{.}}})super.getActualInstance(); + } + + {{/oneOf}} +} diff --git a/libraries/native/pojo.mustache b/libraries/native/pojo.mustache new file mode 100644 index 00000000000..9786b9e10b9 --- /dev/null +++ b/libraries/native/pojo.mustache @@ -0,0 +1,386 @@ +/** + * {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}} + */{{#description}} +@ApiModel(description = "{{{description}}}"){{/description}} +{{#jackson}} +@JsonPropertyOrder({ +{{#vars}} + {{classname}}.JSON_PROPERTY_{{nameInSnakeCase}}{{^-last}},{{/-last}} +{{/vars}} +}) +{{/jackson}} +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} +public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{ +{{#serializableModel}} + private static final long serialVersionUID = 1L; + +{{/serializableModel}} + {{#vars}} + {{#isEnum}} + {{^isContainer}} + {{^vendorExtensions.x-enum-as-string}} +{{>modelInnerEnum}} + {{/vendorExtensions.x-enum-as-string}} + {{/isContainer}} + {{#isContainer}} + {{#mostInnerItems}} +{{>modelInnerEnum}} + {{/mostInnerItems}} + {{/isContainer}} + {{/isEnum}} + {{#gson}} + public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}"; + {{/gson}} + {{#jackson}} + public static final String JSON_PROPERTY_{{nameInSnakeCase}} = "{{baseName}}"; + {{/jackson}} + {{#withXml}} + {{#isXmlAttribute}} + @XmlAttribute(name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlAttribute}} + {{^isXmlAttribute}} + {{^isContainer}} + @XmlElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isContainer}} + {{#isContainer}} + // Is a container wrapped={{isXmlWrapped}} + {{#items}} + // items.name={{name}} items.baseName={{baseName}} items.xmlName={{xmlName}} items.xmlNamespace={{xmlNamespace}} + // items.example={{example}} items.type={{dataType}} + @XmlElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/items}} + {{#isXmlWrapped}} + @XmlElementWrapper({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlWrapped}} + {{/isContainer}} + {{/isXmlAttribute}} + {{/withXml}} + {{#gson}} + @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}}) + {{/gson}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#isContainer}} + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined(); + {{/isContainer}} + {{^isContainer}} + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + {{/isContainer}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{#isContainer}} + private {{{datatypeWithEnum}}} {{name}}{{#required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/required}}{{^required}} = null{{/required}}; + {{/isContainer}} + {{^isContainer}} + private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; + {{/isContainer}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + + {{/vars}} + {{#parcelableModel}} + public {{classname}}() { + {{#parent}} + super(); + {{/parent}} + {{#gson}} + {{#discriminator}} + this.{{{discriminatorName}}} = this.getClass().getSimpleName(); + {{/discriminator}} + {{/gson}} + } + {{/parcelableModel}} + {{^parcelableModel}} + {{#gson}} + {{#discriminator}} + public {{classname}}() { + this.{{{discriminatorName}}} = this.getClass().getSimpleName(); + } + {{/discriminator}} + {{/gson}} + {{/parcelableModel}} + {{#vars}} + + {{^isReadOnly}} + {{#vendorExtensions.x-enum-as-string}} + public static final Set {{{nameInSnakeCase}}}_VALUES = new HashSet<>(Arrays.asList( + {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}} + )); + + {{/vendorExtensions.x-enum-as-string}} + public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-enum-as-string}} + if (!{{{nameInSnakeCase}}}_VALUES.contains({{name}})) { + throw new IllegalArgumentException({{name}} + " is invalid. Possible values for {{name}}: " + String.join(", ", {{{nameInSnakeCase}}}_VALUES)); + } + + {{/vendorExtensions.x-enum-as-string}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + return this; + } + {{#isListContainer}} + + public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null || !this.{{name}}.isPresent()) { + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); + } + try { + this.{{name}}.get().add({{name}}Item); + } catch (java.util.NoSuchElementException e) { + // this can never happen, as we make sure above that the value is present + } + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.add({{name}}Item); + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isListContainer}} + {{#isMapContainer}} + + public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null || !this.{{name}}.isPresent()) { + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); + } + try { + this.{{name}}.get().put(key, {{name}}Item); + } catch (java.util.NoSuchElementException e) { + // this can never happen, as we make sure above that the value is present + } + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.put(key, {{name}}Item); + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isMapContainer}} + + {{/isReadOnly}} + /** + {{#description}} + * {{description}} + {{/description}} + {{^description}} + * Get {{name}} + {{/description}} + {{#minimum}} + * minimum: {{minimum}} + {{/minimum}} + {{#maximum}} + * maximum: {{maximum}} + {{/maximum}} + * @return {{name}} + **/ +{{#required}} +{{#isNullable}} + @javax.annotation.Nullable +{{/isNullable}} +{{/required}} +{{^required}} + @javax.annotation.Nullable +{{/required}} +{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} @ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") +{{#vendorExtensions.x-extra-annotation}} + {{{vendorExtensions.x-extra-annotation}}} +{{/vendorExtensions.x-extra-annotation}} +{{#vendorExtensions.x-is-jackson-optional-nullable}} + {{!unannotated, Jackson would pick this up automatically and add it *in addition* to the _JsonNullable getter field}} + @JsonIgnore +{{/vendorExtensions.x-is-jackson-optional-nullable}} +{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#jackson}}{{> jackson_annotations}}{{/jackson}}{{/vendorExtensions.x-is-jackson-optional-nullable}} + public {{{datatypeWithEnum}}} {{getter}}() { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#isReadOnly}}{{! A readonly attribute doesn't have setter => jackson will set null directly if explicitly returned by API, so make sure we have an empty JsonNullable}} + if ({{name}} == null) { + {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + } + {{/isReadOnly}} + return {{name}}.orElse(null); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + return {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + + {{#vendorExtensions.x-is-jackson-optional-nullable}} +{{> jackson_annotations}} + public JsonNullable<{{{datatypeWithEnum}}}> {{getter}}_JsonNullable() { + return {{name}}; + } + {{/vendorExtensions.x-is-jackson-optional-nullable}}{{#vendorExtensions.x-is-jackson-optional-nullable}} + @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) + {{#isReadOnly}}private{{/isReadOnly}}{{^isReadOnly}}public{{/isReadOnly}} void {{setter}}_JsonNullable(JsonNullable<{{{datatypeWithEnum}}}> {{name}}) { + {{! For getters/setters that have name differing from attribute name, we must include setter (albeit private) for jackson to be able to set the attribute}} + this.{{name}} = {{name}}; + } + {{/vendorExtensions.x-is-jackson-optional-nullable}} + + {{^isReadOnly}} + public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-enum-as-string}} + if (!{{{nameInSnakeCase}}}_VALUES.contains({{name}})) { + throw new IllegalArgumentException({{name}} + " is invalid. Possible values for {{name}}: " + String.join(", ", {{{nameInSnakeCase}}}_VALUES)); + } + + {{/vendorExtensions.x-enum-as-string}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isReadOnly}} + + {{/vars}} +{{>libraries/native/additional_properties}} + /** + * Return true if this {{name}} object is equal to o. + */ + @Override + public boolean equals(Object o) { + {{#useReflectionEqualsHashCode}} + return EqualsBuilder.reflectionEquals(this, o, false, null, true); + {{/useReflectionEqualsHashCode}} + {{^useReflectionEqualsHashCode}} + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + }{{#hasVars}} + {{classname}} {{classVarName}} = ({{classname}}) o; + return {{#vars}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{#hasMore}} && + {{/hasMore}}{{/vars}}{{#additionalPropertiesType}}&& + Objects.equals(this.additionalProperties, {{classVarName}}.additionalProperties){{/additionalPropertiesType}}{{#parent}} && + super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} + return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}} + {{/useReflectionEqualsHashCode}} + } + + @Override + public int hashCode() { + {{#useReflectionEqualsHashCode}} + return HashCodeBuilder.reflectionHashCode(this); + {{/useReflectionEqualsHashCode}} + {{^useReflectionEqualsHashCode}} + return Objects.hash({{#vars}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{#hasMore}}, {{/hasMore}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}{{#additionalPropertiesType}}, additionalProperties{{/additionalPropertiesType}}); + {{/useReflectionEqualsHashCode}} + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class {{classname}} {\n"); + {{#parent}} + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + {{/parent}} + {{#vars}} + sb.append(" {{name}}: ").append(toIndentedString({{name}})).append("\n"); + {{/vars}} + {{#additionalPropertiesType}} + sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n"); + {{/additionalPropertiesType}} + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + +{{#parcelableModel}} + + public void writeToParcel(Parcel out, int flags) { +{{#model}} +{{#isArrayModel}} + out.writeList(this); +{{/isArrayModel}} +{{^isArrayModel}} +{{#parent}} + super.writeToParcel(out, flags); +{{/parent}} +{{#vars}} + out.writeValue({{name}}); +{{/vars}} +{{/isArrayModel}} +{{/model}} + } + + {{classname}}(Parcel in) { +{{#isArrayModel}} + in.readTypedList(this, {{arrayModelType}}.CREATOR); +{{/isArrayModel}} +{{^isArrayModel}} +{{#parent}} + super(in); +{{/parent}} +{{#vars}} +{{#isPrimitiveType}} + {{name}} = ({{{datatypeWithEnum}}})in.readValue(null); +{{/isPrimitiveType}} +{{^isPrimitiveType}} + {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader()); +{{/isPrimitiveType}} +{{/vars}} +{{/isArrayModel}} + } + + public int describeContents() { + return 0; + } + + public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() { + public {{classname}} createFromParcel(Parcel in) { +{{#model}} +{{#isArrayModel}} + {{classname}} result = new {{classname}}(); + result.addAll(in.readArrayList({{arrayModelType}}.class.getClassLoader())); + return result; +{{/isArrayModel}} +{{^isArrayModel}} + return new {{classname}}(in); +{{/isArrayModel}} +{{/model}} + } + public {{classname}}[] newArray(int size) { + return new {{classname}}[size]; + } + }; +{{/parcelableModel}} +{{#discriminator}} +static { + // Initialize and register the discriminator mappings. + Map> mappings = new HashMap>(); + {{#mappedModels}} + mappings.put("{{mappingName}}", {{modelName}}.class); + {{/mappedModels}} + mappings.put("{{name}}", {{classname}}.class); + JSON.registerDiscriminator({{classname}}.class, "{{propertyBaseName}}", mappings); +} +{{/discriminator}} +} diff --git a/libraries/native/pom.mustache b/libraries/native/pom.mustache index ad2a10ae96f..a6445406227 100644 --- a/libraries/native/pom.mustache +++ b/libraries/native/pom.mustache @@ -193,6 +193,13 @@ jackson-databind-nullable ${jackson-databind-nullable-version} + {{#threetenbp}} + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${threetenbp-version} + + {{/threetenbp}} @@ -207,6 +214,13 @@ provided + + + javax.ws.rs + javax.ws.rs-api + ${javax-ws-rs-api-version} + + junit @@ -215,14 +229,19 @@ test + UTF-8 1.5.22 11 11 - 2.9.9 + 2.10.4 0.2.1 1.3.2 + 2.1.1 + {{#threetenbp}} + 2.9.10 + {{/threetenbp}} 4.13.1 From 163c39e9076b0a860a762211f167fdff471dd9a9 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Sun, 18 Oct 2020 20:07:33 -0700 Subject: [PATCH 318/370] Changes lingering isMapContainer to isMap (#7747) * Changes lingering isMapContainer to isMap * Adds ensure up to date updates --- libraries/native/pojo.mustache | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/native/pojo.mustache b/libraries/native/pojo.mustache index 9786b9e10b9..b47b3bffbef 100644 --- a/libraries/native/pojo.mustache +++ b/libraries/native/pojo.mustache @@ -146,7 +146,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{/vendorExtensions.x-is-jackson-optional-nullable}} } {{/isListContainer}} - {{#isMapContainer}} + {{#isMap}} public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { {{#vendorExtensions.x-is-jackson-optional-nullable}} @@ -170,7 +170,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE return this; {{/vendorExtensions.x-is-jackson-optional-nullable}} } - {{/isMapContainer}} + {{/isMap}} {{/isReadOnly}} /** From ccc8613d2d996e3248a1af2eda797e9f776d9c37 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Sun, 18 Oct 2020 21:58:59 -0700 Subject: [PATCH 319/370] Unifies naming for isArray in Schema class properties (#7691) * Updates key java files * Adds all lingering isArray fixes * Adds two files * Reverts two cs files * Fixes lingering isListContainer + isArrayModel references * Some ensure up to date updates --- libraries/jersey2/pojo.mustache | 28 +++++++++++++-------------- libraries/microprofile/pojo.mustache | 12 ++++++------ libraries/native/pojo.mustache | 28 +++++++++++++-------------- libraries/okhttp-gson/api.mustache | 2 +- libraries/webclient/api.mustache | 6 +++--- libraries/webclient/api_test.mustache | 2 +- pojo.mustache | 28 +++++++++++++-------------- 7 files changed, 53 insertions(+), 53 deletions(-) diff --git a/libraries/jersey2/pojo.mustache b/libraries/jersey2/pojo.mustache index 6ac2083704a..3ee4fcffd1c 100644 --- a/libraries/jersey2/pojo.mustache +++ b/libraries/jersey2/pojo.mustache @@ -121,7 +121,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{/vendorExtensions.x-is-jackson-optional-nullable}} return this; } - {{#isListContainer}} + {{#isArray}} public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { {{#vendorExtensions.x-is-jackson-optional-nullable}} @@ -145,7 +145,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE return this; {{/vendorExtensions.x-is-jackson-optional-nullable}} } - {{/isListContainer}} + {{/isArray}} {{#isMap}} public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { @@ -342,25 +342,25 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE public void writeToParcel(Parcel out, int flags) { {{#model}} -{{#isArrayModel}} +{{#isArray}} out.writeList(this); -{{/isArrayModel}} -{{^isArrayModel}} +{{/isArray}} +{{^isArray}} {{#parent}} super.writeToParcel(out, flags); {{/parent}} {{#vars}} out.writeValue({{name}}); {{/vars}} -{{/isArrayModel}} +{{/isArray}} {{/model}} } {{classname}}(Parcel in) { -{{#isArrayModel}} +{{#isArray}} in.readTypedList(this, {{arrayModelType}}.CREATOR); -{{/isArrayModel}} -{{^isArrayModel}} +{{/isArray}} +{{^isArray}} {{#parent}} super(in); {{/parent}} @@ -372,7 +372,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader()); {{/isPrimitiveType}} {{/vars}} -{{/isArrayModel}} +{{/isArray}} } public int describeContents() { @@ -382,14 +382,14 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() { public {{classname}} createFromParcel(Parcel in) { {{#model}} -{{#isArrayModel}} +{{#isArray}} {{classname}} result = new {{classname}}(); result.addAll(in.readArrayList({{arrayModelType}}.class.getClassLoader())); return result; -{{/isArrayModel}} -{{^isArrayModel}} +{{/isArray}} +{{^isArray}} return new {{classname}}(in); -{{/isArrayModel}} +{{/isArray}} {{/model}} } public {{classname}}[] newArray(int size) { diff --git a/libraries/microprofile/pojo.mustache b/libraries/microprofile/pojo.mustache index c250bd2a36d..24e6e7e7d05 100644 --- a/libraries/microprofile/pojo.mustache +++ b/libraries/microprofile/pojo.mustache @@ -76,16 +76,16 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}}{{#serializ {{#vendorExtensions.x-extra-annotation}} {{{vendorExtensions.x-extra-annotation}}} {{/vendorExtensions.x-extra-annotation}} -{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} {{#withXml}}{{#isEnum}}{{^isListContainer}}{{^isMap}}public {{dataType}} {{getter}}() { +{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} {{#withXml}}{{#isEnum}}{{^isArray}}{{^isMap}}public {{dataType}} {{getter}}() { if ({{name}} == null) { return null; } return {{name}}.value(); - }{{/isMap}}{{/isListContainer}}{{/isEnum}}{{/withXml}}{{^withXml}}{{#isEnum}}{{^isListContainer}}{{^isMap}}public {{datatypeWithEnum}} {{getter}}() { + }{{/isMap}}{{/isArray}}{{/isEnum}}{{/withXml}}{{^withXml}}{{#isEnum}}{{^isArray}}{{^isMap}}public {{datatypeWithEnum}} {{getter}}() { return {{name}}; - }{{/isMap}}{{/isListContainer}}{{/isEnum}}{{/withXml}}{{#isEnum}}{{#isListContainer}}public {{{datatypeWithEnum}}} {{getter}}() { + }{{/isMap}}{{/isArray}}{{/isEnum}}{{/withXml}}{{#isEnum}}{{#isArray}}public {{{datatypeWithEnum}}} {{getter}}() { return {{name}}; - }{{/isListContainer}}{{/isEnum}}{{#isEnum}}{{#isMap}}public {{{datatypeWithEnum}}} {{getter}}() { + }{{/isArray}}{{/isEnum}}{{#isEnum}}{{#isMap}}public {{{datatypeWithEnum}}} {{getter}}() { return {{name}}; }{{/isMap}}{{/isEnum}}{{^isEnum}}public {{{datatypeWithEnum}}} {{getter}}() { return {{name}}; @@ -103,13 +103,13 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}}{{#serializ this.{{name}} = {{name}}; return this; } - {{#isListContainer}} + {{#isArray}} public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { this.{{name}}.add({{name}}Item); return this; } - {{/isListContainer}} + {{/isArray}} {{#isMap}} public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { diff --git a/libraries/native/pojo.mustache b/libraries/native/pojo.mustache index b47b3bffbef..544fbf16498 100644 --- a/libraries/native/pojo.mustache +++ b/libraries/native/pojo.mustache @@ -121,7 +121,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{/vendorExtensions.x-is-jackson-optional-nullable}} return this; } - {{#isListContainer}} + {{#isArray}} public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { {{#vendorExtensions.x-is-jackson-optional-nullable}} @@ -145,7 +145,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE return this; {{/vendorExtensions.x-is-jackson-optional-nullable}} } - {{/isListContainer}} + {{/isArray}} {{#isMap}} public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { @@ -317,25 +317,25 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE public void writeToParcel(Parcel out, int flags) { {{#model}} -{{#isArrayModel}} +{{#isArray}} out.writeList(this); -{{/isArrayModel}} -{{^isArrayModel}} +{{/isArray}} +{{^isArray}} {{#parent}} super.writeToParcel(out, flags); {{/parent}} {{#vars}} out.writeValue({{name}}); {{/vars}} -{{/isArrayModel}} +{{/isArray}} {{/model}} } {{classname}}(Parcel in) { -{{#isArrayModel}} +{{#isArray}} in.readTypedList(this, {{arrayModelType}}.CREATOR); -{{/isArrayModel}} -{{^isArrayModel}} +{{/isArray}} +{{^isArray}} {{#parent}} super(in); {{/parent}} @@ -347,7 +347,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader()); {{/isPrimitiveType}} {{/vars}} -{{/isArrayModel}} +{{/isArray}} } public int describeContents() { @@ -357,14 +357,14 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() { public {{classname}} createFromParcel(Parcel in) { {{#model}} -{{#isArrayModel}} +{{#isArray}} {{classname}} result = new {{classname}}(); result.addAll(in.readArrayList({{arrayModelType}}.class.getClassLoader())); return result; -{{/isArrayModel}} -{{^isArrayModel}} +{{/isArray}} +{{^isArray}} return new {{classname}}(in); -{{/isArrayModel}} +{{/isArray}} {{/model}} } public {{classname}}[] newArray(int size) { diff --git a/libraries/okhttp-gson/api.mustache b/libraries/okhttp-gson/api.mustache index 821972f3391..d5158d55273 100644 --- a/libraries/okhttp-gson/api.mustache +++ b/libraries/okhttp-gson/api.mustache @@ -166,7 +166,7 @@ public class {{classname}} { ExecutableValidator executableValidator = factory.getValidator().forExecutables(); Object[] parameterValues = { {{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}} }; - Method method = this.getClass().getMethod("{{operationId}}WithHttpInfo"{{#allParams}}, {{#isListContainer}}java.util.List{{/isListContainer}}{{#isMap}}java.util.Map{{/isMap}}{{^isListContainer}}{{^isMap}}{{{dataType}}}{{/isMap}}{{/isListContainer}}.class{{/allParams}}); + Method method = this.getClass().getMethod("{{operationId}}WithHttpInfo"{{#allParams}}, {{#isArray}}java.util.List{{/isArray}}{{#isMap}}java.util.Map{{/isMap}}{{^isArray}}{{^isMap}}{{{dataType}}}{{/isMap}}{{/isArray}}.class{{/allParams}}); Set> violations = executableValidator.validateParameters(this, method, parameterValues); diff --git a/libraries/webclient/api.mustache b/libraries/webclient/api.mustache index a8077006c8f..a62a10c0c12 100644 --- a/libraries/webclient/api.mustache +++ b/libraries/webclient/api.mustache @@ -62,7 +62,7 @@ public class {{classname}} { * @see {{summary}} Documentation {{/externalDocs}} */ - public {{#returnType}}{{#isListContainer}}Flux<{{{returnBaseType}}}>{{/isListContainer}}{{^isListContainer}}Mono<{{{returnType}}}>{{/isListContainer}} {{/returnType}}{{^returnType}}Mono {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws WebClientResponseException { + public {{#returnType}}{{#isArray}}Flux<{{{returnBaseType}}}>{{/isArray}}{{^isArray}}Mono<{{{returnType}}}>{{/isArray}} {{/returnType}}{{^returnType}}Mono {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws WebClientResponseException { Object postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}} {{#required}} @@ -124,8 +124,8 @@ public class {{classname}} { String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; - {{#returnType}}ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}> localVarReturnType = new ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference localVarReturnType = new ParameterizedTypeReference() {};{{/returnType}} - return apiClient.{{#isListContainer}}invokeFluxAPI{{/isListContainer}}{{^isListContainer}}invokeAPI{{/isListContainer}}("{{{path}}}", HttpMethod.{{httpMethod}}, pathParams, queryParams, postBody, headerParams, cookieParams, formParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType); + {{#returnType}}ParameterizedTypeReference<{{#isArray}}{{{returnBaseType}}}{{/isArray}}{{^isArray}}{{{returnType}}}{{/isArray}}> localVarReturnType = new ParameterizedTypeReference<{{#isArray}}{{{returnBaseType}}}{{/isArray}}{{^isArray}}{{{returnType}}}{{/isArray}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference localVarReturnType = new ParameterizedTypeReference() {};{{/returnType}} + return apiClient.{{#isArray}}invokeFluxAPI{{/isArray}}{{^isArray}}invokeAPI{{/isArray}}("{{{path}}}", HttpMethod.{{httpMethod}}, pathParams, queryParams, postBody, headerParams, cookieParams, formParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType); } {{/operation}} } diff --git a/libraries/webclient/api_test.mustache b/libraries/webclient/api_test.mustache index 1b730bf43a7..edd2c06a70b 100644 --- a/libraries/webclient/api_test.mustache +++ b/libraries/webclient/api_test.mustache @@ -33,7 +33,7 @@ public class {{classname}}Test { {{#allParams}} {{{dataType}}} {{paramName}} = null; {{/allParams}} - {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#isListContainer}}.collectList().block(){{/isListContainer}}{{^isListContainer}}.block(){{/isListContainer}}; + {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#isArray}}.collectList().block(){{/isArray}}{{^isArray}}.block(){{/isArray}}; // TODO: test validations } diff --git a/pojo.mustache b/pojo.mustache index a442eb4e182..17d0c1b5a10 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -104,7 +104,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{^vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = {{name}};{{/vendorExtensions.x-is-jackson-optional-nullable}} return this; } - {{#isListContainer}} + {{#isArray}} public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { {{#vendorExtensions.x-is-jackson-optional-nullable}} @@ -128,7 +128,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE return this; {{/vendorExtensions.x-is-jackson-optional-nullable}} } - {{/isListContainer}} + {{/isArray}} {{#isMap}} public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { @@ -312,25 +312,25 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE public void writeToParcel(Parcel out, int flags) { {{#model}} -{{#isArrayModel}} +{{#isArray}} out.writeList(this); -{{/isArrayModel}} -{{^isArrayModel}} +{{/isArray}} +{{^isArray}} {{#parent}} super.writeToParcel(out, flags); {{/parent}} {{#vars}} out.writeValue({{name}}); {{/vars}} -{{/isArrayModel}} +{{/isArray}} {{/model}} } {{classname}}(Parcel in) { -{{#isArrayModel}} +{{#isArray}} in.readTypedList(this, {{arrayModelType}}.CREATOR); -{{/isArrayModel}} -{{^isArrayModel}} +{{/isArray}} +{{^isArray}} {{#parent}} super(in); {{/parent}} @@ -342,7 +342,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader()); {{/isPrimitiveType}} {{/vars}} -{{/isArrayModel}} +{{/isArray}} } public int describeContents() { @@ -352,14 +352,14 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() { public {{classname}} createFromParcel(Parcel in) { {{#model}} -{{#isArrayModel}} +{{#isArray}} {{classname}} result = new {{classname}}(); result.addAll(in.readArrayList({{arrayModelType}}.class.getClassLoader())); return result; -{{/isArrayModel}} -{{^isArrayModel}} +{{/isArray}} +{{^isArray}} return new {{classname}}(in); -{{/isArrayModel}} +{{/isArray}} {{/model}} } public {{classname}}[] newArray(int size) { From 667b95149c0a951162b998494dec09abd6bde348 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Tue, 20 Oct 2020 10:11:01 +0800 Subject: [PATCH 320/370] [java][jersey2] add proxy support (#7752) * add client config getter and setter * update gradle, sbt config * update client config * update samples * add code sample to set proxy --- README.mustache | 27 +++++++++++ libraries/jersey2/ApiClient.mustache | 60 ++++++++++++++++++------- libraries/jersey2/build.gradle.mustache | 1 + libraries/jersey2/build.sbt.mustache | 1 + libraries/jersey2/pom.mustache | 5 +++ 5 files changed, 77 insertions(+), 17 deletions(-) diff --git a/README.mustache b/README.mustache index 5f2e5943a49..1ff5731a035 100644 --- a/README.mustache +++ b/README.mustache @@ -73,6 +73,33 @@ Then manually install the following JARs: - `target/{{{artifactId}}}-{{{artifactVersion}}}.jar` - `target/lib/*.jar` +{{#jersey2}} +## Usage + +To add a HTTP proxy for the API client, use `ClientConfig`: +```java +{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}} +import org.glassfish.jersey.apache.connector.ApacheConnectorProvider; +import org.glassfish.jersey.client.ClientConfig; +import org.glassfish.jersey.client.ClientProperties; +import {{{invokerPackage}}}.*; +import {{{package}}}.{{{classname}}}; + +... + +ApiClient defaultClient = Configuration.getDefaultApiClient(); +ClientConfig clientConfig = defaultClient.getClientConfig(); +clientConfig.connectorProvider(new ApacheConnectorProvider()); +clientConfig.property(ClientProperties.PROXY_URI, "http://proxy_url_here"); +clientConfig.property(ClientProperties.PROXY_USERNAME, "proxy_username"); +clientConfig.property(ClientProperties.PROXY_PASSWORD, "proxy_password"); +defaultClient.setClientConfig(clientConfig); + +{{{classname}}} apiInstance = new {{{classname}}}(defaultClient); +{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} +``` + +{{/jersey2}} ## Getting Started Please follow the [installation](#installation) instruction and execute the following Java code: diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 4ccf4e9cb09..713332e20b7 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -156,6 +156,7 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { protected Map operationServerIndex = new HashMap(); protected Map> operationServerVariables = new HashMap>(); protected boolean debugging = false; + protected ClientConfig clientConfig; protected int connectionTimeout = 0; private int readTimeout = 0; @@ -182,7 +183,7 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { */ public ApiClient(Map authMap) { json = new JSON(); - httpClient = buildHttpClient(debugging); + httpClient = buildHttpClient(); this.dateFormat = new RFC3339DateFormat(); @@ -562,6 +563,27 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { return this; } + /** + * Gets the client config. + * @return Client config + */ + public ClientConfig getClientConfig() { + return clientConfig; + } + + /** + * Set the client config. + * + * @param clientConfig Set the client config + * @return API client + */ + public ApiClient setClientConfig(ClientConfig clientConfig) { + this.clientConfig = clientConfig; + // Rebuild HTTP Client according to the new "clientConfig" value. + this.httpClient = buildHttpClient(); + return this; + } + /** * Check that whether debugging is enabled for this API client. * @return True if debugging is switched on @@ -579,7 +601,7 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { public ApiClient setDebugging(boolean debugging) { this.debugging = debugging; // Rebuild HTTP Client according to the new "debugging" value. - this.httpClient = buildHttpClient(debugging); + this.httpClient = buildHttpClient(); return this; } @@ -1210,11 +1232,26 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { /** * Build the Client used to make HTTP requests. - * @param debugging Debug setting * @return Client */ - protected Client buildHttpClient(boolean debugging) { - final ClientConfig clientConfig = new ClientConfig(); + protected Client buildHttpClient() { + // use the default client config if not yet initialized + if (clientConfig == null) { + clientConfig = getDefaultClientConfig(); + } + + ClientBuilder clientBuilder = ClientBuilder.newBuilder(); + customizeClientBuilder(clientBuilder); + clientBuilder = clientBuilder.withConfig(clientConfig); + return clientBuilder.build(); + } + + /** + * Get the default client config. + * @return Client config + */ + public ClientConfig getDefaultClientConfig() { + ClientConfig clientConfig = new ClientConfig(); clientConfig.register(MultiPartFeature.class); clientConfig.register(json); clientConfig.register(JacksonFeature.class); @@ -1235,19 +1272,8 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { // suppress warnings for payloads with DELETE calls: java.util.logging.Logger.getLogger("org.glassfish.jersey.client").setLevel(java.util.logging.Level.SEVERE); } - performAdditionalClientConfiguration(clientConfig); - ClientBuilder clientBuilder = ClientBuilder.newBuilder(); - customizeClientBuilder(clientBuilder); - clientBuilder = clientBuilder.withConfig(clientConfig); - return clientBuilder.build(); - } - /** - * Perform additional configuration of the API client. - * This method can be overriden to customize the API client. - */ - protected void performAdditionalClientConfiguration(ClientConfig clientConfig) { - // No-op extension point + return clientConfig; } /** diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index bcbfba97447..392c3fda0b2 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -151,6 +151,7 @@ dependencies { compile "org.glassfish.jersey.inject:jersey-hk2:$jersey_version" compile "org.glassfish.jersey.media:jersey-media-multipart:$jersey_version" compile "org.glassfish.jersey.media:jersey-media-json-jackson:$jersey_version" + compile "org.glassfish.jersey.connectors:jersey-apache-connector:$jersey_version" compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" diff --git a/libraries/jersey2/build.sbt.mustache b/libraries/jersey2/build.sbt.mustache index d4f17f702c2..42afc6016ba 100644 --- a/libraries/jersey2/build.sbt.mustache +++ b/libraries/jersey2/build.sbt.mustache @@ -14,6 +14,7 @@ lazy val root = (project in file(".")). "org.glassfish.jersey.inject" % "jersey-hk2" % "2.27",{{/supportJava6}} "org.glassfish.jersey.media" % "jersey-media-multipart" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.27"{{/supportJava6}}, "org.glassfish.jersey.media" % "jersey-media-json-jackson" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.27"{{/supportJava6}}, + "org.glassfish.jersey.connectors" % "jersey-apache-connector" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.27"{{/supportJava6}}, "com.fasterxml.jackson.core" % "jackson-core" % "2.10.4" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.4" % "compile", "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.4" % "compile", diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 907c3317664..293356545b0 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -381,6 +381,11 @@ ${javax-annotation-version} provided + + org.glassfish.jersey.connectors + jersey-apache-connector + ${jersey-version} + junit From 0e1408e147a9df60a4085fa261dcaf1b9da7c910 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 21 Oct 2020 21:29:53 +0800 Subject: [PATCH 321/370] [Java][webclient] fix missing dependencies in build.gradle (#7777) * fix build.gradle in java webclient * update junit version in samples --- libraries/webclient/build.gradle.mustache | 177 ++++++++++++++++++++++ libraries/webclient/pom.mustache | 43 +++--- pom.mustache | 2 +- 3 files changed, 200 insertions(+), 22 deletions(-) create mode 100644 libraries/webclient/build.gradle.mustache diff --git a/libraries/webclient/build.gradle.mustache b/libraries/webclient/build.gradle.mustache new file mode 100644 index 00000000000..f6c8ac6438c --- /dev/null +++ b/libraries/webclient/build.gradle.mustache @@ -0,0 +1,177 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + maven { url "https://repo1.maven.org/maven2" } + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + } +} + +repositories { + maven { url "https://repo1.maven.org/maven2" } + jcenter() +} + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + } + + compileOptions { + {{#supportJava6}} + sourceCompatibility JavaVersion.VERSION_1_6 + targetCompatibility JavaVersion.VERSION_1_6 + {{/supportJava6}} + {{^supportJava6}} + {{#java8}} + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + {{/java8}} + {{/supportJava6}} + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided 'javax.annotation:jsr250-api:1.0' + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven' + + {{#supportJava6}} + sourceCompatibility = JavaVersion.VERSION_1_6 + targetCompatibility = JavaVersion.VERSION_1_6 + {{/supportJava6}} + {{^supportJava6}} + {{#java8}} + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + {{/java8}} + {{^java8}} + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + {{/java8}} + {{/supportJava6}} + + install { + repositories.mavenInstaller { + pom.artifactId = '{{artifactId}}' + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } + + task sourcesJar(type: Jar, dependsOn: classes) { + classifier = 'sources' + from sourceSets.main.allSource + } + + task javadocJar(type: Jar, dependsOn: javadoc) { + classifier = 'javadoc' + from javadoc.destinationDir + } + + artifacts { + archives sourcesJar + archives javadocJar + } +} + +ext { + swagger_annotations_version = "1.6.2" + spring_web_version = "5.0.16.RELEASE" + jackson_version = "2.11.3" + jackson_databind_version = "2.11.3" + {{#openApiNullable}} + jackson_databind_nullable_version = "0.2.1" + {{/openApiNullable}} + javax_annotation_version = "1.3.2" + reactor_version = "3.3.10.RELEASE" + reactor_netty_version = "0.7.15.RELEASE" + jodatime_version = "2.9.9" + junit_version = "4.13.1" +} + +dependencies { + compile "io.swagger:swagger-annotations:$swagger_annotations_version" + compile "com.google.code.findbugs:jsr305:3.0.2" + compile "io.projectreactor:reactor-core:$reactor_version" + compile "org.springframework:spring-webflux:$spring_web_version" + compile "io.projectreactor.ipc:reactor-netty:$reactor_netty_version" + compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + {{#openApiNullable}} + compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} + {{#joda}} + compile "joda-time:joda-time:$jodatime_version" + {{/joda}} + {{#java8}} + compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{/java8}} + {{^java8}} + compile "com.brsanthu:migbase64:2.2" + {{/java8}} + compile "javax.annotation:javax.annotation-api:$javax_annotation_version" + testCompile "junit:junit:$junit_version" +} + diff --git a/libraries/webclient/pom.mustache b/libraries/webclient/pom.mustache index eadc109da4a..5aaeec6823d 100644 --- a/libraries/webclient/pom.mustache +++ b/libraries/webclient/pom.mustache @@ -40,7 +40,6 @@ - org.apache.maven.plugins maven-compiler-plugin @@ -114,23 +113,23 @@ {{/openApiNullable}} {{#java8}} - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - ${jackson-version} - + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + {{/java8}} {{#joda}} - - com.fasterxml.jackson.datatype - jackson-datatype-joda - ${jackson-version} - - - joda-time - joda-time - ${jodatime-version} - + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + + joda-time + joda-time + ${jodatime-version} + {{/joda}} javax.annotation @@ -149,15 +148,17 @@ UTF-8 - 1.5.22 + 1.6.2 5.0.16.RELEASE - 2.10.3 - 2.10.3 + 2.11.3 + 2.11.3 + {{#openApiNullable}} 0.2.1 + {{/openApiNullable}} 1.3.2 4.13.1 - 3.1.8.RELEASE - 0.7.8.RELEASE + 3.3.10.RELEASE + 0.7.15.RELEASE {{#joda}} 2.9.9 {{/joda}} diff --git a/pom.mustache b/pom.mustache index 5cae3afa36d..75b0e9ef5c6 100644 --- a/pom.mustache +++ b/pom.mustache @@ -395,6 +395,6 @@ {{/threetenbp}} 1.3.2 1.0.0 - 4.13 + 4.13.1 From 7852384200f05926ee884a8b0f2d5db986b3b30d Mon Sep 17 00:00:00 2001 From: Justin Black Date: Fri, 6 Nov 2020 19:04:12 -0800 Subject: [PATCH 322/370] Removes secondaryParam and hasMore (#7882) * Removes secondaryParam and hasMore * Fixes tests * Only uses bodyParam in groovy template --- README.mustache | 6 ++-- api.mustache | 8 ++--- api_doc.mustache | 8 ++--- api_test.mustache | 2 +- libraries/feign/ApiClient.mustache | 2 +- libraries/feign/README.mustache | 4 +-- libraries/feign/api.mustache | 14 ++++----- libraries/feign/api_test.mustache | 4 +-- libraries/google-api-client/api.mustache | 14 ++++----- libraries/google-api-client/api_test.mustache | 2 +- libraries/jersey2/api.mustache | 20 ++++++------- libraries/jersey2/api_doc.mustache | 12 ++++---- libraries/jersey2/api_test.mustache | 4 +-- libraries/jersey2/pojo.mustache | 12 ++++---- libraries/microprofile/api.mustache | 6 ++-- libraries/microprofile/api_test.mustache | 2 +- libraries/native/README.mustache | 6 ++-- libraries/native/api.mustache | 18 +++++------ libraries/native/api_doc.mustache | 16 +++++----- libraries/native/api_test.mustache | 2 +- libraries/native/pojo.mustache | 6 ++-- libraries/okhttp-gson/README.mustache | 6 ++-- libraries/okhttp-gson/api.mustache | 24 +++++++-------- libraries/okhttp-gson/api_doc.mustache | 10 +++---- libraries/okhttp-gson/api_test.mustache | 2 +- libraries/rest-assured/README.mustache | 4 +-- libraries/rest-assured/api.mustache | 2 +- libraries/rest-assured/api_doc.mustache | 6 ++-- libraries/resteasy/api.mustache | 8 ++--- libraries/resttemplate/api.mustache | 30 +++++++++---------- libraries/resttemplate/api_test.mustache | 2 +- libraries/retrofit/ApiClient.mustache | 2 +- libraries/retrofit/README.mustache | 4 +-- libraries/retrofit/api.mustache | 4 +-- libraries/retrofit/api_test.mustache | 2 +- libraries/retrofit2/ApiClient.mustache | 2 +- libraries/retrofit2/README.mustache | 4 +-- libraries/retrofit2/api.mustache | 4 +-- libraries/retrofit2/api_test.mustache | 2 +- libraries/retrofit2/play24/api.mustache | 4 +-- libraries/retrofit2/play25/api.mustache | 4 +-- libraries/retrofit2/play26/api.mustache | 4 +-- libraries/vertx/apiImpl.mustache | 6 ++-- libraries/vertx/rxApiImpl.mustache | 2 +- libraries/webclient/api.mustache | 12 ++++---- libraries/webclient/api_test.mustache | 2 +- pojo.mustache | 12 ++++---- 47 files changed, 166 insertions(+), 166 deletions(-) diff --git a/README.mustache b/README.mustache index 1ff5731a035..40d272ed318 100644 --- a/README.mustache +++ b/README.mustache @@ -157,7 +157,7 @@ public class {{{classname}}}Example { {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} {{/allParams}} try { - {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}});{{#returnType}} System.out.println(result);{{/returnType}} } catch (ApiException e) { System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); @@ -219,5 +219,5 @@ It's recommended to create an instance of `ApiClient` per thread in a multithrea ## Author -{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} -{{/hasMore}}{{/apis}}{{/apiInfo}} +{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}} +{{/-last}}{{/apis}}{{/apiInfo}} diff --git a/api.mustache b/api.mustache index 11fc64de646..894cb011239 100644 --- a/api.mustache +++ b/api.mustache @@ -63,7 +63,7 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set @@ -99,16 +99,16 @@ public class {{classname}} { {{/formParams}} final String[] localVarAccepts = { - {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} + {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} }; final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); final String[] localVarContentTypes = { - {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} + {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} }; final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); - String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; {{#returnType}} GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {}; diff --git a/api_doc.mustache b/api_doc.mustache index 63e7a490012..e68b9b1aef1 100644 --- a/api_doc.mustache +++ b/api_doc.mustache @@ -14,7 +14,7 @@ Method | HTTP request | Description ## {{operationId}} -> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) +> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}) {{summary}}{{#notes}} @@ -60,7 +60,7 @@ public class Example { {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} {{/allParams}} try { - {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}});{{#returnType}} System.out.println(result);{{/returnType}} } catch (ApiException e) { System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); @@ -91,8 +91,8 @@ Name | Type | Description | Notes ### HTTP request headers -- **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} -- **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} +- **Content-Type**: {{#consumes}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} +- **Accept**: {{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}{{^produces}}Not defined{{/produces}} {{#responses.0}} ### HTTP response details diff --git a/api_test.mustache b/api_test.mustache index 7011191c80a..38c58efb711 100644 --- a/api_test.mustache +++ b/api_test.mustache @@ -42,7 +42,7 @@ public class {{classname}}Test { //{{#allParams}} //{{{dataType}}} {{paramName}} = null; //{{/allParams}} - //{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + //{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); // TODO: test validations } diff --git a/libraries/feign/ApiClient.mustache b/libraries/feign/ApiClient.mustache index 48119b3d66b..691f337c7c5 100644 --- a/libraries/feign/ApiClient.mustache +++ b/libraries/feign/ApiClient.mustache @@ -75,7 +75,7 @@ public class ApiClient { auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"); {{/isApiKey}} {{#isOAuth}} - auth = new OAuth(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{#hasMore}}, {{/hasMore}}{{/scopes}}"); + auth = new OAuth(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{^-last}}, {{/-last}}{{/scopes}}"); {{/isOAuth}} } else {{/authMethods}}{ throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); diff --git a/libraries/feign/README.mustache b/libraries/feign/README.mustache index 56560172ee3..a0fac9d41df 100644 --- a/libraries/feign/README.mustache +++ b/libraries/feign/README.mustache @@ -38,6 +38,6 @@ It's recommended to create an instance of `ApiClient` per thread in a multithrea ## Author -{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} -{{/hasMore}}{{/apis}}{{/apiInfo}} +{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}} +{{/-last}}{{/apis}}{{/apiInfo}} diff --git a/libraries/feign/api.mustache b/libraries/feign/api.mustache index cff48fcd2e4..f6319c5da5a 100644 --- a/libraries/feign/api.mustache +++ b/libraries/feign/api.mustache @@ -35,14 +35,14 @@ public interface {{classname}} extends ApiClient.Api { * @see {{summary}} Documentation {{/externalDocs}} */ - @RequestLine("{{httpMethod}} {{{path}}}{{#hasQueryParams}}?{{/hasQueryParams}}{{#queryParams}}{{baseName}}={{=<% %>=}}{<%paramName%>}<%={{ }}=%>{{#hasMore}}&{{/hasMore}}{{/queryParams}}") + @RequestLine("{{httpMethod}} {{{path}}}{{#hasQueryParams}}?{{/hasQueryParams}}{{#queryParams}}{{baseName}}={{=<% %>=}}{<%paramName%>}<%={{ }}=%>{{^-last}}&{{/-last}}{{/queryParams}}") @Headers({ {{#vendorExtensions.x-contentType}} "Content-Type: {{vendorExtensions.x-contentType}}", {{/vendorExtensions.x-contentType}} "Accept: {{vendorExtensions.x-accepts}}",{{#headerParams}} - "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{#hasMore}}, - {{/hasMore}}{{/headerParams}} + "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{^-last}}, + {{/-last}}{{/headerParams}} }) - {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{baseName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{baseName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); {{#hasQueryParams}} /** @@ -73,12 +73,12 @@ public interface {{classname}} extends ApiClient.Api { * @see {{summary}} Documentation {{/externalDocs}} */ - @RequestLine("{{httpMethod}} {{{path}}}?{{#queryParams}}{{baseName}}={{=<% %>=}}{<%paramName%>}<%={{ }}=%>{{#hasMore}}&{{/hasMore}}{{/queryParams}}") + @RequestLine("{{httpMethod}} {{{path}}}?{{#queryParams}}{{baseName}}={{=<% %>=}}{<%paramName%>}<%={{ }}=%>{{^-last}}&{{/-last}}{{/queryParams}}") @Headers({ {{#vendorExtensions.x-contentType}} "Content-Type: {{vendorExtensions.x-contentType}}", {{/vendorExtensions.x-contentType}} "Accept: {{vendorExtensions.x-accepts}}",{{#headerParams}} - "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{#hasMore}}, - {{/hasMore}}{{/headerParams}} + "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{^-last}}, + {{/-last}}{{/headerParams}} }) {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isQueryParam}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{baseName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}, {{/isQueryParam}}{{/allParams}}@QueryMap(encoded=true) Map queryParams); diff --git a/libraries/feign/api_test.mustache b/libraries/feign/api_test.mustache index bcc14a987c6..b24c9327129 100644 --- a/libraries/feign/api_test.mustache +++ b/libraries/feign/api_test.mustache @@ -36,7 +36,7 @@ public class {{classname}}Test { {{#allParams}} {{{dataType}}} {{paramName}} = null; {{/allParams}} - // {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + // {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); // TODO: test validations } @@ -59,7 +59,7 @@ public class {{classname}}Test { {{/allParams}} {{classname}}.{{operationIdCamelCase}}QueryParams queryParams = new {{classname}}.{{operationIdCamelCase}}QueryParams() {{#queryParams}} - .{{paramName}}(null){{^hasMore}};{{/hasMore}} + .{{paramName}}(null){{#-last}};{{/-last}} {{/queryParams}} // {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{^isQueryParam}}{{paramName}}, {{/isQueryParam}}{{/allParams}}queryParams); diff --git a/libraries/google-api-client/api.mustache b/libraries/google-api-client/api.mustache index 2c13f4eb011..2cd0f49badd 100644 --- a/libraries/google-api-client/api.mustache +++ b/libraries/google-api-client/api.mustache @@ -56,8 +56,8 @@ public class {{classname}} { {{/externalDocs}} **/ - public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws IOException { - {{#returnType}}HttpResponse response = {{/returnType}}{{operationId}}ForHttpResponse({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws IOException { + {{#returnType}}HttpResponse response = {{/returnType}}{{operationId}}ForHttpResponse({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});{{#returnType}} TypeReference<{{{returnType}}}> typeRef = new TypeReference<{{{returnType}}}>() {}; return apiClient.getObjectMapper().readValue(response.getContent(), typeRef);{{/returnType}} } @@ -75,13 +75,13 @@ public class {{classname}} { {{/externalDocs}} **/ - public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#bodyParam}}{{^required}}{{{dataType}}} {{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}Map params) throws IOException { - {{#returnType}}HttpResponse response = {{/returnType}}{{operationId}}ForHttpResponse({{#bodyParam}}{{^required}}{{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}params);{{#returnType}} + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#bodyParam}}{{^required}}{{{dataType}}} {{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}Map params) throws IOException { + {{#returnType}}HttpResponse response = {{/returnType}}{{operationId}}ForHttpResponse({{#bodyParam}}{{^required}}{{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}params);{{#returnType}} TypeReference<{{{returnType}}}> typeRef = new TypeReference<{{{returnType}}}>() {}; return apiClient.getObjectMapper().readValue(response.getContent(), typeRef);{{/returnType}} } - public HttpResponse {{operationId}}ForHttpResponse({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws IOException { + public HttpResponse {{operationId}}ForHttpResponse({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws IOException { {{#allParams}}{{#required}}// verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { throw new IllegalArgumentException("Missing the required parameter '{{paramName}}' when calling {{operationId}}"); @@ -112,7 +112,7 @@ public class {{classname}} { return apiClient.getHttpRequestFactory().buildRequest(HttpMethods.{{httpMethod}}, genericUrl, content).execute(); }{{#bodyParam}} - public HttpResponse {{operationId}}ForHttpResponse({{#allParams}}{{#isBodyParam}}java.io.InputStream {{paramName}}{{/isBodyParam}}{{^isBodyParam}}{{{dataType}}} {{paramName}}{{/isBodyParam}}{{#hasMore}}, {{/hasMore}}{{/allParams}}, String mediaType) throws IOException { + public HttpResponse {{operationId}}ForHttpResponse({{#allParams}}{{#isBodyParam}}java.io.InputStream {{paramName}}{{/isBodyParam}}{{^isBodyParam}}{{{dataType}}} {{paramName}}{{/isBodyParam}}{{^-last}}, {{/-last}}{{/allParams}}, String mediaType) throws IOException { {{#allParams}}{{#required}}// verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { throw new IllegalArgumentException("Missing the required parameter '{{paramName}}' when calling {{operationId}}"); @@ -145,7 +145,7 @@ public class {{classname}} { return apiClient.getHttpRequestFactory().buildRequest(HttpMethods.{{httpMethod}}, genericUrl, content).execute(); }{{/bodyParam}} - public HttpResponse {{operationId}}ForHttpResponse({{#bodyParam}}{{^required}}{{{dataType}}} {{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}Map params) throws IOException { + public HttpResponse {{operationId}}ForHttpResponse({{#bodyParam}}{{^required}}{{{dataType}}} {{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}Map params) throws IOException { {{#allParams}}{{#required}}// verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { throw new IllegalArgumentException("Missing the required parameter '{{paramName}}' when calling {{operationId}}"); diff --git a/libraries/google-api-client/api_test.mustache b/libraries/google-api-client/api_test.mustache index 365106fbedf..56b7c1897d1 100644 --- a/libraries/google-api-client/api_test.mustache +++ b/libraries/google-api-client/api_test.mustache @@ -37,7 +37,7 @@ public class {{classname}}Test { {{#allParams}} {{{dataType}}} {{paramName}} = null; {{/allParams}} - {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); // TODO: test validations } diff --git a/libraries/jersey2/api.mustache b/libraries/jersey2/api.mustache index 5fcfb9b19bb..666430c834e 100644 --- a/libraries/jersey2/api.mustache +++ b/libraries/jersey2/api.mustache @@ -81,8 +81,8 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { - {{#returnType}}return {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#returnType}}.getData(){{/returnType}}; + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + {{#returnType}}return {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}){{#returnType}}.getData(){{/returnType}}; } {{/vendorExtensions.x-group-parameters}} @@ -115,7 +115,7 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set @@ -150,16 +150,16 @@ public class {{classname}} { {{/formParams}} final String[] localVarAccepts = { - {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} + {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} }; final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); final String[] localVarContentTypes = { - {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} + {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} }; final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); - String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; {{#returnType}} GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {}; @@ -176,7 +176,7 @@ public class {{classname}} { private {{#isRequired}}final {{/isRequired}}{{{dataType}}} {{paramName}}; {{/allParams}} - private API{{operationId}}Request({{#pathParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}) { + private API{{operationId}}Request({{#pathParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}) { {{#pathParams}} this.{{paramName}} = {{paramName}}; {{/pathParams}} @@ -236,7 +236,7 @@ public class {{classname}} { @Deprecated {{/isDeprecated}} public ApiResponse<{{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> executeWithHttpInfo() throws ApiException { - return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); } } @@ -253,8 +253,8 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public API{{operationId}}Request {{operationId}}({{#pathParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}) throws ApiException { - return new API{{operationId}}Request({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}); + public API{{operationId}}Request {{operationId}}({{#pathParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}) throws ApiException { + return new API{{operationId}}Request({{#pathParams}}{{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}); } {{/vendorExtensions.x-group-parameters}} {{/operation}} diff --git a/libraries/jersey2/api_doc.mustache b/libraries/jersey2/api_doc.mustache index 0e43b4af0bd..42d951f1779 100644 --- a/libraries/jersey2/api_doc.mustache +++ b/libraries/jersey2/api_doc.mustache @@ -15,10 +15,10 @@ Method | HTTP request | Description ## {{operationId}} {{^vendorExtensions.x-group-parameters}} -> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) +> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) {{/vendorExtensions.x-group-parameters}} {{#vendorExtensions.x-group-parameters}} -> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}){{#allParams}}{{^isPathParam}}.{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}}.execute(); +> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#pathParams}}{{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}){{#allParams}}{{^isPathParam}}.{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}}.execute(); {{/vendorExtensions.x-group-parameters}} {{summary}}{{#notes}} @@ -66,10 +66,10 @@ public class Example { {{/allParams}} try { {{^vendorExtensions.x-group-parameters}} - {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}); {{/vendorExtensions.x-group-parameters}} {{#vendorExtensions.x-group-parameters}} - {{#returnType}}{{{returnType}}} result = {{/returnType}}api.{{operationId}}({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}){{#allParams}}{{^isPathParam}} + {{#returnType}}{{{returnType}}} result = {{/returnType}}api.{{operationId}}({{#pathParams}}{{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}){{#allParams}}{{^isPathParam}} .{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}} .execute(); {{/vendorExtensions.x-group-parameters}} @@ -105,8 +105,8 @@ Name | Type | Description | Notes ### HTTP request headers -- **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} -- **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} +- **Content-Type**: {{#consumes}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} +- **Accept**: {{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}{{^produces}}Not defined{{/produces}} {{#responses.0}} ### HTTP response details diff --git a/libraries/jersey2/api_test.mustache b/libraries/jersey2/api_test.mustache index 1bb19c9acb1..b6ea89f6154 100644 --- a/libraries/jersey2/api_test.mustache +++ b/libraries/jersey2/api_test.mustache @@ -41,10 +41,10 @@ public class {{classname}}Test { //{{{dataType}}} {{paramName}} = null; {{/allParams}} {{^vendorExtensions.x-group-parameters}} - //{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + //{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); {{/vendorExtensions.x-group-parameters}} {{#vendorExtensions.x-group-parameters}} - //{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}){{#allParams}}{{^isPathParam}} + //{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#pathParams}}{{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}){{#allParams}}{{^isPathParam}} // .{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}} // .execute(); {{/vendorExtensions.x-group-parameters}} diff --git a/libraries/jersey2/pojo.mustache b/libraries/jersey2/pojo.mustache index 3ee4fcffd1c..1004fa40265 100644 --- a/libraries/jersey2/pojo.mustache +++ b/libraries/jersey2/pojo.mustache @@ -268,8 +268,8 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE return false; }{{#hasVars}} {{classname}} {{classVarName}} = ({{classname}}) o; - return {{#vars}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{#hasMore}} && - {{/hasMore}}{{/vars}}{{#additionalPropertiesType}}&& + return {{#vars}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{^-last}} && + {{/-last}}{{/vars}}{{#additionalPropertiesType}}&& Objects.equals(this.additionalProperties, {{classVarName}}.additionalProperties){{/additionalPropertiesType}}{{#parent}} && super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}} @@ -282,7 +282,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE return HashCodeBuilder.reflectionHashCode(this); {{/useReflectionEqualsHashCode}} {{^useReflectionEqualsHashCode}} - return Objects.hash({{#vars}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{#hasMore}}, {{/hasMore}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}{{#additionalPropertiesType}}, additionalProperties{{/additionalPropertiesType}}); + return Objects.hash({{#vars}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}{{#additionalPropertiesType}}, additionalProperties{{/additionalPropertiesType}}); {{/useReflectionEqualsHashCode}} } @@ -297,15 +297,15 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE return false; }{{#hasVars}} {{classname}} {{classVarName}} = ({{classname}}) o; - return {{#vars}}ObjectUtils.equals(this.{{name}}, {{classVarName}}.{{name}}){{#hasMore}} && - {{/hasMore}}{{/vars}}{{#parent}} && + return {{#vars}}ObjectUtils.equals(this.{{name}}, {{classVarName}}.{{name}}){{^-last}} && + {{/-last}}{{/vars}}{{#parent}} && super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} return true;{{/hasVars}} } @Override public int hashCode() { - return ObjectUtils.hashCodeMulti({{#vars}}{{name}}{{#hasMore}}, {{/hasMore}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); + return ObjectUtils.hashCodeMulti({{#vars}}{{name}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); } {{/supportJava6}} diff --git a/libraries/microprofile/api.mustache b/libraries/microprofile/api.mustache index d481f96ea0b..b9e8dad8cef 100644 --- a/libraries/microprofile/api.mustache +++ b/libraries/microprofile/api.mustache @@ -49,12 +49,12 @@ public interface {{classname}} { @{{httpMethod}} {{#subresourceOperation}}@Path("{{{path}}}"){{/subresourceOperation}} {{#hasConsumes}} - @Consumes({ {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} }) + @Consumes({ {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} }) {{/hasConsumes}} {{#hasProduces}} - @Produces({ {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }) + @Produces({ {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} }) {{/hasProduces}} - public {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{nickname}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException, ProcessingException; + public {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{nickname}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException, ProcessingException; {{/operation}} } {{/operations}} diff --git a/libraries/microprofile/api_test.mustache b/libraries/microprofile/api_test.mustache index d2cb03f2798..e0ed40ef88b 100644 --- a/libraries/microprofile/api_test.mustache +++ b/libraries/microprofile/api_test.mustache @@ -66,7 +66,7 @@ public class {{classname}}Test { {{#allParams}} {{^isFile}}{{{dataType}}} {{paramName}} = null;{{/isFile}}{{#isFile}}org.apache.cxf.jaxrs.ext.multipart.Attachment {{paramName}} = null;{{/isFile}} {{/allParams}} - //{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + //{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); //{{#returnType}}assertNotNull(response);{{/returnType}} diff --git a/libraries/native/README.mustache b/libraries/native/README.mustache index 66924985507..0f6d46a460b 100644 --- a/libraries/native/README.mustache +++ b/libraries/native/README.mustache @@ -99,7 +99,7 @@ public class {{{classname}}}Example { {{/allParams}} try { {{^vendorExtensions.x-group-parameters}} - {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} result = {{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture result = {{/asyncNative}}{{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} result = {{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture result = {{/asyncNative}}{{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}); {{/vendorExtensions.x-group-parameters}} {{#vendorExtensions.x-group-parameters}} {{#hasParams}} @@ -174,5 +174,5 @@ However, the instances of the api clients created from the `ApiClient` are threa ## Author -{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} -{{/hasMore}}{{/apis}}{{/apiInfo}} +{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}} +{{/-last}}{{/apis}}{{/apiInfo}} diff --git a/libraries/native/api.mustache b/libraries/native/api.mustache index 75910062985..b974f790ee8 100644 --- a/libraries/native/api.mustache +++ b/libraries/native/api.mustache @@ -91,7 +91,7 @@ public class {{classname}} { {{#allParams}} {{{dataType}}} {{paramName}} = apiRequest.{{paramName}}(); {{/allParams}} - {{#returnType}}return {{/returnType}}{{^returnType}}{{#asyncNative}}return {{/asyncNative}}{{/returnType}}{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{#returnType}}return {{/returnType}}{{^returnType}}{{#asyncNative}}return {{/asyncNative}}{{/returnType}}{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); } /** @@ -115,7 +115,7 @@ public class {{classname}} { {{#allParams}} {{{dataType}}} {{paramName}} = apiRequest.{{paramName}}(); {{/allParams}} - return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); } {{/hasParams}} @@ -141,16 +141,16 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { {{^asyncNative}} - {{#returnType}}ApiResponse<{{{returnType}}}> localVarResponse = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{#returnType}}ApiResponse<{{{returnType}}}> localVarResponse = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); {{#returnType}} return localVarResponse.getData(); {{/returnType}} {{/asyncNative}} {{#asyncNative}} try { - HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); return memberVarHttpClient.sendAsync( localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()).thenComposeAsync(localVarResponse -> { @@ -196,9 +196,9 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + public {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { {{^asyncNative}} - HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); try { HttpResponse localVarResponse = memberVarHttpClient.send( localVarRequestBuilder.build(), @@ -227,7 +227,7 @@ public class {{classname}} { {{/asyncNative}} {{#asyncNative}} try { - HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); return memberVarHttpClient.sendAsync( localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()).thenComposeAsync(localVarResponse -> { @@ -260,7 +260,7 @@ public class {{classname}} { {{/asyncNative}} } - private HttpRequest.Builder {{operationId}}RequestBuilder({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + private HttpRequest.Builder {{operationId}}RequestBuilder({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { {{#allParams}} {{#required}} // verify the required parameter '{{paramName}}' is set diff --git a/libraries/native/api_doc.mustache b/libraries/native/api_doc.mustache index 603f7886480..23473757c36 100644 --- a/libraries/native/api_doc.mustache +++ b/libraries/native/api_doc.mustache @@ -16,7 +16,7 @@ Method | HTTP request | Description ## {{operationId}} {{^vendorExtensions.x-group-parameters}} -> {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) +> {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}) {{/vendorExtensions.x-group-parameters}} {{#vendorExtensions.x-group-parameters}} > {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}({{#hasParams}}{{operationId}}Request{{/hasParams}}) @@ -71,7 +71,7 @@ public class Example { {{/allParams}} try { {{^vendorExtensions.x-group-parameters}} - {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} result = {{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture result = {{/asyncNative}}{{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} result = {{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture result = {{/asyncNative}}{{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}); {{/vendorExtensions.x-group-parameters}} {{#vendorExtensions.x-group-parameters}} {{#hasParams}} @@ -121,8 +121,8 @@ Name | Type | Description | Notes ### HTTP request headers -- **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} -- **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} +- **Content-Type**: {{#consumes}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} +- **Accept**: {{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}{{^produces}}Not defined{{/produces}} {{#responses.0}} ### HTTP response details @@ -136,7 +136,7 @@ Name | Type | Description | Notes ## {{operationId}}WithHttpInfo {{^vendorExtensions.x-group-parameters}} -> {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}} {{operationId}}WithHttpInfo({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) +> {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}} {{operationId}}WithHttpInfo({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}) {{/vendorExtensions.x-group-parameters}} {{#vendorExtensions.x-group-parameters}} > {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}} {{operationId}}WithHttpInfo({{#hasParams}}{{operationId}}Request{{/hasParams}}) @@ -192,7 +192,7 @@ public class Example { {{/allParams}} try { {{^vendorExtensions.x-group-parameters}} - {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} response = apiInstance.{{{operationId}}}WithHttpInfo({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} response = apiInstance.{{{operationId}}}WithHttpInfo({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}); {{/vendorExtensions.x-group-parameters}} {{#vendorExtensions.x-group-parameters}} {{#hasParams}} @@ -253,8 +253,8 @@ Name | Type | Description | Notes ### HTTP request headers -- **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} -- **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} +- **Content-Type**: {{#consumes}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} +- **Accept**: {{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}{{^produces}}Not defined{{/produces}} {{#responses.0}} ### HTTP response details diff --git a/libraries/native/api_test.mustache b/libraries/native/api_test.mustache index dbfedfeb7b0..2f5ffae22c4 100644 --- a/libraries/native/api_test.mustache +++ b/libraries/native/api_test.mustache @@ -43,7 +43,7 @@ public class {{classname}}Test { {{/allParams}} {{^vendorExtensions.x-group-parameters}} {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} response = {{/returnType}} - {{^returnType}}{{#asyncNative}}CompletableFuture response = {{/asyncNative}}{{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{^returnType}}{{#asyncNative}}CompletableFuture response = {{/asyncNative}}{{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); {{/vendorExtensions.x-group-parameters}} {{#vendorExtensions.x-group-parameters}}{{#hasParams}} {{classname}}.API{{operationId}}Request request = {{classname}}.API{{operationId}}Request.newBuilder(){{#allParams}} diff --git a/libraries/native/pojo.mustache b/libraries/native/pojo.mustache index 544fbf16498..e7053dcc39a 100644 --- a/libraries/native/pojo.mustache +++ b/libraries/native/pojo.mustache @@ -267,8 +267,8 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE return false; }{{#hasVars}} {{classname}} {{classVarName}} = ({{classname}}) o; - return {{#vars}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{#hasMore}} && - {{/hasMore}}{{/vars}}{{#additionalPropertiesType}}&& + return {{#vars}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{^-last}} && + {{/-last}}{{/vars}}{{#additionalPropertiesType}}&& Objects.equals(this.additionalProperties, {{classVarName}}.additionalProperties){{/additionalPropertiesType}}{{#parent}} && super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}} @@ -281,7 +281,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE return HashCodeBuilder.reflectionHashCode(this); {{/useReflectionEqualsHashCode}} {{^useReflectionEqualsHashCode}} - return Objects.hash({{#vars}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{#hasMore}}, {{/hasMore}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}{{#additionalPropertiesType}}, additionalProperties{{/additionalPropertiesType}}); + return Objects.hash({{#vars}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}{{#additionalPropertiesType}}, additionalProperties{{/additionalPropertiesType}}); {{/useReflectionEqualsHashCode}} } diff --git a/libraries/okhttp-gson/README.mustache b/libraries/okhttp-gson/README.mustache index e9be868f52c..6da087078f0 100644 --- a/libraries/okhttp-gson/README.mustache +++ b/libraries/okhttp-gson/README.mustache @@ -114,7 +114,7 @@ public class Example { {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} {{/allParams}} try { - {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}{{^vendorExtensions.x-group-parameters}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}({{#requiredParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}){{#optionalParams}} + {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}{{^vendorExtensions.x-group-parameters}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}({{#requiredParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/requiredParams}}){{#optionalParams}} .{{{paramName}}}({{{paramName}}}){{/optionalParams}} .execute();{{/vendorExtensions.x-group-parameters}}{{#returnType}} System.out.println(result);{{/returnType}} @@ -172,5 +172,5 @@ It's recommended to create an instance of `ApiClient` per thread in a multithrea ## Author -{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} -{{/hasMore}}{{/apis}}{{/apiInfo}} +{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}} +{{/-last}}{{/apis}}{{/apiInfo}} diff --git a/libraries/okhttp-gson/api.mustache b/libraries/okhttp-gson/api.mustache index d5158d55273..bbbca63b2b1 100644 --- a/libraries/okhttp-gson/api.mustache +++ b/libraries/okhttp-gson/api.mustache @@ -126,7 +126,7 @@ public class {{classname}} { {{/formParams}} final String[] localVarAccepts = { - {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} + {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} }; final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); if (localVarAccept != null) { @@ -134,12 +134,12 @@ public class {{classname}} { } final String[] localVarContentTypes = { - {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} + {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} }; final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); localVarHeaderParams.put("Content-Type", localVarContentType); - String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; return localVarApiClient.buildCall(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); } @@ -165,7 +165,7 @@ public class {{classname}} { ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); ExecutableValidator executableValidator = factory.getValidator().forExecutables(); - Object[] parameterValues = { {{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}} }; + Object[] parameterValues = { {{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}} }; Method method = this.getClass().getMethod("{{operationId}}WithHttpInfo"{{#allParams}}, {{#isArray}}java.util.List{{/isArray}}{{#isMap}}java.util.Map{{/isMap}}{{^isArray}}{{^isMap}}{{{dataType}}}{{/isMap}}{{/isArray}}.class{{/allParams}}); Set> violations = executableValidator.validateParameters(this, method, parameterValues); @@ -215,8 +215,8 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { - {{#returnType}}ApiResponse<{{{returnType}}}> localVarResp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + {{#returnType}}ApiResponse<{{{returnType}}}> localVarResp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});{{#returnType}} return localVarResp.getData();{{/returnType}} } {{/vendorExtensions.x-group-parameters}} @@ -247,7 +247,7 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { okhttp3.Call localVarCall = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}null); {{#returnType}}Type localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType(); return localVarApiClient.execute(localVarCall, localVarReturnType);{{/returnType}}{{^returnType}}return localVarApiClient.execute(localVarCall);{{/returnType}} @@ -297,7 +297,7 @@ public class {{classname}} { private {{{dataType}}} {{paramName}}; {{/optionalParams}} - private API{{operationId}}Request({{#requiredParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}) { + private API{{operationId}}Request({{#requiredParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}) { {{#requiredParams}} this.{{paramName}} = {{paramName}}; {{/requiredParams}} @@ -361,7 +361,7 @@ public class {{classname}} { @Deprecated {{/isDeprecated}} public {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} execute() throws ApiException { - {{#returnType}}ApiResponse<{{{returnType}}}> localVarResp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + {{#returnType}}ApiResponse<{{{returnType}}}> localVarResp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});{{#returnType}} return localVarResp.getData();{{/returnType}} } @@ -386,7 +386,7 @@ public class {{classname}} { @Deprecated {{/isDeprecated}} public ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> executeWithHttpInfo() throws ApiException { - return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); } /** @@ -440,8 +440,8 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public API{{operationId}}Request {{operationId}}({{#requiredParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}) { - return new API{{operationId}}Request({{#requiredParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}); + public API{{operationId}}Request {{operationId}}({{#requiredParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}) { + return new API{{operationId}}Request({{#requiredParams}}{{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}); } {{/vendorExtensions.x-group-parameters}} {{/operation}} diff --git a/libraries/okhttp-gson/api_doc.mustache b/libraries/okhttp-gson/api_doc.mustache index c7ce067ce13..332088661a9 100644 --- a/libraries/okhttp-gson/api_doc.mustache +++ b/libraries/okhttp-gson/api_doc.mustache @@ -12,8 +12,8 @@ Method | HTTP request | Description {{#operation}} # **{{operationId}}**{{^vendorExtensions.x-group-parameters}} -> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}} -> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#requiredParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}){{#optionalParams}}.{{paramName}}({{paramName}}){{/optionalParams}}.execute();{{/vendorExtensions.x-group-parameters}} +> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}){{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}} +> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#requiredParams}}{{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}){{#optionalParams}}.{{paramName}}({{paramName}}){{/optionalParams}}.execute();{{/vendorExtensions.x-group-parameters}} {{summary}}{{#notes}} @@ -58,7 +58,7 @@ public class Example { {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} {{/allParams}} try { - {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}{{^vendorExtensions.x-group-parameters}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}({{#requiredParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}){{#optionalParams}} + {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}{{^vendorExtensions.x-group-parameters}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}({{#requiredParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/requiredParams}}){{#optionalParams}} .{{{paramName}}}({{{paramName}}}){{/optionalParams}} .execute();{{/vendorExtensions.x-group-parameters}}{{#returnType}} System.out.println(result);{{/returnType}} @@ -90,8 +90,8 @@ Name | Type | Description | Notes ### HTTP request headers - - **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} - - **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} + - **Content-Type**: {{#consumes}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} + - **Accept**: {{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}{{^produces}}Not defined{{/produces}} {{#responses.0}} ### HTTP response details diff --git a/libraries/okhttp-gson/api_test.mustache b/libraries/okhttp-gson/api_test.mustache index b5693776b59..050bf8617d6 100644 --- a/libraries/okhttp-gson/api_test.mustache +++ b/libraries/okhttp-gson/api_test.mustache @@ -37,7 +37,7 @@ public class {{classname}}Test { {{#allParams}} {{{dataType}}} {{paramName}} = null; {{/allParams}} - {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}{{^vendorExtensions.x-group-parameters}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}({{#requiredParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}){{#optionalParams}} + {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}{{^vendorExtensions.x-group-parameters}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}({{#requiredParams}}{{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}){{#optionalParams}} .{{paramName}}({{paramName}}){{/optionalParams}} .execute();{{/vendorExtensions.x-group-parameters}} diff --git a/libraries/rest-assured/README.mustache b/libraries/rest-assured/README.mustache index 56560172ee3..a0fac9d41df 100644 --- a/libraries/rest-assured/README.mustache +++ b/libraries/rest-assured/README.mustache @@ -38,6 +38,6 @@ It's recommended to create an instance of `ApiClient` per thread in a multithrea ## Author -{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} -{{/hasMore}}{{/apis}}{{/apiInfo}} +{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}} +{{/-last}}{{/apis}}{{/apiInfo}} diff --git a/libraries/rest-assured/api.mustache b/libraries/rest-assured/api.mustache index 2016726a9cb..dea1217125e 100644 --- a/libraries/rest-assured/api.mustache +++ b/libraries/rest-assured/api.mustache @@ -73,7 +73,7 @@ public class {{classname}} { nickname = "{{{operationId}}}", tags = { {{#tags}}{{#name}}"{{{name}}}"{{/name}}{{^-last}}, {{/-last}}{{/tags}} }) @ApiResponses(value = { {{#responses}} - @ApiResponse(code = {{{code}}}, message = "{{{message}}}") {{#hasMore}},{{/hasMore}}{{/responses}} }) + @ApiResponse(code = {{{code}}}, message = "{{{message}}}") {{^-last}},{{/-last}}{{/responses}} }) {{#isDeprecated}} @Deprecated {{/isDeprecated}} diff --git a/libraries/rest-assured/api_doc.mustache b/libraries/rest-assured/api_doc.mustache index c8bf20319e7..f173a89016e 100644 --- a/libraries/rest-assured/api_doc.mustache +++ b/libraries/rest-assured/api_doc.mustache @@ -12,7 +12,7 @@ Method | HTTP request | Description {{#operation}} # **{{operationId}}** -> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) +> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}) {{summary}}{{#notes}} @@ -55,8 +55,8 @@ Name | Type | Description | Notes ### HTTP request headers - - **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} - - **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} + - **Content-Type**: {{#consumes}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} + - **Accept**: {{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}{{^produces}}Not defined{{/produces}} {{/operation}} {{/operations}} diff --git a/libraries/resteasy/api.mustache b/libraries/resteasy/api.mustache index fcb2268a100..85891614c0e 100644 --- a/libraries/resteasy/api.mustache +++ b/libraries/resteasy/api.mustache @@ -56,7 +56,7 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set @@ -91,16 +91,16 @@ public class {{classname}} { {{/formParams}} final String[] localVarAccepts = { - {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} + {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} }; final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); final String[] localVarContentTypes = { - {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} + {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} }; final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); - String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; {{#returnType}} GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {}; diff --git a/libraries/resttemplate/api.mustache b/libraries/resttemplate/api.mustache index 21a86a96a4a..006e6cf8f93 100644 --- a/libraries/resttemplate/api.mustache +++ b/libraries/resttemplate/api.mustache @@ -71,12 +71,12 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws RestClientException { {{#returnType}} - return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}).getBody(); + return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).getBody(); {{/returnType}} {{^returnType}} - {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); {{/returnType}} } @@ -99,7 +99,7 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public ResponseEntity<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { + public ResponseEntity<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws RestClientException { Object postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set @@ -117,31 +117,31 @@ public class {{classname}} { final MultiValueMap cookieParams = new LinkedMultiValueMap(); final MultiValueMap formParams = new LinkedMultiValueMap();{{#hasQueryParams}} - {{#queryParams}}queryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{#hasMore}} - {{/hasMore}}{{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}} + {{#queryParams}}queryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{^-last}} + {{/-last}}{{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}} {{#headerParams}}if ({{paramName}} != null) - headerParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{#hasMore}} - {{/hasMore}}{{/headerParams}}{{/hasHeaderParams}}{{#hasCookieParams}} + headerParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{^-last}} + {{/-last}}{{/headerParams}}{{/hasHeaderParams}}{{#hasCookieParams}} {{#cookieParams}}if ({{paramName}} != null) - cookieParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{#hasMore}} - {{/hasMore}}{{/cookieParams}}{{/hasCookieParams}}{{#hasFormParams}} + cookieParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{^-last}} + {{/-last}}{{/cookieParams}}{{/hasCookieParams}}{{#hasFormParams}} {{#formParams}}if ({{paramName}} != null) - formParams.{{^collectionFormat}}add{{/collectionFormat}}{{#collectionFormat}}addAll{{/collectionFormat}}("{{baseName}}", {{#isFile}}{{^collectionFormat}}{{#useAbstractionForFiles}}{{paramName}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}new FileSystemResource({{paramName}}){{/useAbstractionForFiles}}{{/collectionFormat}}{{/isFile}}{{#isFile}}{{#collectionFormat}}{{paramName}}.stream(){{^useAbstractionForFiles}}.map(FileSystemResource::new){{/useAbstractionForFiles}}.collect(Collectors.toList()){{/collectionFormat}}{{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} - {{/hasMore}}{{/formParams}}{{/hasFormParams}} + formParams.{{^collectionFormat}}add{{/collectionFormat}}{{#collectionFormat}}addAll{{/collectionFormat}}("{{baseName}}", {{#isFile}}{{^collectionFormat}}{{#useAbstractionForFiles}}{{paramName}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}new FileSystemResource({{paramName}}){{/useAbstractionForFiles}}{{/collectionFormat}}{{/isFile}}{{#isFile}}{{#collectionFormat}}{{paramName}}.stream(){{^useAbstractionForFiles}}.map(FileSystemResource::new){{/useAbstractionForFiles}}.collect(Collectors.toList()){{/collectionFormat}}{{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{^-last}} + {{/-last}}{{/formParams}}{{/hasFormParams}} final String[] localVarAccepts = { {{#hasProduces}} - {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} + {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} {{/hasProduces}} }; final List localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); final String[] contentTypes = { {{#hasConsumes}} - {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} + {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} {{/hasConsumes}} }; final MediaType contentType = apiClient.selectHeaderContentType(contentTypes); - String[] authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + String[] authNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; {{#returnType}}ParameterizedTypeReference<{{{returnType}}}> returnType = new ParameterizedTypeReference<{{{returnType}}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference returnType = new ParameterizedTypeReference() {};{{/returnType}} return apiClient.invokeAPI(path, HttpMethod.{{httpMethod}}, queryParams, postBody, headerParams, cookieParams, formParams, localVarAccept, contentType, authNames, returnType); diff --git a/libraries/resttemplate/api_test.mustache b/libraries/resttemplate/api_test.mustache index a82e352f6fc..119194543c3 100644 --- a/libraries/resttemplate/api_test.mustache +++ b/libraries/resttemplate/api_test.mustache @@ -36,7 +36,7 @@ public class {{classname}}Test { {{#allParams}} {{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}} = null; {{/allParams}} - {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); // TODO: test validations } diff --git a/libraries/retrofit/ApiClient.mustache b/libraries/retrofit/ApiClient.mustache index a4a99fea9ee..ad3057e9c3d 100644 --- a/libraries/retrofit/ApiClient.mustache +++ b/libraries/retrofit/ApiClient.mustache @@ -73,7 +73,7 @@ public class ApiClient { auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"); {{/isApiKey}} {{#isOAuth}} - auth = new OAuth(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{#hasMore}}, {{/hasMore}}{{/scopes}}"); + auth = new OAuth(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{^-last}}, {{/-last}}{{/scopes}}"); {{/isOAuth}} } else {{/authMethods}}{ throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); diff --git a/libraries/retrofit/README.mustache b/libraries/retrofit/README.mustache index 56560172ee3..a0fac9d41df 100644 --- a/libraries/retrofit/README.mustache +++ b/libraries/retrofit/README.mustache @@ -38,6 +38,6 @@ It's recommended to create an instance of `ApiClient` per thread in a multithrea ## Author -{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} -{{/hasMore}}{{/apis}}{{/apiInfo}} +{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}} +{{/-last}}{{/apis}}{{/apiInfo}} diff --git a/libraries/retrofit/api.mustache b/libraries/retrofit/api.mustache index 9effc056056..99b7f4f796a 100644 --- a/libraries/retrofit/api.mustache +++ b/libraries/retrofit/api.mustache @@ -36,8 +36,8 @@ public interface {{classname}} { {{#isMultipart}}@retrofit.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit.http.FormUrlEncoded{{/isMultipart}}{{/-first}}{{/formParams}} @{{httpMethod}}("{{{path}}}") {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}} {{operationId}}({{^allParams}});{{/allParams}} - {{#allParams}}{{>libraries/retrofit/queryParams}}{{>libraries/retrofit/pathParams}}{{>libraries/retrofit/headerParams}}{{>libraries/retrofit/bodyParams}}{{>libraries/retrofit/formParams}}{{#hasMore}}, {{/hasMore}}{{^hasMore}} - );{{/hasMore}}{{/allParams}} + {{#allParams}}{{>libraries/retrofit/queryParams}}{{>libraries/retrofit/pathParams}}{{>libraries/retrofit/headerParams}}{{>libraries/retrofit/bodyParams}}{{>libraries/retrofit/formParams}}{{^-last}}, {{/-last}}{{#-last}} + );{{/-last}}{{/allParams}} /** * {{summary}} diff --git a/libraries/retrofit/api_test.mustache b/libraries/retrofit/api_test.mustache index a34cfe0e12b..db07fb825c9 100644 --- a/libraries/retrofit/api_test.mustache +++ b/libraries/retrofit/api_test.mustache @@ -36,7 +36,7 @@ public class {{classname}}Test { {{#allParams}} {{{dataType}}} {{paramName}} = null; {{/allParams}} - // {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + // {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); // TODO: test validations } diff --git a/libraries/retrofit2/ApiClient.mustache b/libraries/retrofit2/ApiClient.mustache index 645727db3c0..de40d727587 100644 --- a/libraries/retrofit2/ApiClient.mustache +++ b/libraries/retrofit2/ApiClient.mustache @@ -85,7 +85,7 @@ public class ApiClient { auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"); {{/isApiKey}} {{#isOAuth}} - auth = new OAuth(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{#hasMore}}, {{/hasMore}}{{/scopes}}"); + auth = new OAuth(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{^-last}}, {{/-last}}{{/scopes}}"); {{/isOAuth}} } else {{/authMethods}}{ throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); diff --git a/libraries/retrofit2/README.mustache b/libraries/retrofit2/README.mustache index 9d744b8589e..847b9d5a2a1 100644 --- a/libraries/retrofit2/README.mustache +++ b/libraries/retrofit2/README.mustache @@ -34,6 +34,6 @@ After the client library is installed/deployed, you can use it in your Maven pro ## Author -{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} -{{/hasMore}}{{/apis}}{{/apiInfo}} +{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}} +{{/-last}}{{/apis}}{{/apiInfo}} diff --git a/libraries/retrofit2/api.mustache b/libraries/retrofit2/api.mustache index a54e6ffd60f..baa89192cd7 100644 --- a/libraries/retrofit2/api.mustache +++ b/libraries/retrofit2/api.mustache @@ -75,8 +75,8 @@ public interface {{classname}} { {{/formParams}} @{{httpMethod}}("{{{path}}}") {{^doNotUseRx}}{{#useRxJava}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/useRxJava}}{{#useRxJava2}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{{returnType}}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{#useRxJava3}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{{returnType}}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava3}}{{/doNotUseRx}}{{#doNotUseRx}}Call<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/doNotUseRx}} {{operationId}}({{^allParams}});{{/allParams}} - {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{#hasMore}}, {{/hasMore}}{{^hasMore}} - );{{/hasMore}}{{/allParams}} + {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{^-last}}, {{/-last}}{{#-last}} + );{{/-last}}{{/allParams}} {{/operation}} } diff --git a/libraries/retrofit2/api_test.mustache b/libraries/retrofit2/api_test.mustache index 0a85ef5095c..d214d97724c 100644 --- a/libraries/retrofit2/api_test.mustache +++ b/libraries/retrofit2/api_test.mustache @@ -37,7 +37,7 @@ public class {{classname}}Test { {{#allParams}} {{{dataType}}} {{paramName}} = null; {{/allParams}} - // {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + // {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); // TODO: test validations } diff --git a/libraries/retrofit2/play24/api.mustache b/libraries/retrofit2/play24/api.mustache index dd6bf23e947..42cc9347d68 100644 --- a/libraries/retrofit2/play24/api.mustache +++ b/libraries/retrofit2/play24/api.mustache @@ -51,8 +51,8 @@ public interface {{classname}} { {{/formParams}} @{{httpMethod}}("{{{path}}}") F.Promise> {{operationId}}({{^allParams}});{{/allParams}} - {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{#hasMore}}, {{/hasMore}}{{^hasMore}} - );{{/hasMore}}{{/allParams}} + {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{^-last}}, {{/-last}}{{#-last}} + );{{/-last}}{{/allParams}} {{/operation}} } diff --git a/libraries/retrofit2/play25/api.mustache b/libraries/retrofit2/play25/api.mustache index b435a16c051..8f9dc16cea1 100644 --- a/libraries/retrofit2/play25/api.mustache +++ b/libraries/retrofit2/play25/api.mustache @@ -51,8 +51,8 @@ public interface {{classname}} { {{/formParams}} @{{httpMethod}}("{{{path}}}") CompletionStage> {{operationId}}({{^allParams}});{{/allParams}} - {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{#hasMore}}, {{/hasMore}}{{^hasMore}} - );{{/hasMore}}{{/allParams}} + {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{^-last}}, {{/-last}}{{#-last}} + );{{/-last}}{{/allParams}} {{/operation}} } diff --git a/libraries/retrofit2/play26/api.mustache b/libraries/retrofit2/play26/api.mustache index b435a16c051..8f9dc16cea1 100644 --- a/libraries/retrofit2/play26/api.mustache +++ b/libraries/retrofit2/play26/api.mustache @@ -51,8 +51,8 @@ public interface {{classname}} { {{/formParams}} @{{httpMethod}}("{{{path}}}") CompletionStage> {{operationId}}({{^allParams}});{{/allParams}} - {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{#hasMore}}, {{/hasMore}}{{^hasMore}} - );{{/hasMore}}{{/allParams}} + {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{^-last}}, {{/-last}}{{#-last}} + );{{/-last}}{{/allParams}} {{/operation}} } diff --git a/libraries/vertx/apiImpl.mustache b/libraries/vertx/apiImpl.mustache index ed38fe79438..e9e9a2fe7de 100644 --- a/libraries/vertx/apiImpl.mustache +++ b/libraries/vertx/apiImpl.mustache @@ -100,9 +100,9 @@ public class {{classname}}Impl implements {{classname}} { {{#formParams}}if ({{paramName}} != null) localVarFormParams.put("{{baseName}}", {{paramName}}); {{/formParams}} - String[] localVarAccepts = { {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }; - String[] localVarContentTypes = { {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} }; - String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + String[] localVarAccepts = { {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} }; + String[] localVarContentTypes = { {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} }; + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; {{#returnType}} TypeReference<{{{returnType}}}> localVarReturnType = new TypeReference<{{{returnType}}}>() {}; apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccepts, localVarContentTypes, localVarAuthNames, authInfo, localVarReturnType, resultHandler);{{/returnType}}{{^returnType}} diff --git a/libraries/vertx/rxApiImpl.mustache b/libraries/vertx/rxApiImpl.mustache index abb6e8458d4..f1f5d0323f5 100644 --- a/libraries/vertx/rxApiImpl.mustache +++ b/libraries/vertx/rxApiImpl.mustache @@ -58,7 +58,7 @@ public class {{classname}} { {{/allParams}} * @return Asynchronous result handler (RxJava Single) */ - public Single<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> rx{{operationIdCamelCase}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) { + public Single<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> rx{{operationIdCamelCase}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) { return Single.create(new io.vertx.rx.java.SingleOnSubscribeAdapter<>(fut -> delegate.{{operationId}}({{#allParams}}{{paramName}}, {{/allParams}}fut) )); diff --git a/libraries/webclient/api.mustache b/libraries/webclient/api.mustache index a62a10c0c12..83178188549 100644 --- a/libraries/webclient/api.mustache +++ b/libraries/webclient/api.mustache @@ -62,7 +62,7 @@ public class {{classname}} { * @see {{summary}} Documentation {{/externalDocs}} */ - public {{#returnType}}{{#isArray}}Flux<{{{returnBaseType}}}>{{/isArray}}{{^isArray}}Mono<{{{returnType}}}>{{/isArray}} {{/returnType}}{{^returnType}}Mono {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws WebClientResponseException { + public {{#returnType}}{{#isArray}}Flux<{{{returnBaseType}}}>{{/isArray}}{{^isArray}}Mono<{{{returnType}}}>{{/isArray}} {{/returnType}}{{^returnType}}Mono {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws WebClientResponseException { Object postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}} {{#required}} @@ -95,8 +95,8 @@ public class {{classname}} { {{#headerParams}} if ({{paramName}} != null) - headerParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{#hasMore}} - {{/hasMore}} + headerParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{^-last}} + {{/-last}} {{/headerParams}} {{/hasHeaderParams}} {{#hasCookieParams}} @@ -114,15 +114,15 @@ public class {{classname}} { {{/hasFormParams}} final String[] localVarAccepts = { {{#hasProduces}} - {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} + {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} {{/hasProduces}}}; final List localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); final String[] localVarContentTypes = { {{#hasConsumes}} - {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} + {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} {{/hasConsumes}}}; final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); - String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; {{#returnType}}ParameterizedTypeReference<{{#isArray}}{{{returnBaseType}}}{{/isArray}}{{^isArray}}{{{returnType}}}{{/isArray}}> localVarReturnType = new ParameterizedTypeReference<{{#isArray}}{{{returnBaseType}}}{{/isArray}}{{^isArray}}{{{returnType}}}{{/isArray}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference localVarReturnType = new ParameterizedTypeReference() {};{{/returnType}} return apiClient.{{#isArray}}invokeFluxAPI{{/isArray}}{{^isArray}}invokeAPI{{/isArray}}("{{{path}}}", HttpMethod.{{httpMethod}}, pathParams, queryParams, postBody, headerParams, cookieParams, formParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType); diff --git a/libraries/webclient/api_test.mustache b/libraries/webclient/api_test.mustache index edd2c06a70b..301acf8f244 100644 --- a/libraries/webclient/api_test.mustache +++ b/libraries/webclient/api_test.mustache @@ -33,7 +33,7 @@ public class {{classname}}Test { {{#allParams}} {{{dataType}}} {{paramName}} = null; {{/allParams}} - {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#isArray}}.collectList().block(){{/isArray}}{{^isArray}}.block(){{/isArray}}; + {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}){{#isArray}}.collectList().block(){{/isArray}}{{^isArray}}.block(){{/isArray}}; // TODO: test validations } diff --git a/pojo.mustache b/pojo.mustache index 17d0c1b5a10..03cf219b760 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -242,8 +242,8 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE return false; }{{#hasVars}} {{classname}} {{classVarName}} = ({{classname}}) o; - return {{#vars}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{#hasMore}} && - {{/hasMore}}{{/vars}}{{#parent}} && + return {{#vars}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{^-last}} && + {{/-last}}{{/vars}}{{#parent}} && super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}} {{/useReflectionEqualsHashCode}} @@ -255,7 +255,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE return HashCodeBuilder.reflectionHashCode(this); {{/useReflectionEqualsHashCode}} {{^useReflectionEqualsHashCode}} - return Objects.hash({{#vars}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{#hasMore}}, {{/hasMore}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); + return Objects.hash({{#vars}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); {{/useReflectionEqualsHashCode}} } @@ -270,15 +270,15 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE return false; }{{#hasVars}} {{classname}} {{classVarName}} = ({{classname}}) o; - return {{#vars}}ObjectUtils.equals(this.{{name}}, {{classVarName}}.{{name}}){{#hasMore}} && - {{/hasMore}}{{/vars}}{{#parent}} && + return {{#vars}}ObjectUtils.equals(this.{{name}}, {{classVarName}}.{{name}}){{^-last}} && + {{/-last}}{{/vars}}{{#parent}} && super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} return true;{{/hasVars}} } @Override public int hashCode() { - return ObjectUtils.hashCodeMulti({{#vars}}{{name}}{{#hasMore}}, {{/hasMore}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); + return ObjectUtils.hashCodeMulti({{#vars}}{{name}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); } {{/supportJava6}} From 153da83a8f2207a9f80cf558b3ec9b6177249e6b Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 20 Nov 2020 11:54:39 +0800 Subject: [PATCH 323/370] fix additional properties without variables (#7978) --- libraries/jersey2/pojo.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/jersey2/pojo.mustache b/libraries/jersey2/pojo.mustache index 1004fa40265..3d1c6cf59db 100644 --- a/libraries/jersey2/pojo.mustache +++ b/libraries/jersey2/pojo.mustache @@ -282,7 +282,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE return HashCodeBuilder.reflectionHashCode(this); {{/useReflectionEqualsHashCode}} {{^useReflectionEqualsHashCode}} - return Objects.hash({{#vars}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}{{#additionalPropertiesType}}, additionalProperties{{/additionalPropertiesType}}); + return Objects.hash({{#vars}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}{{#additionalPropertiesType}}{{#hasVars}}, {{/hasVars}}{{^hasVars}}{{#parent}}, {{/parent}}{{/hasVars}}additionalProperties{{/additionalPropertiesType}}); {{/useReflectionEqualsHashCode}} } From bb9acee389d6f80a595f212ec90a2027bb900001 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Herv=C3=A9?= Date: Mon, 23 Nov 2020 09:24:31 +0100 Subject: [PATCH 324/370] Remove links to basic types in java API docs (#7989) * Remove links to basic types in java API docs This removes (most) wrong links to basic types in Java API docs. * Regenerate some more samples --- libraries/jersey2/api_doc.mustache | 2 +- pojo_doc.mustache | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/jersey2/api_doc.mustache b/libraries/jersey2/api_doc.mustache index 42d951f1779..e0c65a61d60 100644 --- a/libraries/jersey2/api_doc.mustache +++ b/libraries/jersey2/api_doc.mustache @@ -92,7 +92,7 @@ public class Example { {{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} Name | Type | Description | Notes ------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} -{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{^isContainer}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} +{{#allParams}} **{{paramName}}** | {{#isContainer}}{{#isArray}}{{#items}}{{#isModel}}{{^isFile}}[{{/isFile}}{{/isModel}}**List<{{dataType}}>**{{#isModel}}{{^isFile}}]({{^baseType}}{{dataType}}{{/baseType}}{{#baseType}}{{baseType}}{{/baseType}}.md){{/isFile}}{{/isModel}}{{/items}}{{/isArray}}{{#isMap}}{{#items}}{{#isModel}}{{^isFile}}[{{/isFile}}{{/isModel}}**Map<String,{{dataType}}>**{{#isModel}}{{^isFile}}]({{^baseType}}{{dataType}}{{/baseType}}{{#baseType}}{{baseType}}{{/baseType}}.md){{/isFile}}{{/isModel}}{{/items}}{{/isMap}}{{/isContainer}}{{^isContainer}}{{#isModel}}{{^isFile}}[{{/isFile}}{{/isModel}}**{{dataType}}**{{#isModel}}{{^isFile}}]({{^baseType}}{{dataType}}{{/baseType}}{{#baseType}}{{baseType}}{{/baseType}}.md){{/isFile}}{{/isModel}}{{/isContainer}}| {{description}} |{{^required}} [optional]{{/required}}{{^isContainer}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} {{/allParams}} ### Return type diff --git a/pojo_doc.mustache b/pojo_doc.mustache index d9381323c87..0a42c19469a 100644 --- a/pojo_doc.mustache +++ b/pojo_doc.mustache @@ -7,7 +7,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -{{#vars}}**{{name}}** | {{#isEnum}}[**{{datatypeWithEnum}}**](#{{datatypeWithEnum}}){{/isEnum}}{{^isEnum}}{{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}}{{/isEnum}} | {{description}} | {{^required}} [optional]{{/required}}{{#isReadOnly}} [readonly]{{/isReadOnly}} +{{#vars}}**{{name}}** | {{#isEnum}}[**{{datatypeWithEnum}}**](#{{datatypeWithEnum}}){{/isEnum}}{{^isEnum}}{{#isContainer}}{{#isArray}}{{#items}}{{#isModel}}[{{/isModel}}{{/items}}**{{baseType}}{{#items}}<{{dataType}}>**{{#isModel}}]({{^baseType}}{{dataType}}{{/baseType}}{{#baseType}}{{baseType}}{{/baseType}}.md){{/isModel}}{{/items}}{{/isArray}}{{#isMap}}{{#items}}{{#isModel}}[{{/isModel}}**Map<String, {{dataType}}>**{{#isModel}}]({{^baseType}}{{dataType}}{{/baseType}}{{#baseType}}{{baseType}}{{/baseType}}.md){{/isModel}}{{/items}}{{/isMap}}{{/isContainer}}{{^isContainer}}{{#isModel}}[{{/isModel}}**{{dataType}}**{{#isModel}}]({{^baseType}}{{dataType}}{{/baseType}}{{#baseType}}{{baseType}}{{/baseType}}.md){{/isModel}}{{/isContainer}}{{/isEnum}} | {{description}} | {{^required}} [optional]{{/required}}{{#isReadOnly}} [readonly]{{/isReadOnly}} {{/vars}} {{#vars}}{{#isEnum}} @@ -33,4 +33,4 @@ Name | Value {{#oneOf}} * {{{.}}} {{/oneOf}} -{{/vendorExtensions.x-is-one-of-interface}} \ No newline at end of file +{{/vendorExtensions.x-is-one-of-interface}} From a4bd42beec431881a53f6cc34c25dc80cf47c15b Mon Sep 17 00:00:00 2001 From: David Ruppelt <44848632+druppelt@users.noreply.github.com> Date: Tue, 24 Nov 2020 15:28:23 +0100 Subject: [PATCH 325/370] remove default ContentType for java webclient (#7945) --- libraries/webclient/ApiClient.mustache | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index 98f4bfb2004..e2db597c54c 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -477,11 +477,11 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { * otherwise use the first one of the array. * * @param contentTypes The Content-Type array to select from - * @return MediaType The Content-Type header to use. If the given array is empty, JSON will be used. + * @return MediaType The Content-Type header to use. If the given array is empty, null will be returned. */ public MediaType selectHeaderContentType(String[] contentTypes) { if (contentTypes.length == 0) { - return MediaType.APPLICATION_JSON; + return null; } for (String contentType : contentTypes) { MediaType mediaType = MediaType.parseMediaType(contentType); From fafc5f7c2ef928676216e2dadeda73aef0629523 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Herv=C3=A9?= Date: Thu, 26 Nov 2020 11:14:26 +0100 Subject: [PATCH 326/370] Improve generated Java examples (#8012) * Add basic types imports to generated examples This adds an extension to include basic types imports to generated Java examples. * Make some fixes to example generation * Generate OffsetDatetime correctly * Create a useful sample for enums, regenerate samples * Fix BigDecimal as well --- libraries/jersey2/api_doc.mustache | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/jersey2/api_doc.mustache b/libraries/jersey2/api_doc.mustache index e0c65a61d60..e9270ceb18f 100644 --- a/libraries/jersey2/api_doc.mustache +++ b/libraries/jersey2/api_doc.mustache @@ -28,6 +28,9 @@ Method | HTTP request | Description ### Example ```java +{{#vendorExtensions.x-java-import}} +import {{.}}; +{{/vendorExtensions.x-java-import}} // Import classes: import {{{invokerPackage}}}.ApiClient; import {{{invokerPackage}}}.ApiException; From 8a26b64a892cdad9c71d08c53ba31f753b06582a Mon Sep 17 00:00:00 2001 From: Toby Murray Date: Sun, 6 Dec 2020 21:44:23 -0500 Subject: [PATCH 327/370] Bump Gradle in generated Java projects to 6.7.1 (#8079) * Bump Gradle in Java projects from 6.0.1 to 6.7.1 Regular maintenance, 6.0.1 was released November 18th, 2019 and the latest release (November 16th, 2020) is 6.7.1. This updates all the wrapper templatesto the latest version. * Updated generated Java samples Generated via `./bin/generate-samples.sh bin/configs/java-*` * update samples Co-authored-by: William Cheng --- gradle-wrapper.jar | Bin 58702 -> 59203 bytes gradle-wrapper.properties.mustache | 2 +- gradlew.bat.mustache | 25 +++++++------------------ gradlew.mustache | 2 ++ 4 files changed, 10 insertions(+), 19 deletions(-) diff --git a/gradle-wrapper.jar b/gradle-wrapper.jar index cc4fdc293d0e50b0ad9b65c16e7ddd1db2f6025b..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f 100644 GIT binary patch delta 18978 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 delta 18570 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 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -51,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -61,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/gradlew.mustache b/gradlew.mustache index 2fe81a7d95e..4f906e0c811 100755 --- a/gradlew.mustache +++ b/gradlew.mustache @@ -82,6 +82,7 @@ esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -129,6 +130,7 @@ fi if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath From 91aa458555fe037bceaf1a6ada0af64045af33e6 Mon Sep 17 00:00:00 2001 From: Christophe Bornet Date: Thu, 10 Dec 2020 11:22:39 +0100 Subject: [PATCH 328/370] =?UTF-8?q?[Java/okhttp]=C2=A0Add=20dynamic=20oper?= =?UTF-8?q?ations=20option=20(#7916)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add dynamicOperations option to okhttp gen * Add tests * Add apiclient tests * Fix apiclient template * Add dependencies in gradle and sbt --- apiOperation.mustache | 28 +++++ libraries/okhttp-gson/ApiClient.mustache | 129 ++++++++++++++++++++ libraries/okhttp-gson/api.mustache | 50 ++++++-- libraries/okhttp-gson/build.gradle.mustache | 3 + libraries/okhttp-gson/build.sbt.mustache | 3 + libraries/okhttp-gson/pom.mustache | 7 ++ 6 files changed, 211 insertions(+), 9 deletions(-) create mode 100644 apiOperation.mustache diff --git a/apiOperation.mustache b/apiOperation.mustache new file mode 100644 index 00000000000..97adb0ea285 --- /dev/null +++ b/apiOperation.mustache @@ -0,0 +1,28 @@ +{{>licenseInfo}} +package {{invokerPackage}}; + +import io.swagger.v3.oas.models.Operation; + +public class ApiOperation { + private final String path; + private final String method; + private final Operation operation; + + public ApiOperation(String path, String method, Operation operation) { + this.path = path; + this.method = method; + this.operation = operation; + } + + public Operation getOperation() { + return operation; + } + + public String getPath() { + return path; + } + + public String getMethod() { + return method; + } +} diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index 37572c1b4a7..d417072e334 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -2,6 +2,14 @@ package {{invokerPackage}}; +{{#dynamicOperations}} +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.PathItem; +import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.oas.models.parameters.Parameter.StyleEnum; +import io.swagger.v3.parser.OpenAPIV3Parser; +{{/dynamicOperations}} import okhttp3.*; import okhttp3.internal.http.HttpMethod; import okhttp3.internal.tls.OkHostnameVerifier; @@ -86,6 +94,10 @@ public class ApiClient { private HttpLoggingInterceptor loggingInterceptor; + {{#dynamicOperations}} + private Map operationLookupMap = new HashMap<>(); + + {{/dynamicOperations}} /* * Basic constructor for ApiClient */ @@ -209,6 +221,11 @@ public class ApiClient { setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); authentications = new HashMap(); + {{#dynamicOperations}} + + OpenAPI openAPI = new OpenAPIV3Parser().read("openapi/openapi.yaml"); + createOperationLookupMap(openAPI); + {{/dynamicOperations}} } /** @@ -694,6 +711,7 @@ public class ApiClient { return params; } + {{^dynamicOperations}} /** * Formats the specified collection query parameters to a list of {@code Pair} objects. * @@ -743,6 +761,46 @@ public class ApiClient { return params; } + {{/dynamicOperations}} + {{#dynamicOperations}} + public List parameterToPairs(Parameter param, Collection value) { + List params = new ArrayList(); + + // preconditions + if (param == null || param.getName() == null || param.getName().isEmpty() || value == null) { + return params; + } + + // create the params based on the collection format + if (StyleEnum.FORM.equals(param.getStyle()) && Boolean.TRUE.equals(param.getExplode())) { + for (Object item : value) { + params.add(new Pair(param.getName(), escapeString(parameterToString(item)))); + } + return params; + } + + // collectionFormat is assumed to be "csv" by default + String delimiter = ","; + + // escape all delimiters except commas, which are URI reserved + // characters + if (StyleEnum.SPACEDELIMITED.equals(param.getStyle())) { + delimiter = escapeString(" "); + } else if (StyleEnum.PIPEDELIMITED.equals(param.getStyle())) { + delimiter = escapeString("|"); + } + + StringBuilder sb = new StringBuilder(); + for (Object item : value) { + sb.append(delimiter); + sb.append(escapeString(parameterToString(item))); + } + + params.add(new Pair(param.getName(), sb.substring(delimiter.length()))); + + return params; + } + {{/dynamicOperations}} /** * Formats the specified collection path parameter to a string value. @@ -1467,4 +1525,75 @@ public class ApiClient { throw new AssertionError(e); } } + {{#dynamicOperations}} + + public ApiClient createOperationLookupMap(OpenAPI openAPI) { + operationLookupMap = new HashMap<>(); + for (Map.Entry pathItemEntry : openAPI.getPaths().entrySet()) { + String path = pathItemEntry.getKey(); + PathItem pathItem = pathItemEntry.getValue(); + addOperationLookupEntry(path, "GET", pathItem.getGet()); + addOperationLookupEntry(path, "PUT", pathItem.getPut()); + addOperationLookupEntry(path, "POST", pathItem.getPost()); + addOperationLookupEntry(path, "DELETE", pathItem.getDelete()); + addOperationLookupEntry(path, "OPTIONS", pathItem.getOptions()); + addOperationLookupEntry(path, "HEAD", pathItem.getHead()); + addOperationLookupEntry(path, "PATCH", pathItem.getPatch()); + addOperationLookupEntry(path, "TRACE", pathItem.getTrace()); + } + return this; + } + + private void addOperationLookupEntry(String path, String method, Operation operation) { + if ( operation != null && operation.getOperationId() != null) { + operationLookupMap.put( + operation.getOperationId(), + new ApiOperation(path, method, operation)); + } + } + + public Map getOperationLookupMap() { + return operationLookupMap; + } + + public String fillParametersFromOperation( + Operation operation, + Map paramMap, + String path, + List queryParams, + List collectionQueryParams, + Map headerParams, + Map cookieParams + ) { + for (Map.Entry entry : paramMap.entrySet()) { + Object value = entry.getValue(); + for (Parameter param : operation.getParameters()) { + if (entry.getKey().equals(param.getName())) { + switch (param.getIn()) { + case "path": + path = path.replaceAll("\\{" + param.getName() + "\\}", escapeString(value.toString())); + break; + case "query": + if (value instanceof Collection) { + collectionQueryParams.addAll(parameterToPairs(param, (Collection) value)); + } else { + queryParams.addAll(parameterToPair(param.getName(), value)); + } + break; + case "header": + headerParams.put(param.getName(), parameterToString(value)); + break; + case "cookie": + cookieParams.put(param.getName(), parameterToString(value)); + break; + default: + throw new IllegalStateException("Unexpected param in: " + param.getIn()); + } + + } + } + } + return path; + } + {{/dynamicOperations}} } diff --git a/libraries/okhttp-gson/api.mustache b/libraries/okhttp-gson/api.mustache index bbbca63b2b1..6f71a36cd97 100644 --- a/libraries/okhttp-gson/api.mustache +++ b/libraries/okhttp-gson/api.mustache @@ -5,6 +5,9 @@ package {{package}}; import {{invokerPackage}}.ApiCallback; import {{invokerPackage}}.ApiClient; import {{invokerPackage}}.ApiException; +{{#dynamicOperations}} +import {{invokerPackage}}.ApiOperation; +{{/dynamicOperations}} import {{invokerPackage}}.ApiResponse; import {{invokerPackage}}.Configuration; import {{invokerPackage}}.Pair; @@ -15,6 +18,10 @@ import {{invokerPackage}}.BeanValidationException; {{/performBeanValidation}} import com.google.gson.reflect.TypeToken; +{{#dynamicOperations}} +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.parameters.Parameter; +{{/dynamicOperations}} import java.io.IOException; @@ -93,38 +100,63 @@ public class {{classname}} { Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; // create path and map variables + {{^dynamicOperations}} String localVarPath = "{{{path}}}"{{#pathParams}} .replaceAll("\\{" + "{{baseName}}" + "\\}", localVarApiClient.escapeString({{#collectionFormat}}localVarApiClient.collectionPathParameterToString("{{{collectionFormat}}}", {{{paramName}}}){{/collectionFormat}}{{^collectionFormat}}{{{paramName}}}.toString(){{/collectionFormat}})){{/pathParams}}; + {{/dynamicOperations}} + {{#dynamicOperations}} + ApiOperation apiOperation = localVarApiClient.getOperationLookupMap().get("{{{operationId}}}"); + if (apiOperation == null) { + throw new ApiException("Operation not found in OAS"); + } + Operation operation = apiOperation.getOperation(); + String localVarPath = apiOperation.getPath(); + Map paramMap = new HashMap<>(); + {{#allParams}} + {{^isFormParam}} + {{^isBodyParam}} + paramMap.put("{{baseName}}", {{paramName}}); + {{/isBodyParam}} + {{/isFormParam}} + {{/allParams}} + {{/dynamicOperations}} {{javaUtilPrefix}}List localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); {{javaUtilPrefix}}List localVarCollectionQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}Map localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarCookieParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarFormParams = new {{javaUtilPrefix}}HashMap(); + + {{#formParams}} + if ({{paramName}} != null) { + localVarFormParams.put("{{baseName}}", {{paramName}}); + } + + {{/formParams}} + {{^dynamicOperations}} {{#queryParams}} if ({{paramName}} != null) { {{#collectionFormat}}localVarCollectionQueryParams.addAll(localVarApiClient.parameterToPairs("{{{collectionFormat}}}", {{/collectionFormat}}{{^collectionFormat}}localVarQueryParams.addAll(localVarApiClient.parameterToPair({{/collectionFormat}}"{{baseName}}", {{paramName}})); } {{/queryParams}} - {{javaUtilPrefix}}Map localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); {{#headerParams}} if ({{paramName}} != null) { localVarHeaderParams.put("{{baseName}}", localVarApiClient.parameterToString({{paramName}})); } {{/headerParams}} - {{javaUtilPrefix}}Map localVarCookieParams = new {{javaUtilPrefix}}HashMap(); {{#cookieParams}} if ({{paramName}} != null) { localVarCookieParams.put("{{baseName}}", localVarApiClient.parameterToString({{paramName}})); } {{/cookieParams}} - {{javaUtilPrefix}}Map localVarFormParams = new {{javaUtilPrefix}}HashMap(); - {{#formParams}} - if ({{paramName}} != null) { - localVarFormParams.put("{{baseName}}", {{paramName}}); - } + {{/dynamicOperations}} + {{#dynamicOperations}} + localVarPath = localVarApiClient.fillParametersFromOperation(operation, paramMap, localVarPath, localVarQueryParams, localVarCollectionQueryParams, localVarHeaderParams, localVarCookieParams); - {{/formParams}} + {{/dynamicOperations}} final String[] localVarAccepts = { {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} }; @@ -140,7 +172,7 @@ public class {{classname}} { localVarHeaderParams.put("Content-Type", localVarContentType); String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; - return localVarApiClient.buildCall(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + return localVarApiClient.buildCall(localVarPath, {{^dynamicOperations}}"{{httpMethod}}"{{/dynamicOperations}}{{#dynamicOperations}}apiOperation.getMethod(){{/dynamicOperations}}, localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); } {{#isDeprecated}} diff --git a/libraries/okhttp-gson/build.gradle.mustache b/libraries/okhttp-gson/build.gradle.mustache index b263167cb55..8f10fd4e728 100644 --- a/libraries/okhttp-gson/build.gradle.mustache +++ b/libraries/okhttp-gson/build.gradle.mustache @@ -142,6 +142,9 @@ dependencies { {{#threetenbp}} compile 'org.threeten:threetenbp:1.4.3' {{/threetenbp}} + {{#dynamicOperations}} + compile 'io.swagger.parser.v3:swagger-parser-v3:2.0.23' + {{/dynamicOperations}} compile 'javax.annotation:javax.annotation-api:1.3.2' testCompile 'junit:junit:4.13.1' } diff --git a/libraries/okhttp-gson/build.sbt.mustache b/libraries/okhttp-gson/build.sbt.mustache index 16c3f694b93..a14047e7998 100644 --- a/libraries/okhttp-gson/build.sbt.mustache +++ b/libraries/okhttp-gson/build.sbt.mustache @@ -23,6 +23,9 @@ lazy val root = (project in file(".")). {{#threetenbp}} "org.threeten" % "threetenbp" % "1.4.3" % "compile", {{/threetenbp}} + {{#dynamicOperations}} + "io.swagger.parser.v3" % "swagger-parser-v3" "2.0.23" % "compile" + {{/dynamicOperations}} "io.gsonfire" % "gson-fire" % "1.8.3" % "compile", "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", "com.google.code.findbugs" % "jsr305" % "3.0.2" % "compile", diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index b97d8ccba01..598312cad6c 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -274,6 +274,13 @@ ${threetenbp-version} {{/threetenbp}} + {{#dynamicOperations}} + + io.swagger.parser.v3 + swagger-parser-v3 + 2.0.23 + + {{/dynamicOperations}} {{#useBeanValidation}} From ec6a912ec52ea5cdb982bb585444dc486204a407 Mon Sep 17 00:00:00 2001 From: agilob Date: Fri, 11 Dec 2020 02:51:57 +0000 Subject: [PATCH 329/370] [java] Generate "static final" instead "final static" (#8158) * Generate java code with "static final" instead "final static" * Regenerate code with "static final" --- libraries/jersey2/anyof_model.mustache | 2 +- libraries/jersey2/oneof_model.mustache | 2 +- libraries/native/anyof_model.mustache | 2 +- libraries/native/oneof_model.mustache | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/jersey2/anyof_model.mustache b/libraries/jersey2/anyof_model.mustache index 668200778ea..8d236677b00 100644 --- a/libraries/jersey2/anyof_model.mustache +++ b/libraries/jersey2/anyof_model.mustache @@ -99,7 +99,7 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im } // store a list of schema names defined in anyOf - public final static Map schemas = new HashMap(); + public static final Map schemas = new HashMap(); public {{classname}}() { super("anyOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); diff --git a/libraries/jersey2/oneof_model.mustache b/libraries/jersey2/oneof_model.mustache index ca2dc49a2e0..eb47106559d 100644 --- a/libraries/jersey2/oneof_model.mustache +++ b/libraries/jersey2/oneof_model.mustache @@ -132,7 +132,7 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im } // store a list of schema names defined in oneOf - public final static Map schemas = new HashMap(); + public static final Map schemas = new HashMap(); public {{classname}}() { super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); diff --git a/libraries/native/anyof_model.mustache b/libraries/native/anyof_model.mustache index 8cba2615105..456f8309c09 100644 --- a/libraries/native/anyof_model.mustache +++ b/libraries/native/anyof_model.mustache @@ -99,7 +99,7 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im } // store a list of schema names defined in anyOf - public final static Map schemas = new HashMap(); + public static final Map schemas = new HashMap(); public {{classname}}() { super("anyOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); diff --git a/libraries/native/oneof_model.mustache b/libraries/native/oneof_model.mustache index f130362ea3d..f2345ab33be 100644 --- a/libraries/native/oneof_model.mustache +++ b/libraries/native/oneof_model.mustache @@ -132,7 +132,7 @@ public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-im } // store a list of schema names defined in oneOf - public final static Map schemas = new HashMap(); + public static final Map schemas = new HashMap(); public {{classname}}() { super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); From b87934c6125e58b003a576245c6e40b22c4da25d Mon Sep 17 00:00:00 2001 From: Tivadar Bocz Date: Fri, 18 Dec 2020 03:05:55 +0100 Subject: [PATCH 330/370] feat(#8038): add url encode feature to WebClient (#8171) --- libraries/webclient/ApiClient.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index e2db597c54c..dcd72c7e113 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -568,7 +568,7 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { builder.queryParams(queryParams); } - final WebClient.RequestBodySpec requestBuilder = webClient.method(method).uri(builder.build(false).toUriString(), pathParams); + final WebClient.RequestBodySpec requestBuilder = webClient.method(method).uri(builder.encode().toUriString(), pathParams); if(accept != null) { requestBuilder.accept(accept.toArray(new MediaType[accept.size()])); } From 2b433488fe4a17ab5d0fc07f0d448ac166272f24 Mon Sep 17 00:00:00 2001 From: agilob Date: Fri, 18 Dec 2020 04:08:30 +0000 Subject: [PATCH 331/370] [java] Add setBearerToken method in okhttp-gson (#8200) * Add setBearerToken method in okhttp-gson * Update generated files --- libraries/okhttp-gson/ApiClient.mustache | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index d417072e334..f12320b3e4b 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -413,6 +413,22 @@ public class ApiClient { return authentications.get(authName); } + {{#hasHttpBearerMethods}} + /** + * Helper method to set access token for the first Bearer authentication. + * @param bearerToken Bearer token + */ + public void setBearerToken(String bearerToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBearerAuth) { + ((HttpBearerAuth) auth).setBearerToken(bearerToken); + return; + } + } + throw new RuntimeException("No Bearer authentication configured!"); + } + {{/hasHttpBearerMethods}} + /** * Helper method to set username for the first HTTP basic authentication. * From 4f07472285eed920a36abebdb5413648c67edd27 Mon Sep 17 00:00:00 2001 From: Nicholas Muesch Date: Sun, 3 Jan 2021 21:54:01 -0500 Subject: [PATCH 332/370] Use Map interface for configureApiKeys (#7982) --- libraries/jersey2/ApiClient.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 713332e20b7..e8833c12611 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -396,7 +396,7 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { * * @param secrets Hash map from authentication name to its secret. */ - public ApiClient configureApiKeys(HashMap secrets) { + public ApiClient configureApiKeys(Map secrets) { for (Map.Entry authEntry : authentications.entrySet()) { Authentication auth = authEntry.getValue(); if (auth instanceof ApiKeyAuth) { From c224e5a621d665b49d27439c8fbb3061cc0cb735 Mon Sep 17 00:00:00 2001 From: Arnaud Jeansen Date: Mon, 4 Jan 2021 04:02:39 +0100 Subject: [PATCH 333/370] =?UTF-8?q?7141:=20filter=20out=20problem+json=20m?= =?UTF-8?q?ime=20type=20from=20JSON=20mime=20types=20fast=20tra=E2=80=A6?= =?UTF-8?q?=20(#7976)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 7141: filter out problem+json mime type from JSON mime types fast tracked into the Accept header (resttemplate) * 7141: ran ensure-up-to-date * 7141: minimize changes with master (keep using isJsonMime for MediaType) --- libraries/resttemplate/ApiClient.mustache | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libraries/resttemplate/ApiClient.mustache b/libraries/resttemplate/ApiClient.mustache index a6687d778cd..315fcdd4415 100644 --- a/libraries/resttemplate/ApiClient.mustache +++ b/libraries/resttemplate/ApiClient.mustache @@ -522,6 +522,15 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { return mediaType != null && (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType) || mediaType.getSubtype().matches("^.*\\+json[;]?\\s*$")); } + /** + * Check if the given {@code String} is a Problem JSON MIME (RFC-7807). + * @param mediaType the input MediaType + * @return boolean true if the MediaType represents Problem JSON, false otherwise + */ + public boolean isProblemJsonMime(String mediaType) { + return "application/problem+json".equalsIgnoreCase(mediaType); + } + /** * Select the Accept header's value from the given accepts array: * if JSON exists in the given array, use it; @@ -536,7 +545,7 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { } for (String accept : accepts) { MediaType mediaType = MediaType.parseMediaType(accept); - if (isJsonMime(mediaType)) { + if (isJsonMime(mediaType) && !isProblemJsonMime(accept)) { return Collections.singletonList(mediaType); } } From d0af10820446a6a0b9dea3e46c6cfd3b49a95583 Mon Sep 17 00:00:00 2001 From: Toby Murray Date: Fri, 15 Jan 2021 09:32:50 -0500 Subject: [PATCH 334/370] Migrate off deprecate Gradle configurations (#8436) A bunch of gradle configurations have been deprecated, with drop in replacements. Relevant to this project: compile -> implementation testCompile -> testImplementation They're visible by executing e.g. ./gradlew build --warning-mode all with supporting documentation here: https://docs.gradle.org/6.6.1/userguide/upgrading_version_5.html#dependencies_should_no_longer_be_declared_using_the_compile_and_runtime_configurations --- build.gradle.mustache | 30 +++++------ libraries/feign/build.gradle.mustache | 34 ++++++------ .../google-api-client/build.gradle.mustache | 32 ++++++------ libraries/jersey2/build.gradle.mustache | 42 +++++++-------- libraries/native/build.gradle.mustache | 22 ++++---- libraries/okhttp-gson/build.gradle.mustache | 26 +++++----- libraries/rest-assured/build.gradle.mustache | 42 +++++++-------- libraries/resteasy/build.gradle.mustache | 36 ++++++------- libraries/resttemplate/build.gradle.mustache | 32 ++++++------ libraries/retrofit/build.gradle.mustache | 18 +++---- libraries/retrofit2/build.gradle.mustache | 52 +++++++++---------- libraries/vertx/build.gradle.mustache | 28 +++++----- libraries/webclient/build.gradle.mustache | 30 +++++------ 13 files changed, 212 insertions(+), 212 deletions(-) diff --git a/build.gradle.mustache b/build.gradle.mustache index 4f408644a9b..0982932dfb0 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -150,30 +150,30 @@ ext { } dependencies { - compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "com.google.code.findbugs:jsr305:3.0.2" - compile "com.sun.jersey:jersey-client:$jersey_version" - compile "com.sun.jersey.contribs:jersey-multipart:$jersey_version" - compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" - compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "com.sun.jersey:jersey-client:$jersey_version" + implementation "com.sun.jersey.contribs:jersey-multipart:$jersey_version" + implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + implementation "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" {{#openApiNullable}} - compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" {{/openApiNullable}} {{#joda}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} {{#java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threetenbp_version" + implementation "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threetenbp_version" {{/threetenbp}} {{^java8}} - compile "com.brsanthu:migbase64:2.2" + implementation "com.brsanthu:migbase64:2.2" {{/java8}} - compile 'javax.annotation:javax.annotation-api:1.3.2' - testCompile "junit:junit:$junit_version" + implementation 'javax.annotation:javax.annotation-api:1.3.2' + testImplementation "junit:junit:$junit_version" } diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index 3f9664b221a..3e00fb91797 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -135,29 +135,29 @@ ext { } dependencies { - compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "com.google.code.findbugs:jsr305:3.0.2" - compile "io.github.openfeign:feign-core:$feign_version" - compile "io.github.openfeign:feign-jackson:$feign_version" - compile "io.github.openfeign:feign-slf4j:$feign_version" - compile "io.github.openfeign.form:feign-form:$feign_form_version" - compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "io.github.openfeign:feign-core:$feign_version" + implementation "io.github.openfeign:feign-jackson:$feign_version" + implementation "io.github.openfeign:feign-slf4j:$feign_version" + implementation "io.github.openfeign.form:feign-form:$feign_form_version" + implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" {{#openApiNullable}} - compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" {{/openApiNullable}} {{#joda}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} {{#java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threetenbp_version" + implementation "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threetenbp_version" {{/threetenbp}} - compile "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version" - compile "com.brsanthu:migbase64:2.2" - compile 'javax.annotation:javax.annotation-api:1.3.2' - testCompile "junit:junit:$junit_version" + implementation "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version" + implementation "com.brsanthu:migbase64:2.2" + implementation 'javax.annotation:javax.annotation-api:1.3.2' + testImplementation "junit:junit:$junit_version" } diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache index 6537bf62f99..496ff42fcce 100644 --- a/libraries/google-api-client/build.gradle.mustache +++ b/libraries/google-api-client/build.gradle.mustache @@ -135,30 +135,30 @@ ext { } dependencies { - compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "com.google.code.findbugs:jsr305:3.0.2" - compile "com.google.api-client:google-api-client:${google_api_client_version}" - compile "org.glassfish.jersey.core:jersey-common:${jersey_common_version}" - compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" - compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "com.google.api-client:google-api-client:${google_api_client_version}" + implementation "org.glassfish.jersey.core:jersey-common:${jersey_common_version}" + implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + implementation "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" {{#openApiNullable}} - compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" {{/openApiNullable}} {{#java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} {{#joda}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" - compile "joda-time:joda-time:$jodatime_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + implementation "joda-time:joda-time:$jodatime_version" {{/joda}} {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threeten_version" + implementation "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threeten_version" {{/threetenbp}} {{#withXml}} - compile "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jackson_version" + implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jackson_version" {{/withXml}} - compile 'javax.annotation:javax.annotation-api:1.3.2' - testCompile "junit:junit:$junit_version" + implementation 'javax.annotation:javax.annotation-api:1.3.2' + testImplementation "junit:junit:$junit_version" } diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index 392c3fda0b2..9292d599cad 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -145,43 +145,43 @@ ext { } dependencies { - compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "com.google.code.findbugs:jsr305:3.0.2" - compile "org.glassfish.jersey.core:jersey-client:$jersey_version" - compile "org.glassfish.jersey.inject:jersey-hk2:$jersey_version" - compile "org.glassfish.jersey.media:jersey-media-multipart:$jersey_version" - compile "org.glassfish.jersey.media:jersey-media-json-jackson:$jersey_version" - compile "org.glassfish.jersey.connectors:jersey-apache-connector:$jersey_version" - compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "org.glassfish.jersey.core:jersey-client:$jersey_version" + implementation "org.glassfish.jersey.inject:jersey-hk2:$jersey_version" + implementation "org.glassfish.jersey.media:jersey-media-multipart:$jersey_version" + implementation "org.glassfish.jersey.media:jersey-media-json-jackson:$jersey_version" + implementation "org.glassfish.jersey.connectors:jersey-apache-connector:$jersey_version" + implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" {{#openApiNullable}} - compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" {{/openApiNullable}} {{#joda}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} {{#java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} {{#hasOAuthMethods}} - compile "com.github.scribejava:scribejava-apis:$scribejava_apis_version" + implementation "com.github.scribejava:scribejava-apis:$scribejava_apis_version" {{/hasOAuthMethods}} {{#hasHttpSignatureMethods}} - compile "org.tomitribe:tomitribe-http-signatures:$tomitribe_http_signatures_version" + implementation "org.tomitribe:tomitribe-http-signatures:$tomitribe_http_signatures_version" {{/hasHttpSignatureMethods}} {{#supportJava6}} - compile "commons-io:commons-io:$commons_io_version" - compile "org.apache.commons:commons-lang3:$commons_lang3_version" + implementation "commons-io:commons-io:$commons_io_version" + implementation "org.apache.commons:commons-lang3:$commons_lang3_version" {{/supportJava6}} {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$threetenbp_version" + implementation "com.github.joschi.jackson:jackson-datatype-threetenbp:$threetenbp_version" {{/threetenbp}} {{^java8}} - compile "com.brsanthu:migbase64:2.2" + implementation "com.brsanthu:migbase64:2.2" {{/java8}} - compile 'javax.annotation:javax.annotation-api:1.3.2' - testCompile "junit:junit:$junit_version" + implementation 'javax.annotation:javax.annotation-api:1.3.2' + testImplementation "junit:junit:$junit_version" } javadoc { diff --git a/libraries/native/build.gradle.mustache b/libraries/native/build.gradle.mustache index 312d1f5db1f..e1967261a11 100644 --- a/libraries/native/build.gradle.mustache +++ b/libraries/native/build.gradle.mustache @@ -60,17 +60,17 @@ ext { } dependencies { - compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "com.google.code.findbugs:jsr305:3.0.2" - compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" - compile "org.openapitools:jackson-databind-nullable:0.2.1" - compile 'javax.annotation:javax.annotation-api:1.3.2' - compile "javax.ws.rs:javax.ws.rs-api:$ws_rs_version" + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + implementation "org.openapitools:jackson-databind-nullable:0.2.1" + implementation 'javax.annotation:javax.annotation-api:1.3.2' + implementation "javax.ws.rs:javax.ws.rs-api:$ws_rs_version" {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$threetenbp_version" + implementation "com.github.joschi.jackson:jackson-datatype-threetenbp:$threetenbp_version" {{/threetenbp}} - testCompile "junit:junit:$junit_version" + testImplementation "junit:junit:$junit_version" } diff --git a/libraries/okhttp-gson/build.gradle.mustache b/libraries/okhttp-gson/build.gradle.mustache index 8f10fd4e728..104fe6d0ff1 100644 --- a/libraries/okhttp-gson/build.gradle.mustache +++ b/libraries/okhttp-gson/build.gradle.mustache @@ -126,27 +126,27 @@ if(hasProperty('target') && target == 'android') { } dependencies { - compile 'io.swagger:swagger-annotations:1.5.24' - compile "com.google.code.findbugs:jsr305:3.0.2" - compile 'com.squareup.okhttp3:okhttp:3.14.7' - compile 'com.squareup.okhttp3:logging-interceptor:3.14.7' - compile 'com.google.code.gson:gson:2.8.6' - compile 'io.gsonfire:gson-fire:1.8.4' + implementation 'io.swagger:swagger-annotations:1.5.24' + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation 'com.squareup.okhttp3:okhttp:3.14.7' + implementation 'com.squareup.okhttp3:logging-interceptor:3.14.7' + implementation 'com.google.code.gson:gson:2.8.6' + implementation 'io.gsonfire:gson-fire:1.8.4' {{#hasOAuthMethods}} - compile group: 'org.apache.oltu.oauth2', name: 'org.apache.oltu.oauth2.client', version: '1.0.1' + implementation group: 'org.apache.oltu.oauth2', name: 'org.apache.oltu.oauth2.client', version: '1.0.1' {{/hasOAuthMethods}} - compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.10' + implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.10' {{#joda}} - compile 'joda-time:joda-time:2.9.9' + implementation 'joda-time:joda-time:2.9.9' {{/joda}} {{#threetenbp}} - compile 'org.threeten:threetenbp:1.4.3' + implementation 'org.threeten:threetenbp:1.4.3' {{/threetenbp}} {{#dynamicOperations}} - compile 'io.swagger.parser.v3:swagger-parser-v3:2.0.23' + implementation 'io.swagger.parser.v3:swagger-parser-v3:2.0.23' {{/dynamicOperations}} - compile 'javax.annotation:javax.annotation-api:1.3.2' - testCompile 'junit:junit:4.13.1' + implementation 'javax.annotation:javax.annotation-api:1.3.2' + testImplementation 'junit:junit:4.13.1' } javadoc { diff --git a/libraries/rest-assured/build.gradle.mustache b/libraries/rest-assured/build.gradle.mustache index 47d9a13ea3e..28c213b41b7 100644 --- a/libraries/rest-assured/build.gradle.mustache +++ b/libraries/rest-assured/build.gradle.mustache @@ -122,47 +122,47 @@ ext { } dependencies { - compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "com.google.code.findbugs:jsr305:3.0.2" - compile "io.rest-assured:rest-assured:$rest_assured_version" + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "io.rest-assured:rest-assured:$rest_assured_version" {{#jackson}} - compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" - compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + implementation "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" {{#openApiNullable}} - compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" {{/openApiNullable}} {{#withXml}} - compile "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jackson_version" + implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jackson_version" {{/withXml}} {{#joda}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} {{#java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threetenbp_version" + implementation "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threetenbp_version" {{/threetenbp}} {{/jackson}} {{#gson}} - compile "io.gsonfire:gson-fire:$gson_fire_version" - compile 'com.google.code.gson:gson:$gson_version' + implementation "io.gsonfire:gson-fire:$gson_fire_version" + implementation 'com.google.code.gson:gson:$gson_version' {{/gson}} {{#joda}} - compile "joda-time:joda-time:$jodatime_version" + implementation "joda-time:joda-time:$jodatime_version" {{/joda}} {{#threetenbp}} - compile "org.threeten:threetenbp:$threetenbp_version" + implementation "org.threeten:threetenbp:$threetenbp_version" {{/threetenbp}} - compile "com.squareup.okio:okio:$okio_version" + implementation "com.squareup.okio:okio:$okio_version" {{#useBeanValidation}} - compile "javax.validation:validation-api:2.0.1.Final" + implementation "javax.validation:validation-api:2.0.1.Final" {{/useBeanValidation}} {{#performBeanValidation}} - compile "org.hibernate:hibernate-validator:6.0.19.Final" + implementation "org.hibernate:hibernate-validator:6.0.19.Final" {{/performBeanValidation}} - compile 'javax.annotation:javax.annotation-api:1.3.2' - testCompile "junit:junit:$junit_version" + implementation 'javax.annotation:javax.annotation-api:1.3.2' + testImplementation "junit:junit:$junit_version" } diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index e2b6913c672..ed3020519df 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -137,30 +137,30 @@ ext { } dependencies { - compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "com.google.code.findbugs:jsr305:3.0.2" - compile "org.jboss.resteasy:resteasy-client:$resteasy_version" - compile "org.jboss.resteasy:resteasy-multipart-provider:$resteasy_version" - compile "org.jboss.resteasy:resteasy-jackson2-provider:$resteasy_version" - compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$threetenbp_version" + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "org.jboss.resteasy:resteasy-client:$resteasy_version" + implementation "org.jboss.resteasy:resteasy-multipart-provider:$resteasy_version" + implementation "org.jboss.resteasy:resteasy-jackson2-provider:$resteasy_version" + implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + implementation "com.github.joschi.jackson:jackson-datatype-threetenbp:$threetenbp_version" {{#openApiNullable}} - compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" {{/openApiNullable}} {{#java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} {{^java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" - compile "joda-time:joda-time:$jodatime_version" - compile "com.brsanthu:migbase64:2.2" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + implementation "joda-time:joda-time:$jodatime_version" + implementation "com.brsanthu:migbase64:2.2" {{/java8}} {{#supportJava6}} - compile "commons-io:commons-io:$commons_io_version" - compile "org.apache.commons:commons-lang3:$commons_lang3_version" + implementation "commons-io:commons-io:$commons_io_version" + implementation "org.apache.commons:commons-lang3:$commons_lang3_version" {{/supportJava6}} - compile 'javax.annotation:javax.annotation-api:1.3.2' - testCompile "junit:junit:$junit_version" + implementation 'javax.annotation:javax.annotation-api:1.3.2' + testImplementation "junit:junit:$junit_version" } diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index 57606f07311..d41aa90de15 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -134,30 +134,30 @@ ext { } dependencies { - compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "com.google.code.findbugs:jsr305:3.0.2" - compile "org.springframework:spring-web:$spring_web_version" - compile "org.springframework:spring-context:$spring_web_version" - compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" - compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "org.springframework:spring-web:$spring_web_version" + implementation "org.springframework:spring-context:$spring_web_version" + implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + implementation "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" {{#openApiNullable}} - compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" {{/openApiNullable}} {{#java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} {{#joda}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" - compile "joda-time:joda-time:$jodatime_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + implementation "joda-time:joda-time:$jodatime_version" {{/joda}} {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threeten_version" + implementation "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threeten_version" {{/threetenbp}} {{#withXml}} - compile "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jackson_version" + implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jackson_version" {{/withXml}} - compile 'javax.annotation:javax.annotation-api:1.3.2' - testCompile "junit:junit:$junit_version" + implementation 'javax.annotation:javax.annotation-api:1.3.2' + testImplementation "junit:junit:$junit_version" } diff --git a/libraries/retrofit/build.gradle.mustache b/libraries/retrofit/build.gradle.mustache index 14ce3d1dafd..cd1096e5723 100644 --- a/libraries/retrofit/build.gradle.mustache +++ b/libraries/retrofit/build.gradle.mustache @@ -119,15 +119,15 @@ ext { } dependencies { - compile "com.squareup.okhttp:okhttp:$okhttp_version" - compile "com.google.code.findbugs:jsr305:3.0.2" - compile "com.squareup.retrofit:retrofit:$retrofit_version" - compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version" - compile "joda-time:joda-time:$jodatime_version" + implementation "com.squareup.okhttp:okhttp:$okhttp_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "com.squareup.retrofit:retrofit:$retrofit_version" + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version" + implementation "joda-time:joda-time:$jodatime_version" {{#threetenbp}} - compile "org.threeten:threetenbp:$threetenbp_version" + implementation "org.threeten:threetenbp:$threetenbp_version" {{/threetenbp}} - compile 'javax.annotation:javax.annotation-api:1.3.2' - testCompile "junit:junit:$junit_version" + implementation 'javax.annotation:javax.annotation-api:1.3.2' + testImplementation "junit:junit:$junit_version" } diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index 3ea42a41dc3..517d6a4e844 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -158,50 +158,50 @@ ext { } dependencies { - compile "com.squareup.retrofit2:retrofit:$retrofit_version" - compile "com.squareup.retrofit2:converter-scalars:$retrofit_version" - compile "com.squareup.retrofit2:converter-gson:$retrofit_version" + implementation "com.squareup.retrofit2:retrofit:$retrofit_version" + implementation "com.squareup.retrofit2:converter-scalars:$retrofit_version" + implementation "com.squareup.retrofit2:converter-gson:$retrofit_version" {{#useRxJava}} - compile "com.squareup.retrofit2:adapter-rxjava:$retrofit_version" - compile "io.reactivex:rxjava:$rx_java_version" + implementation "com.squareup.retrofit2:adapter-rxjava:$retrofit_version" + implementation "io.reactivex:rxjava:$rx_java_version" {{/useRxJava}} {{#useRxJava2}} - compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' - compile "io.reactivex.rxjava2:rxjava:$rx_java_version" + implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' + implementation "io.reactivex.rxjava2:rxjava:$rx_java_version" {{/useRxJava2}} {{#useRxJava3}} - compile 'com.github.akarnokd:rxjava3-retrofit-adapter:3.0.0' - compile "io.reactivex.rxjava3:rxjava:$rx_java_version" + implementation 'com.github.akarnokd:rxjava3-retrofit-adapter:3.0.0' + implementation "io.reactivex.rxjava3:rxjava:$rx_java_version" {{/useRxJava3}} - compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "com.google.code.findbugs:jsr305:3.0.2" - compile ("org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version"){ + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation ("org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version"){ exclude group:'org.apache.oltu.oauth2' , module: 'org.apache.oltu.oauth2.common' } - compile "io.gsonfire:gson-fire:$json_fire_version" + implementation "io.gsonfire:gson-fire:$json_fire_version" {{#joda}} - compile "joda-time:joda-time:$jodatime_version" + implementation "joda-time:joda-time:$jodatime_version" {{/joda}} {{#threetenbp}} - compile "org.threeten:threetenbp:$threetenbp_version" + implementation "org.threeten:threetenbp:$threetenbp_version" {{/threetenbp}} {{#usePlayWS}} {{#play26}} - compile "com.typesafe.play:play-ahc-ws_2.12:$play_version" - compile "javax.validation:validation-api:1.1.0.Final" + implementation "com.typesafe.play:play-ahc-ws_2.12:$play_version" + implementation "javax.validation:validation-api:1.1.0.Final" {{/play26}} {{^play26}} - compile "com.typesafe.play:play-java-ws_2.11:$play_version" + implementation "com.typesafe.play:play-java-ws_2.11:$play_version" {{/play26}} - compile "com.squareup.retrofit2:converter-jackson:$retrofit_version" - compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + implementation "com.squareup.retrofit2:converter-jackson:$retrofit_version" + implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" {{#openApiNullable}} - compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" {{/openApiNullable}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}:$jackson_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}:$jackson_version" {{/usePlayWS}} - compile 'javax.annotation:javax.annotation-api:1.3.2' - testCompile "junit:junit:$junit_version" + implementation 'javax.annotation:javax.annotation-api:1.3.2' + testImplementation "junit:junit:$junit_version" } diff --git a/libraries/vertx/build.gradle.mustache b/libraries/vertx/build.gradle.mustache index 3166da0d84a..cb2910c8430 100644 --- a/libraries/vertx/build.gradle.mustache +++ b/libraries/vertx/build.gradle.mustache @@ -41,26 +41,26 @@ ext { } dependencies { - compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "com.google.code.findbugs:jsr305:3.0.2" - compile "io.vertx:vertx-web-client:$vertx_version" - compile "io.vertx:vertx-rx-java:$vertx_version" - compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "io.vertx:vertx-web-client:$vertx_version" + implementation "io.vertx:vertx-rx-java:$vertx_version" + implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" {{#joda}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} {{#java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:jackson_threeten_version" + implementation "com.github.joschi.jackson:jackson-datatype-threetenbp:jackson_threeten_version" {{/threetenbp}} {{#openApiNullable}} - compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" {{/openApiNullable}} - compile 'javax.annotation:javax.annotation-api:1.3.2' - testCompile "junit:junit:$junit_version" - testCompile "io.vertx:vertx-unit:$vertx_version" + implementation 'javax.annotation:javax.annotation-api:1.3.2' + testImplementation "junit:junit:$junit_version" + testImplementation "io.vertx:vertx-unit:$vertx_version" } diff --git a/libraries/webclient/build.gradle.mustache b/libraries/webclient/build.gradle.mustache index f6c8ac6438c..028d9e5cc51 100644 --- a/libraries/webclient/build.gradle.mustache +++ b/libraries/webclient/build.gradle.mustache @@ -150,28 +150,28 @@ ext { } dependencies { - compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "com.google.code.findbugs:jsr305:3.0.2" - compile "io.projectreactor:reactor-core:$reactor_version" - compile "org.springframework:spring-webflux:$spring_web_version" - compile "io.projectreactor.ipc:reactor-netty:$reactor_netty_version" - compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" - compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "io.projectreactor:reactor-core:$reactor_version" + implementation "org.springframework:spring-webflux:$spring_web_version" + implementation "io.projectreactor.ipc:reactor-netty:$reactor_netty_version" + implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + implementation "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" {{#openApiNullable}} - compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" {{/openApiNullable}} {{#joda}} - compile "joda-time:joda-time:$jodatime_version" + implementation "joda-time:joda-time:$jodatime_version" {{/joda}} {{#java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} {{^java8}} - compile "com.brsanthu:migbase64:2.2" + implementation "com.brsanthu:migbase64:2.2" {{/java8}} - compile "javax.annotation:javax.annotation-api:$javax_annotation_version" - testCompile "junit:junit:$junit_version" + implementation "javax.annotation:javax.annotation-api:$javax_annotation_version" + testImplementation "junit:junit:$junit_version" } From f7234db22dfda37da6828e97098a8af3bc211497 Mon Sep 17 00:00:00 2001 From: Hugo Alves Date: Tue, 19 Jan 2021 04:41:25 +0000 Subject: [PATCH 335/370] [JAVA][Feign] Replace Apache oltu with scribejava (#8318) * - Replace apache oltu with scribejava - Implement the following authentication methods - ApiKey header - HTTP basic authentication - Oauth client credentials flow - Oauth Implicit flow - Oauth Pasword (deprecated) * Create class hierarchy for Oauth flows implementation * Add instructions of how to use the ApiClient to Readme.md * Update samples * Remove support for java 6 and 7 * Remove java 6 and 7 support from gradle * Format pom.xml * Remove empty line * Update samples * Remove oltu dependency from build.gradle and build.sbt. Replace oltu with ScribeJava Update samples * Update samples * Update samples --- auth/OAuthFlow.mustache | 6 +- libraries/feign/ApiClient.mustache | 169 ++++--------- libraries/feign/README.mustache | 36 ++- .../feign/auth/DefaultApi20Impl.mustache | 47 ++++ libraries/feign/auth/OAuth.mustache | 229 +++++------------- .../auth/OauthClientCredentialsGrant.mustache | 39 +++ .../feign/auth/OauthPasswordGrant.mustache | 48 ++++ libraries/feign/build.gradle.mustache | 29 +-- libraries/feign/build.sbt.mustache | 2 +- libraries/feign/pom.mustache | 66 +++-- 10 files changed, 314 insertions(+), 357 deletions(-) create mode 100644 libraries/feign/auth/DefaultApi20Impl.mustache create mode 100644 libraries/feign/auth/OauthClientCredentialsGrant.mustache create mode 100644 libraries/feign/auth/OauthPasswordGrant.mustache diff --git a/auth/OAuthFlow.mustache b/auth/OAuthFlow.mustache index 002e9572f33..07b7f3aa673 100644 --- a/auth/OAuthFlow.mustache +++ b/auth/OAuthFlow.mustache @@ -2,6 +2,10 @@ package {{invokerPackage}}.auth; +{{>generatedAnnotation}} public enum OAuthFlow { - accessCode, implicit, password, application + accessCode, //called authorizationCode in OpenAPI 3.0 + implicit, + password, + application //called clientCredentials in OpenAPI 3.0 } diff --git a/libraries/feign/ApiClient.mustache b/libraries/feign/ApiClient.mustache index 691f337c7c5..54201a1c615 100644 --- a/libraries/feign/ApiClient.mustache +++ b/libraries/feign/ApiClient.mustache @@ -2,11 +2,8 @@ package {{invokerPackage}}; import java.util.LinkedHashMap; import java.util.Map; - -{{#hasOAuthMethods}} -import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; -import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; -{{/hasOAuthMethods}} +import java.util.logging.Level; +import java.util.logging.Logger; {{#threetenbp}} import org.threeten.bp.*; @@ -41,6 +38,8 @@ import {{invokerPackage}}.auth.OAuth.AccessTokenListener; {{>generatedAnnotation}} public class ApiClient { + private static final Logger log = Logger.getLogger(ApiClient.class.getName()); + public interface Api {} protected ObjectMapper objectMapper; @@ -60,6 +59,7 @@ public class ApiClient { public ApiClient(String[] authNames) { this(); for(String authName : authNames) { + log.log(Level.FINE, "Creating authentication {0}", authName); {{#hasAuthMethods}} RequestInterceptor auth; {{#authMethods}}if ("{{name}}".equals(authName)) { @@ -75,7 +75,7 @@ public class ApiClient { auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"); {{/isApiKey}} {{#isOAuth}} - auth = new OAuth(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{^-last}}, {{/-last}}{{/scopes}}"); + auth = buildOauthRequestInterceptor(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{^-last}}, {{/-last}}{{/scopes}}"); {{/isOAuth}} } else {{/authMethods}}{ throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); @@ -106,36 +106,6 @@ public class ApiClient { this.setApiKey(apiKey); } - /** - * Helper constructor for single basic auth or password oauth2 - * @param authName - * @param username - * @param password - */ - public ApiClient(String authName, String username, String password) { - this(authName); - this.setCredentials(username, password); - } - - {{#hasOAuthMethods}} - /** - * Helper constructor for single password oauth2 - * @param authName - * @param clientId - * @param secret - * @param username - * @param password - */ - public ApiClient(String authName, String clientId, String secret, String username, String password) { - this(authName); - this.getTokenEndPoint() - .setClientId(clientId) - .setClientSecret(secret) - .setUsername(username) - .setPassword(password); - } - - {{/hasOAuthMethods}} public String getBasePath() { return basePath; } @@ -190,10 +160,25 @@ public class ApiClient { return objectMapper; } + private RequestInterceptor buildOauthRequestInterceptor(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { + switch (flow) { + case password: + return new OauthPasswordGrant(tokenUrl, scopes); + case application: + return new OauthClientCredentialsGrant(authorizationUrl, tokenUrl, scopes); + default: + throw new RuntimeException("Oauth flow \"" + flow + "\" is not implemented"); + } + } + public ObjectMapper getObjectMapper(){ return objectMapper; } + public void setObjectMapper(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + /** * Creates a feign client for given API interface. * @@ -240,19 +225,13 @@ public class ApiClient { return contentTypes[0]; } - /** * Helper method to configure the bearer token. * @param bearerToken the bearer token. */ public void setBearerToken(String bearerToken) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof HttpBearerAuth) { - ((HttpBearerAuth) apiAuthorization).setBearerToken(bearerToken); - return; - } - } - throw new RuntimeException("No Bearer authentication configured!"); + HttpBearerAuth apiAuthorization = getAuthorization(HttpBearerAuth.class); + apiAuthorization.setBearerToken(bearerToken); } /** @@ -260,66 +239,39 @@ public class ApiClient { * @param apiKey API key */ public void setApiKey(String apiKey) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof ApiKeyAuth) { - ApiKeyAuth keyAuth = (ApiKeyAuth) apiAuthorization; - keyAuth.setApiKey(apiKey); - return ; - } - } - throw new RuntimeException("No API key authentication configured!"); + ApiKeyAuth apiAuthorization = getAuthorization(ApiKeyAuth.class); + apiAuthorization.setApiKey(apiKey); } /** - * Helper method to configure the username/password for basic auth or password OAuth + * Helper method to configure the username/password for basic auth * @param username Username * @param password Password */ public void setCredentials(String username, String password) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof HttpBasicAuth) { - HttpBasicAuth basicAuth = (HttpBasicAuth) apiAuthorization; - basicAuth.setCredentials(username, password); - return; - } - {{#hasOAuthMethods}} - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - oauth.getTokenRequestBuilder().setUsername(username).setPassword(password); - return; - } - {{/hasOAuthMethods}} - } - throw new RuntimeException("No Basic authentication or OAuth configured!"); + HttpBasicAuth apiAuthorization = getAuthorization(HttpBasicAuth.class); + apiAuthorization.setCredentials(username, password); } {{#hasOAuthMethods}} /** - * Helper method to configure the token endpoint of the first oauth found in the apiAuthorizations (there should be only one) - * @return Token request builder + * Helper method to configure the client credentials for Oauth + * @param username Username + * @param password Password */ - public TokenRequestBuilder getTokenEndPoint() { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - return oauth.getTokenRequestBuilder(); - } - } - return null; + public void setClientCredentials(String clientId, String clientSecret) { + OauthClientCredentialsGrant authorization = getAuthorization(OauthClientCredentialsGrant.class); + authorization.configure(clientId, clientSecret); } /** - * Helper method to configure authorization endpoint of the first oauth found in the apiAuthorizations (there should be only one) - * @return Authentication request builder + * Helper method to configure the username/password for Oauth password grant + * @param username Username + * @param password Password */ - public AuthenticationRequestBuilder getAuthorizationEndPoint() { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - return oauth.getAuthenticationRequestBuilder(); - } - } - return null; + public void setOauthPassword(String username, String password, String clientId, String clientSecret) { + OauthPasswordGrant apiAuthorization = getAuthorization(OauthPasswordGrant.class); + apiAuthorization.configure(username, password, clientId, clientSecret); } /** @@ -327,14 +279,9 @@ public class ApiClient { * @param accessToken Access Token * @param expiresIn Validity period in seconds */ - public void setAccessToken(String accessToken, Long expiresIn) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - oauth.setAccessToken(accessToken, expiresIn); - return; - } - } + public void setAccessToken(String accessToken, Integer expiresIn) { + OAuth apiAuthorization = getAuthorization(OAuth.class); + apiAuthorization.setAccessToken(accessToken, expiresIn); } /** @@ -344,19 +291,7 @@ public class ApiClient { * @param redirectURI Redirect URI */ public void configureAuthorizationFlow(String clientId, String clientSecret, String redirectURI) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - oauth.getTokenRequestBuilder() - .setClientId(clientId) - .setClientSecret(clientSecret) - .setRedirectURI(redirectURI); - oauth.getAuthenticationRequestBuilder() - .setClientId(clientId) - .setRedirectURI(redirectURI); - return; - } - } + throw new RuntimeException("Not implemented"); } /** @@ -364,13 +299,8 @@ public class ApiClient { * @param accessTokenListener Acesss token listener */ public void registerAccessTokenListener(AccessTokenListener accessTokenListener) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - oauth.registerAccessTokenListener(accessTokenListener); - return; - } - } + OAuth apiAuthorization = getAuthorization(OAuth.class); + apiAuthorization.registerAccessTokenListener(accessTokenListener); } {{/hasOAuthMethods}} @@ -396,4 +326,11 @@ public class ApiClient { feignBuilder.requestInterceptor(authorization); } + private T getAuthorization(Class type) { + return (T) apiAuthorizations.values() + .stream() + .filter(requestInterceptor -> type.isAssignableFrom(requestInterceptor.getClass())) + .findFirst() + .orElseThrow(() -> new RuntimeException("No Oauth authentication or OAuth configured!")); + } } diff --git a/libraries/feign/README.mustache b/libraries/feign/README.mustache index a0fac9d41df..acab659406d 100644 --- a/libraries/feign/README.mustache +++ b/libraries/feign/README.mustache @@ -32,6 +32,41 @@ After the client library is installed/deployed, you can use it in your Maven pro ``` +And to use the api you can follow the examples bellow: + +```java + + //Set bearer token manually + ApiClient apiClient = new ApiClient("petstore_auth_client"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + apiClient.setAccessToken("TOKEN", 10000); + + //Use api key + ApiClient apiClient = new ApiClient("api_key", "API KEY"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + + //Use http basic authentication + ApiClient apiClient = new ApiClient("basicAuth"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + apiClient.setCredentials("username", "password"); + + //Oauth password + ApiClient apiClient = new ApiClient("oauth_password"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + apiClient.setOauthPassword("username", "password", "client_id", "client_secret"); + + //Oauth client credentials flow + ApiClient apiClient = new ApiClient("oauth_client_credentials"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + apiClient.setClientCredentials("client_id", "client_secret"); + + PetApi petApi = apiClient.buildClient(PetApi.class); + Pet petById = petApi.getPetById(12345L); + + System.out.println(petById); + } +``` + ## Recommendation It's recommended to create an instance of `ApiClient` per thread in a multithreaded environment to avoid any potential issues. @@ -40,4 +75,3 @@ It's recommended to create an instance of `ApiClient` per thread in a multithrea {{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}} {{/-last}}{{/apis}}{{/apiInfo}} - diff --git a/libraries/feign/auth/DefaultApi20Impl.mustache b/libraries/feign/auth/DefaultApi20Impl.mustache new file mode 100644 index 00000000000..72b0a00495e --- /dev/null +++ b/libraries/feign/auth/DefaultApi20Impl.mustache @@ -0,0 +1,47 @@ +package {{invokerPackage}}.auth; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor; +import com.github.scribejava.core.extractors.TokenExtractor; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignatureURIQueryParameter; +import com.github.scribejava.core.oauth2.clientauthentication.ClientAuthentication; +import com.github.scribejava.core.oauth2.clientauthentication.RequestBodyAuthenticationScheme; + +{{>generatedAnnotation}} +public class DefaultApi20Impl extends DefaultApi20 { + + private final String accessTokenEndpoint; + private final String authorizationBaseUrl; + + protected DefaultApi20Impl(String authorizationBaseUrl, String accessTokenEndpoint) { + this.authorizationBaseUrl = authorizationBaseUrl; + this.accessTokenEndpoint = accessTokenEndpoint; + } + + @Override + public String getAccessTokenEndpoint() { + return accessTokenEndpoint; + } + + @Override + protected String getAuthorizationBaseUrl() { + return authorizationBaseUrl; + } + + @Override + public BearerSignature getBearerSignature() { + return BearerSignatureURIQueryParameter.instance(); + } + + @Override + public ClientAuthentication getClientAuthentication() { + return RequestBodyAuthenticationScheme.instance(); + } + + @Override + public TokenExtractor getAccessTokenExtractor() { + return OAuth2AccessTokenJsonExtractor.instance(); + } +} \ No newline at end of file diff --git a/libraries/feign/auth/OAuth.mustache b/libraries/feign/auth/OAuth.mustache index b451e97ae6e..864ee3fe3a5 100644 --- a/libraries/feign/auth/OAuth.mustache +++ b/libraries/feign/auth/OAuth.mustache @@ -1,198 +1,81 @@ package {{invokerPackage}}.auth; -import java.io.IOException; -import java.util.Collection; -import java.util.Map; -import java.util.Map.Entry; - -import org.apache.oltu.oauth2.client.HttpClient; -import org.apache.oltu.oauth2.client.OAuthClient; -import org.apache.oltu.oauth2.client.request.OAuthClientRequest; -import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; -import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; -import org.apache.oltu.oauth2.client.response.OAuthClientResponse; -import org.apache.oltu.oauth2.client.response.OAuthClientResponseFactory; -import org.apache.oltu.oauth2.client.response.OAuthJSONAccessTokenResponse; -import org.apache.oltu.oauth2.common.exception.OAuthProblemException; -import org.apache.oltu.oauth2.common.exception.OAuthSystemException; -import org.apache.oltu.oauth2.common.message.types.GrantType; -import org.apache.oltu.oauth2.common.token.BasicOAuthToken; - -import feign.Client; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth.OAuth20Service; import feign.Request.HttpMethod; -import feign.Request.Options; import feign.RequestInterceptor; import feign.RequestTemplate; -import feign.Response; import feign.RetryableException; -import feign.Util; -import {{invokerPackage}}.StringUtil; - - -public class OAuth implements RequestInterceptor { - static final int MILLIS_PER_SECOND = 1000; +{{>generatedAnnotation}} +public abstract class OAuth implements RequestInterceptor { - public interface AccessTokenListener { - void notify(BasicOAuthToken token); - } + static final int MILLIS_PER_SECOND = 1000; - private volatile String accessToken; - private Long expirationTimeMillis; - private OAuthClient oauthClient; - private TokenRequestBuilder tokenRequestBuilder; - private AuthenticationRequestBuilder authenticationRequestBuilder; - private AccessTokenListener accessTokenListener; + public interface AccessTokenListener { + void notify(OAuth2AccessToken token); + } - public OAuth(Client client, TokenRequestBuilder requestBuilder) { - this.oauthClient = new OAuthClient(new OAuthFeignClient(client)); - this.tokenRequestBuilder = requestBuilder; - } + private volatile String accessToken; + private Long expirationTimeMillis; + private AccessTokenListener accessTokenListener; - public OAuth(Client client, OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { - this(client, OAuthClientRequest.tokenLocation(tokenUrl).setScope(scopes)); + protected OAuth20Service service; + protected String scopes; + protected String authorizationUrl; + protected String tokenUrl; - switch(flow) { - case accessCode: - case implicit: - tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE); - break; - case password: - tokenRequestBuilder.setGrantType(GrantType.PASSWORD); - break; - case application: - tokenRequestBuilder.setGrantType(GrantType.CLIENT_CREDENTIALS); - break; - default: - break; - } - authenticationRequestBuilder = OAuthClientRequest.authorizationLocation(authorizationUrl); - } + public OAuth(String authorizationUrl, String tokenUrl, String scopes) { + this.scopes = scopes; + this.authorizationUrl = authorizationUrl; + this.tokenUrl = tokenUrl; + } - public OAuth(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { - this(new Client.Default(null, null), flow, authorizationUrl, tokenUrl, scopes); + @Override + public void apply(RequestTemplate template) { + // If the request already have an authorization (eg. Basic auth), do nothing + if (template.headers().containsKey("Authorization")) { + return; } - - @Override - public void apply(RequestTemplate template) { - // If the request already have an authorization (eg. Basic auth), do nothing - if (template.headers().containsKey("Authorization")) { - return; - } - // If first time, get the token - if (expirationTimeMillis == null || System.currentTimeMillis() >= expirationTimeMillis) { - updateAccessToken(template); - } - if (getAccessToken() != null) { - template.header("Authorization", "Bearer " + getAccessToken()); - } + // If first time, get the token + if (expirationTimeMillis == null || System.currentTimeMillis() >= expirationTimeMillis) { + updateAccessToken(template); } - - public synchronized void updateAccessToken(RequestTemplate template) { - OAuthJSONAccessTokenResponse accessTokenResponse; - try { - accessTokenResponse = oauthClient.accessToken(tokenRequestBuilder.buildBodyMessage()); - } catch (Exception e) { - throw new RetryableException(0, e.getMessage(), HttpMethod.POST, e, null, template.request()); - } - if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { - setAccessToken(accessTokenResponse.getAccessToken(), accessTokenResponse.getExpiresIn()); - if (accessTokenListener != null) { - accessTokenListener.notify((BasicOAuthToken) accessTokenResponse.getOAuthToken()); - } - } + if (getAccessToken() != null) { + template.header("Authorization", "Bearer " + getAccessToken()); } + } - public synchronized void registerAccessTokenListener(AccessTokenListener accessTokenListener) { - this.accessTokenListener = accessTokenListener; + private synchronized void updateAccessToken(RequestTemplate template) { + OAuth2AccessToken accessTokenResponse; + try { + accessTokenResponse = getOAuth2AccessToken(); + } catch (Exception e) { + throw new RetryableException(0, e.getMessage(), HttpMethod.POST, e, null, template.request()); } - - public synchronized String getAccessToken() { - return accessToken; + if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { + setAccessToken(accessTokenResponse.getAccessToken(), accessTokenResponse.getExpiresIn()); + if (accessTokenListener != null) { + accessTokenListener.notify(accessTokenResponse); + } } + } - public synchronized void setAccessToken(String accessToken, Long expiresIn) { - this.accessToken = accessToken; - this.expirationTimeMillis = expiresIn == null ? null : System.currentTimeMillis() + expiresIn * MILLIS_PER_SECOND; - } + abstract OAuth2AccessToken getOAuth2AccessToken(); - public TokenRequestBuilder getTokenRequestBuilder() { - return tokenRequestBuilder; - } + abstract OAuthFlow getFlow(); - public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) { - this.tokenRequestBuilder = tokenRequestBuilder; - } + public synchronized void registerAccessTokenListener(AccessTokenListener accessTokenListener) { + this.accessTokenListener = accessTokenListener; + } - public AuthenticationRequestBuilder getAuthenticationRequestBuilder() { - return authenticationRequestBuilder; - } + public synchronized String getAccessToken() { + return accessToken; + } - public void setAuthenticationRequestBuilder(AuthenticationRequestBuilder authenticationRequestBuilder) { - this.authenticationRequestBuilder = authenticationRequestBuilder; - } + public synchronized void setAccessToken(String accessToken, Integer expiresIn) { + this.accessToken = accessToken; + this.expirationTimeMillis = expiresIn == null ? null : System.currentTimeMillis() + expiresIn * MILLIS_PER_SECOND; + } - public OAuthClient getOauthClient() { - return oauthClient; - } - - public void setOauthClient(OAuthClient oauthClient) { - this.oauthClient = oauthClient; - } - - public void setOauthClient(Client client) { - this.oauthClient = new OAuthClient( new OAuthFeignClient(client)); - } - - public static class OAuthFeignClient implements HttpClient { - - private Client client; - - public OAuthFeignClient() { - this.client = new Client.Default(null, null); - } - - public OAuthFeignClient(Client client) { - this.client = client; - } - - public T execute(OAuthClientRequest request, Map headers, - String requestMethod, Class responseClass) - throws OAuthSystemException, OAuthProblemException { - - RequestTemplate req = new RequestTemplate() - .append(request.getLocationUri()) - .method(requestMethod) - .body(request.getBody()); - - for (Entry entry : headers.entrySet()) { - req.header(entry.getKey(), entry.getValue()); - } - Response feignResponse; - String body = ""; - try { - feignResponse = client.execute(req.request(), new Options()); - body = Util.toString(feignResponse.body().asReader()); - } catch (IOException e) { - throw new OAuthSystemException(e); - } - - String contentType = null; - Collection contentTypeHeader = feignResponse.headers().get("Content-Type"); - if(contentTypeHeader != null) { - contentType = StringUtil.join(contentTypeHeader.toArray(new String[0]), ";"); - } - - return OAuthClientResponseFactory.createCustomResponse( - body, - contentType, - feignResponse.status(), - responseClass - ); - } - - public void shutdown() { - // Nothing to do here - } - } -} +} \ No newline at end of file diff --git a/libraries/feign/auth/OauthClientCredentialsGrant.mustache b/libraries/feign/auth/OauthClientCredentialsGrant.mustache new file mode 100644 index 00000000000..ef22c211637 --- /dev/null +++ b/libraries/feign/auth/OauthClientCredentialsGrant.mustache @@ -0,0 +1,39 @@ +package {{invokerPackage}}.auth; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; + +{{>generatedAnnotation}} +public class OauthClientCredentialsGrant extends OAuth { + + public OauthClientCredentialsGrant(String authorizationUrl, String tokenUrl, String scopes) { + super(authorizationUrl, tokenUrl, scopes); + } + + @Override + protected OAuth2AccessToken getOAuth2AccessToken() { + try { + return service.getAccessTokenClientCredentialsGrant(scopes); + } catch (Exception e) { + throw new RuntimeException("Failed to get oauth token", e); + } + } + + @Override + protected OAuthFlow getFlow() { + return OAuthFlow.application; + } + + /** + * Configures the client credentials flow + * + * @param clientId + * @param clientSecret + */ + public void configure(String clientId, String clientSecret) { + service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope(scopes) + .build(new DefaultApi20Impl(authorizationUrl, tokenUrl)); + } +} diff --git a/libraries/feign/auth/OauthPasswordGrant.mustache b/libraries/feign/auth/OauthPasswordGrant.mustache new file mode 100644 index 00000000000..870c3755a8b --- /dev/null +++ b/libraries/feign/auth/OauthPasswordGrant.mustache @@ -0,0 +1,48 @@ +package {{invokerPackage}}.auth; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; + +{{>generatedAnnotation}} +public class OauthPasswordGrant extends OAuth { + + private String username; + private String password; + + public OauthPasswordGrant(String tokenUrl, String scopes) { + super(null, tokenUrl, scopes); + } + + @Override + protected OAuth2AccessToken getOAuth2AccessToken() { + try { + return service.getAccessTokenPasswordGrant(username, password); + } catch (Exception e) { + throw new RuntimeException("Failed to get oauth token", e); + } + } + + @Override + protected OAuthFlow getFlow() { + return OAuthFlow.password; + } + + /** + * Configures Oauth password grant flow + * Note: this flow is deprecated. + * + * @param username + * @param password + * @param clientId + * @param clientSecret + */ + public void configure(String username, String password, String clientId, String clientSecret) { + this.username = username; + this.password = password; + //TODO the clientId and secret are optional according with the RFC + service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope(scopes) + .build(new DefaultApi20Impl(authorizationUrl, tokenUrl)); + } +} \ No newline at end of file diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index 3e00fb91797..ae4a04c11b3 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -33,20 +33,8 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 25 } compileOptions { - {{#supportJava6}} - sourceCompatibility JavaVersion.VERSION_1_6 - targetCompatibility JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 - {{/java8}} - {{^java8}} - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - {{/java8}} - {{/supportJava6}} } // Rename the aar correctly @@ -91,20 +79,8 @@ if(hasProperty('target') && target == 'android') { apply plugin: 'java' apply plugin: 'maven' - {{#supportJava6}} - sourceCompatibility = JavaVersion.VERSION_1_6 - targetCompatibility = JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 - {{/java8}} - {{^java8}} - sourceCompatibility = JavaVersion.VERSION_1_7 - targetCompatibility = JavaVersion.VERSION_1_7 - {{/java8}} - {{/supportJava6}} install { repositories.mavenInstaller { @@ -131,7 +107,7 @@ ext { feign_version = "10.11" feign_form_version = "3.8.0" junit_version = "4.13.1" - oltu_version = "1.0.1" + scribejava_version = "8.0.0" } dependencies { @@ -156,7 +132,8 @@ dependencies { {{#threetenbp}} implementation "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threetenbp_version" {{/threetenbp}} - implementation "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version" + implementation "com.brsanthu:migbase64:2.2" + implementation "com.github.scribejava:scribejava-core:$scribejava_version" implementation "com.brsanthu:migbase64:2.2" implementation 'javax.annotation:javax.annotation-api:1.3.2' testImplementation "junit:junit:$junit_version" diff --git a/libraries/feign/build.sbt.mustache b/libraries/feign/build.sbt.mustache index 322abb2a5cb..218469b0d57 100644 --- a/libraries/feign/build.sbt.mustache +++ b/libraries/feign/build.sbt.mustache @@ -19,7 +19,7 @@ lazy val root = (project in file(".")). "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", "com.fasterxml.jackson.datatype" % "jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}" % "2.9.10" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", - "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", + "com.github.scribejava" % "scribejava-core" % "8.0.0" % "compile", "com.brsanthu" % "migbase64" % "2.2" % "compile", "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", "junit" % "junit" % "4.13.1" % "test", diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index e9abe7dbaad..ce830af9e11 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -161,17 +161,7 @@ 3.1.1 none - {{#supportJava6}} - 1.6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} - 1.8 - {{/java8}} - {{^java8}} - 1.7 - {{/java8}} - {{/supportJava6}} + 1.8 @@ -282,40 +272,38 @@ {{/openApiNullable}} {{#withXml}} - - - - com.fasterxml.jackson.dataformat - jackson-dataformat-xml - ${jackson-version} - - + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson-version} + {{/withXml}} {{#joda}} - - com.fasterxml.jackson.datatype - jackson-datatype-joda - ${jackson-version} - + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + {{/joda}} {{#java8}} - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - ${jackson-version} - + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + {{/java8}} {{#threetenbp}} - - com.github.joschi.jackson - jackson-datatype-threetenbp - ${jackson-threetenbp-version} - + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${jackson-threetenbp-version} + {{/threetenbp}} - org.apache.oltu.oauth2 - org.apache.oltu.oauth2.client - ${oltu-version} + com.github.scribejava + scribejava-core + ${scribejava-version} javax.annotation @@ -346,7 +334,7 @@ UTF-8 - {{#supportJava6}}1.6{{/supportJava6}}{{^supportJava6}}{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}{{/supportJava6}} + 1.8 ${java.version} ${java.version} 1.5.24 @@ -363,6 +351,6 @@ 1.3.2 4.13.1 1.0.0 - 1.0.1 + 8.0.0 From a3939cf6291230b0898c3a351a41d06390bee94d Mon Sep 17 00:00:00 2001 From: Hugo Alves Date: Sat, 23 Jan 2021 02:33:16 +0000 Subject: [PATCH 336/370] [JAVA][FEIGN]Implement unit tests for java-feign client (#8484) * Implement unit tests for feign client Implement tests Migrate to junit 5 * Default feign client does not support PATCH verb Default feign client does not support PATCH verb * Remove test for GET endpoint with request body * Configure junit in gradle build * Configure logback for unit tests * Add missing dependencies to sbt * Fix gradle dependency * Add logback to gradle unit test * Regenerate samples * Make junit test classes package private * Make junit test classes package private * Update samples * Organize imports * Organize imports --- libraries/feign/ApiClient.mustache | 2 ++ libraries/feign/api_test.mustache | 12 +++---- libraries/feign/build.gradle.mustache | 15 +++++++-- libraries/feign/build.sbt.mustache | 8 ++++- libraries/feign/model_test.mustache | 48 +++++++++++++++++++++++++++ libraries/feign/pom.mustache | 41 ++++++++++++++++++----- 6 files changed, 108 insertions(+), 18 deletions(-) create mode 100644 libraries/feign/model_test.mustache diff --git a/libraries/feign/ApiClient.mustache b/libraries/feign/ApiClient.mustache index 54201a1c615..4e094dfccbe 100644 --- a/libraries/feign/ApiClient.mustache +++ b/libraries/feign/ApiClient.mustache @@ -8,6 +8,7 @@ import java.util.logging.Logger; {{#threetenbp}} import org.threeten.bp.*; {{/threetenbp}} +import feign.okhttp.OkHttpClient; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; @@ -51,6 +52,7 @@ public class ApiClient { objectMapper = createObjectMapper(); apiAuthorizations = new LinkedHashMap(); feignBuilder = Feign.builder() + .client(new OkHttpClient()) .encoder(new FormEncoder(new JacksonEncoder(objectMapper))) .decoder(new JacksonDecoder(objectMapper)) .logger(new Slf4jLogger()); diff --git a/libraries/feign/api_test.mustache b/libraries/feign/api_test.mustache index b24c9327129..e9f9d055e02 100644 --- a/libraries/feign/api_test.mustache +++ b/libraries/feign/api_test.mustache @@ -3,8 +3,8 @@ package {{package}}; import {{invokerPackage}}.ApiClient; {{#imports}}import {{import}}; {{/imports}} -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; {{^fullJavaUtil}} import java.util.ArrayList; @@ -16,11 +16,11 @@ import java.util.Map; /** * API tests for {{classname}} */ -public class {{classname}}Test { +class {{classname}}Test { private {{classname}} api; - @Before + @BeforeEach public void setup() { api = new ApiClient().buildClient({{classname}}.class); } @@ -32,7 +32,7 @@ public class {{classname}}Test { * {{notes}} */ @Test - public void {{operationId}}Test() { + void {{operationId}}Test() { {{#allParams}} {{{dataType}}} {{paramName}} = null; {{/allParams}} @@ -51,7 +51,7 @@ public class {{classname}}Test { * listing them out individually. */ @Test - public void {{operationId}}TestQueryMap() { + void {{operationId}}TestQueryMap() { {{#allParams}} {{^isQueryParam}} {{{dataType}}} {{paramName}} = null; diff --git a/libraries/feign/build.gradle.mustache b/libraries/feign/build.gradle.mustache index ae4a04c11b3..eda36125e37 100644 --- a/libraries/feign/build.gradle.mustache +++ b/libraries/feign/build.gradle.mustache @@ -94,6 +94,10 @@ if(hasProperty('target') && target == 'android') { } } +test { + useJUnitPlatform() +} + ext { swagger_annotations_version = "1.5.24" jackson_version = "2.10.3" @@ -106,7 +110,7 @@ ext { {{/threetenbp}} feign_version = "10.11" feign_form_version = "3.8.0" - junit_version = "4.13.1" + junit_version = "5.7.0" scribejava_version = "8.0.0" } @@ -116,6 +120,7 @@ dependencies { implementation "io.github.openfeign:feign-core:$feign_version" implementation "io.github.openfeign:feign-jackson:$feign_version" implementation "io.github.openfeign:feign-slf4j:$feign_version" + implementation "io.github.openfeign:feign-okhttp:$feign_version" implementation "io.github.openfeign.form:feign-form:$feign_form_version" implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" @@ -136,5 +141,11 @@ dependencies { implementation "com.github.scribejava:scribejava-core:$scribejava_version" implementation "com.brsanthu:migbase64:2.2" implementation 'javax.annotation:javax.annotation-api:1.3.2' - testImplementation "junit:junit:$junit_version" + testImplementation "org.junit.jupiter:junit-jupiter:$junit_version" + testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit_version" + testImplementation "org.junit.jupiter:junit-jupiter-params:$junit_version" + testImplementation "com.github.tomakehurst:wiremock-jre8:2.27.2" + testImplementation "org.hamcrest:hamcrest:2.2" + testImplementation "commons-io:commons-io:2.8.0" + testImplementation "ch.qos.logback:logback-classic:1.2.3" } diff --git a/libraries/feign/build.sbt.mustache b/libraries/feign/build.sbt.mustache index 218469b0d57..95745cdad26 100644 --- a/libraries/feign/build.sbt.mustache +++ b/libraries/feign/build.sbt.mustache @@ -10,10 +10,12 @@ lazy val root = (project in file(".")). resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( "io.swagger" % "swagger-annotations" % "1.5.24" % "compile", + "com.google.code.findbugs" % "jsr305" % "3.0.2" % "compile", "io.github.openfeign" % "feign-core" % "10.11" % "compile", "io.github.openfeign" % "feign-jackson" % "10.11" % "compile", "io.github.openfeign" % "feign-slf4j" % "10.11" % "compile", "io.github.openfeign.form" % "feign-form" % "3.8.0" % "compile", + "io.github.openfeign" % "feign-okhttp" % "10.11" % "compile", "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", @@ -22,7 +24,11 @@ lazy val root = (project in file(".")). "com.github.scribejava" % "scribejava-core" % "8.0.0" % "compile", "com.brsanthu" % "migbase64" % "2.2" % "compile", "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", - "junit" % "junit" % "4.13.1" % "test", + "org.junit.jupiter" % "junit-jupiter" % "5.7.0" % "test", + "org.junit.jupiter" % "junit-jupiter-params" % "5.7.0" % "test", + "com.github.tomakehurst" % "wiremock-jre8" % "2.27.2" % "test", + "org.hamcrest" % "hamcrest" % "2.2" % "test", + "commons-io" % "commons-io" % "2.8.0" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) ) diff --git a/libraries/feign/model_test.mustache b/libraries/feign/model_test.mustache new file mode 100644 index 00000000000..0d75e120b09 --- /dev/null +++ b/libraries/feign/model_test.mustache @@ -0,0 +1,48 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.jupiter.api.Test; + +{{#fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * Model tests for {{classname}} + */ +class {{classname}}Test { + {{#models}} + {{#model}} + {{^vendorExtensions.x-is-one-of-interface}} + {{^isEnum}} + private final {{classname}} model = new {{classname}}(); + + {{/isEnum}} + /** + * Model tests for {{classname}} + */ + @Test + void test{{classname}}() { + // TODO: test {{classname}} + } + + {{#allVars}} + /** + * Test the property '{{name}}' + */ + @Test + void {{name}}Test() { + // TODO: test {{name}} + } + + {{/allVars}} + {{/vendorExtensions.x-is-one-of-interface}} + {{/model}} + {{/models}} +} diff --git a/libraries/feign/pom.mustache b/libraries/feign/pom.mustache index ce830af9e11..65b3cc3c214 100644 --- a/libraries/feign/pom.mustache +++ b/libraries/feign/pom.mustache @@ -247,6 +247,11 @@ feign-form ${feign-form-version} + + io.github.openfeign + feign-okhttp + ${feign-version} + @@ -314,21 +319,39 @@ - junit - junit + ch.qos.logback + logback-classic + 1.2.3 + test + + + org.junit.jupiter + junit-jupiter ${junit-version} test - com.squareup.okhttp3 - mockwebserver - 3.6.0 + org.junit.jupiter + junit-jupiter-params + ${junit-version} + test + + + org.hamcrest + hamcrest + 2.2 + test + + + com.github.tomakehurst + wiremock-jre8 + 2.27.2 test - org.assertj - assertj-core - 1.7.1 + commons-io + commons-io + 2.8.0 test @@ -349,7 +372,7 @@ 2.9.10 {{/threetenbp}} 1.3.2 - 4.13.1 + 5.7.0 1.0.0 8.0.0 From d0917e470dfcaebfd76133e314474a1cc6520a83 Mon Sep 17 00:00:00 2001 From: iyzana <16743652+iyzana@users.noreply.github.com> Date: Mon, 25 Jan 2021 11:55:26 +0100 Subject: [PATCH 337/370] Implement useAbstractionForFiles for webclient library (#7567) * implement useAbstractionForFiles for webclient library * update doc Co-authored-by: William Cheng --- libraries/webclient/api.mustache | 4 ++-- libraries/webclient/api_test.mustache | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/webclient/api.mustache b/libraries/webclient/api.mustache index 83178188549..5fbef45db81 100644 --- a/libraries/webclient/api.mustache +++ b/libraries/webclient/api.mustache @@ -62,7 +62,7 @@ public class {{classname}} { * @see {{summary}} Documentation {{/externalDocs}} */ - public {{#returnType}}{{#isArray}}Flux<{{{returnBaseType}}}>{{/isArray}}{{^isArray}}Mono<{{{returnType}}}>{{/isArray}} {{/returnType}}{{^returnType}}Mono {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws WebClientResponseException { + public {{#returnType}}{{#isArray}}Flux<{{{returnBaseType}}}>{{/isArray}}{{^isArray}}Mono<{{{returnType}}}>{{/isArray}} {{/returnType}}{{^returnType}}Mono {{/returnType}}{{operationId}}({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.AbstractResource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws WebClientResponseException { Object postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}} {{#required}} @@ -109,7 +109,7 @@ public class {{classname}} { {{#formParams}} if ({{paramName}} != null) - formParams.add{{#collectionFormat}}All{{/collectionFormat}}("{{baseName}}", {{#isFile}}{{^collectionFormat}}new FileSystemResource({{paramName}}){{/collectionFormat}}{{/isFile}}{{#isFile}}{{#collectionFormat}}{{paramName}}.stream().map(FileSystemResource::new).collect(Collectors.toList()){{/collectionFormat}}{{/isFile}}{{^isFile}}{{paramName}}{{/isFile}}); + formParams.add{{#collectionFormat}}All{{/collectionFormat}}("{{baseName}}", {{#isFile}}{{^collectionFormat}}{{#useAbstractionForFiles}}{{paramName}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}new FileSystemResource({{paramName}}){{/useAbstractionForFiles}}{{/collectionFormat}}{{/isFile}}{{#isFile}}{{#collectionFormat}}{{paramName}}.stream(){{^useAbstractionForFiles}}.map(FileSystemResource::new){{/useAbstractionForFiles}}.collect(Collectors.toList()){{/collectionFormat}}{{/isFile}}{{^isFile}}{{paramName}}{{/isFile}}); {{/formParams}} {{/hasFormParams}} diff --git a/libraries/webclient/api_test.mustache b/libraries/webclient/api_test.mustache index 301acf8f244..c2b491aedc1 100644 --- a/libraries/webclient/api_test.mustache +++ b/libraries/webclient/api_test.mustache @@ -31,7 +31,7 @@ public class {{classname}}Test { @Test public void {{operationId}}Test() { {{#allParams}} - {{{dataType}}} {{paramName}} = null; + {{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.AbstractResource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}} = null; {{/allParams}} {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}){{#isArray}}.collectList().block(){{/isArray}}{{^isArray}}.block(){{/isArray}}; From 1857e9c981808810cfcc4623a18cd846b2438de1 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Tue, 26 Jan 2021 10:27:09 +0800 Subject: [PATCH 338/370] remove supportJava6 option (#8514) --- README.mustache | 2 +- build.gradle.mustache | 12 ------- .../google-api-client/build.gradle.mustache | 12 ------- libraries/google-api-client/pom.mustache | 11 ------- libraries/jersey2/ApiClient.mustache | 17 ---------- libraries/jersey2/build.gradle.mustache | 23 ------------- libraries/jersey2/build.sbt.mustache | 14 +++----- libraries/jersey2/model.mustache | 5 --- libraries/jersey2/pojo.mustache | 25 --------------- libraries/jersey2/pom.mustache | 32 ------------------- libraries/okhttp-gson/README.mustache | 2 +- libraries/okhttp-gson/build.gradle.mustache | 12 ------- libraries/okhttp-gson/pom.mustache | 2 +- libraries/resteasy/ApiClient.mustache | 6 ---- libraries/resteasy/build.gradle.mustache | 20 ------------ libraries/resteasy/build.sbt.mustache | 4 --- libraries/resteasy/pom.mustache | 28 ---------------- libraries/resttemplate/build.gradle.mustache | 12 ------- libraries/resttemplate/pom.mustache | 6 ---- libraries/retrofit/build.gradle.mustache | 6 ---- libraries/retrofit/pom.mustache | 11 ------- libraries/retrofit2/build.gradle.mustache | 12 ------- libraries/retrofit2/play24/ApiClient.mustache | 8 ++--- libraries/retrofit2/play25/ApiClient.mustache | 8 ++--- libraries/retrofit2/pom.mustache | 13 +------- libraries/vertx/pom.mustache | 5 --- libraries/webclient/build.gradle.mustache | 12 ------- model.mustache | 5 --- pojo.mustache | 25 --------------- pom.mustache | 27 ---------------- 30 files changed, 17 insertions(+), 360 deletions(-) diff --git a/README.mustache b/README.mustache index 40d272ed318..fd9abd28241 100644 --- a/README.mustache +++ b/README.mustache @@ -20,7 +20,7 @@ Building the API client library requires: -1. Java {{#supportJava6}}1.6{{/supportJava6}}{{^supportJava6}}{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}{{/supportJava6}}+ +1. Java {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}+ 2. Maven/Gradle ## Installation diff --git a/build.gradle.mustache b/build.gradle.mustache index 0982932dfb0..a14862d3a81 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -34,11 +34,6 @@ if(hasProperty('target') && target == 'android') { } compileOptions { - {{#supportJava6}} - sourceCompatibility JavaVersion.VERSION_1_6 - targetCompatibility JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -47,7 +42,6 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 {{/java8}} - {{/supportJava6}} } // Rename the aar correctly @@ -92,11 +86,6 @@ if(hasProperty('target') && target == 'android') { apply plugin: 'java' apply plugin: 'maven' - {{#supportJava6}} - sourceCompatibility = JavaVersion.VERSION_1_6 - targetCompatibility = JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 @@ -105,7 +94,6 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility = JavaVersion.VERSION_1_7 targetCompatibility = JavaVersion.VERSION_1_7 {{/java8}} - {{/supportJava6}} install { repositories.mavenInstaller { diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache index 496ff42fcce..14d93d588dc 100644 --- a/libraries/google-api-client/build.gradle.mustache +++ b/libraries/google-api-client/build.gradle.mustache @@ -33,11 +33,6 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 22 } compileOptions { - {{#supportJava6}} - sourceCompatibility JavaVersion.VERSION_1_6 - targetCompatibility JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -46,7 +41,6 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 {{/java8}} - {{/supportJava6}} } // Rename the aar correctly @@ -91,11 +85,6 @@ if(hasProperty('target') && target == 'android') { apply plugin: 'java' apply plugin: 'maven' - {{#supportJava6}} - sourceCompatibility = JavaVersion.VERSION_1_6 - targetCompatibility = JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 @@ -104,7 +93,6 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility = JavaVersion.VERSION_1_7 targetCompatibility = JavaVersion.VERSION_1_7 {{/java8}} - {{/supportJava6}} install { repositories.mavenInstaller { diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index 17a87a012d4..3a4b62e203b 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -144,11 +144,6 @@ maven-compiler-plugin 3.6.1 - {{#supportJava6}} - 1.6 - 1.6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} 1.8 1.8 @@ -157,7 +152,6 @@ 1.7 1.7 {{/java8}} - {{/supportJava6}} @@ -166,17 +160,12 @@ 3.1.1 none - {{#supportJava6}} - 1.6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} 1.8 {{/java8}} {{^java8}} 1.7 {{/java8}} - {{/supportJava6}} diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index e8833c12611..69727cd0ace 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -34,15 +34,9 @@ import java.security.cert.X509Certificate; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; -{{^supportJava6}} import java.nio.file.Files; import java.nio.file.StandardCopyOption; import org.glassfish.jersey.logging.LoggingFeature; -{{/supportJava6}} -{{#supportJava6}} -import org.apache.commons.io.FileUtils; -import org.glassfish.jersey.filter.LoggingFilter; -{{/supportJava6}} import java.util.logging.Level; import java.util.logging.Logger; import java.util.Collection; @@ -997,13 +991,7 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { public File downloadFileFromResponse(Response response) throws ApiException { try { File file = prepareDownloadFile(response); -{{^supportJava6}} Files.copy(response.readEntity(InputStream.class), file.toPath(), StandardCopyOption.REPLACE_EXISTING); -{{/supportJava6}} -{{#supportJava6}} - // Java6 falls back to commons.io for file copying - FileUtils.copyToFile(response.readEntity(InputStream.class), file); -{{/supportJava6}} return file; } catch (IOException e) { throw new ApiException(e); @@ -1259,15 +1247,10 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { // turn off compliance validation to be able to send payloads with DELETE calls clientConfig.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true); if (debugging) { -{{^supportJava6}} clientConfig.register(new LoggingFeature(java.util.logging.Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME), java.util.logging.Level.INFO, LoggingFeature.Verbosity.PAYLOAD_ANY, 1024*50 /* Log payloads up to 50K */)); clientConfig.property(LoggingFeature.LOGGING_FEATURE_VERBOSITY, LoggingFeature.Verbosity.PAYLOAD_ANY); // Set logger to ALL java.util.logging.Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME).setLevel(java.util.logging.Level.ALL); -{{/supportJava6}} -{{#supportJava6}} - clientConfig.register(new LoggingFilter(java.util.logging.Logger.getLogger(LoggingFilter.class.getName()), true)); -{{/supportJava6}} } else { // suppress warnings for payloads with DELETE calls: java.util.logging.Logger.getLogger("org.glassfish.jersey.client").setLevel(java.util.logging.Level.SEVERE); diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index 9292d599cad..a15919fb9bb 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -33,11 +33,6 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 25 } compileOptions { - {{#supportJava6}} - sourceCompatibility JavaVersion.VERSION_1_6 - targetCompatibility JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -46,7 +41,6 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 {{/java8}} - {{/supportJava6}} } // Rename the aar correctly @@ -90,11 +84,6 @@ if(hasProperty('target') && target == 'android') { apply plugin: 'java' apply plugin: 'maven' - {{#supportJava6}} - sourceCompatibility = JavaVersion.VERSION_1_6 - targetCompatibility = JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 @@ -103,7 +92,6 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility = JavaVersion.VERSION_1_7 targetCompatibility = JavaVersion.VERSION_1_7 {{/java8}} - {{/supportJava6}} install { repositories.mavenInstaller { @@ -124,14 +112,7 @@ ext { {{#openApiNullable}} jackson_databind_nullable_version = "0.2.1" {{/openApiNullable}} - {{#supportJava6}} - jersey_version = "2.6" - commons_io_version=2.5 - commons_lang3_version=3.6 - {{/supportJava6}} - {{^supportJava6}} jersey_version = "2.27" - {{/supportJava6}} junit_version = "4.13.1" {{#threetenbp}} threetenbp_version = "2.9.10" @@ -170,10 +151,6 @@ dependencies { {{#hasHttpSignatureMethods}} implementation "org.tomitribe:tomitribe-http-signatures:$tomitribe_http_signatures_version" {{/hasHttpSignatureMethods}} - {{#supportJava6}} - implementation "commons-io:commons-io:$commons_io_version" - implementation "org.apache.commons:commons-lang3:$commons_lang3_version" - {{/supportJava6}} {{#threetenbp}} implementation "com.github.joschi.jackson:jackson-datatype-threetenbp:$threetenbp_version" {{/threetenbp}} diff --git a/libraries/jersey2/build.sbt.mustache b/libraries/jersey2/build.sbt.mustache index 42afc6016ba..52f17959a63 100644 --- a/libraries/jersey2/build.sbt.mustache +++ b/libraries/jersey2/build.sbt.mustache @@ -10,11 +10,11 @@ lazy val root = (project in file(".")). resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( "io.swagger" % "swagger-annotations" % "1.5.22", - "org.glassfish.jersey.core" % "jersey-client" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.27"{{/supportJava6}},{{^supportJava6}} - "org.glassfish.jersey.inject" % "jersey-hk2" % "2.27",{{/supportJava6}} - "org.glassfish.jersey.media" % "jersey-media-multipart" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.27"{{/supportJava6}}, - "org.glassfish.jersey.media" % "jersey-media-json-jackson" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.27"{{/supportJava6}}, - "org.glassfish.jersey.connectors" % "jersey-apache-connector" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.27"{{/supportJava6}}, + "org.glassfish.jersey.core" % "jersey-client" % "2.27", + "org.glassfish.jersey.inject" % "jersey-hk2" % "2.27", + "org.glassfish.jersey.media" % "jersey-media-multipart" % "2.27", + "org.glassfish.jersey.media" % "jersey-media-json-jackson" % "2.27", + "org.glassfish.jersey.connectors" % "jersey-apache-connector" % "2.27", "com.fasterxml.jackson.core" % "jackson-core" % "2.10.4" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.4" % "compile", "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.4" % "compile", @@ -36,10 +36,6 @@ lazy val root = (project in file(".")). {{^java8}} "com.brsanthu" % "migbase64" % "2.2", {{/java8}} - {{#supportJava6}} - "org.apache.commons" % "commons-lang3" % "3.6", - "commons-io" % "commons-io" % "2.5", - {{/supportJava6}} "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", "junit" % "junit" % "4.13.1" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" diff --git a/libraries/jersey2/model.mustache b/libraries/jersey2/model.mustache index c0664be10de..18ee1211785 100644 --- a/libraries/jersey2/model.mustache +++ b/libraries/jersey2/model.mustache @@ -16,15 +16,10 @@ import com.fasterxml.jackson.annotation.JsonAnySetter; {{/additionalPropertiesType}} {{/model}} {{/models}} -{{^supportJava6}} import java.util.Objects; import java.util.Arrays; import java.util.Map; import java.util.HashMap; -{{/supportJava6}} -{{#supportJava6}} -import org.apache.commons.lang3.ObjectUtils; -{{/supportJava6}} {{#imports}} import {{import}}; {{/imports}} diff --git a/libraries/jersey2/pojo.mustache b/libraries/jersey2/pojo.mustache index 3d1c6cf59db..70fadd299bc 100644 --- a/libraries/jersey2/pojo.mustache +++ b/libraries/jersey2/pojo.mustache @@ -251,7 +251,6 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{/vars}} {{>libraries/jersey2/additional_properties}} -{{^supportJava6}} /** * Return true if this {{name}} object is equal to o. */ @@ -286,30 +285,6 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{/useReflectionEqualsHashCode}} } -{{/supportJava6}} -{{#supportJava6}} - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - }{{#hasVars}} - {{classname}} {{classVarName}} = ({{classname}}) o; - return {{#vars}}ObjectUtils.equals(this.{{name}}, {{classVarName}}.{{name}}){{^-last}} && - {{/-last}}{{/vars}}{{#parent}} && - super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} - return true;{{/hasVars}} - } - - @Override - public int hashCode() { - return ObjectUtils.hashCodeMulti({{#vars}}{{name}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); - } - -{{/supportJava6}} - @Override public String toString() { StringBuilder sb = new StringBuilder(); diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index 293356545b0..e7765a50d1b 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -145,11 +145,6 @@ maven-compiler-plugin 3.8.1 - {{#supportJava6}} - 1.6 - 1.6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} 1.8 1.8 @@ -158,7 +153,6 @@ 1.7 1.7 {{/java8}} - {{/supportJava6}} true 128m 512m @@ -182,17 +176,12 @@ none - {{#supportJava6}} - 1.6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} 1.8 {{/java8}} {{^java8}} 1.7 {{/java8}} - {{/supportJava6}} http.response.details @@ -262,13 +251,11 @@ jersey-client ${jersey-version} - {{^supportJava6}} org.glassfish.jersey.inject jersey-hk2 ${jersey-version} - {{/supportJava6}} org.glassfish.jersey.media jersey-media-multipart @@ -340,18 +327,6 @@ 2.2 {{/java8}} - {{#supportJava6}} - - org.apache.commons - commons-lang3 - ${commons-lang3-version} - - - commons-io - commons-io - ${commons-io-version} - - {{/supportJava6}} {{#hasHttpSignatureMethods}} org.tomitribe @@ -397,14 +372,7 @@ UTF-8 1.6.1 - {{^supportJava6}} 2.30.1 - {{/supportJava6}} - {{#supportJava6}} - 2.6 - 2.5 - 3.6 - {{/supportJava6}} 2.10.4 2.10.4 0.2.1 diff --git a/libraries/okhttp-gson/README.mustache b/libraries/okhttp-gson/README.mustache index 6da087078f0..5b4ff7e38f5 100644 --- a/libraries/okhttp-gson/README.mustache +++ b/libraries/okhttp-gson/README.mustache @@ -18,7 +18,7 @@ ## Requirements Building the API client library requires: -1. Java {{#supportJava6}}1.6{{/supportJava6}}{{^supportJava6}}{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}{{/supportJava6}}+ +1. Java {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}+ 2. Maven/Gradle ## Installation diff --git a/libraries/okhttp-gson/build.gradle.mustache b/libraries/okhttp-gson/build.gradle.mustache index 104fe6d0ff1..c027064edd4 100644 --- a/libraries/okhttp-gson/build.gradle.mustache +++ b/libraries/okhttp-gson/build.gradle.mustache @@ -40,11 +40,6 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 25 } compileOptions { - {{#supportJava6}} - sourceCompatibility JavaVersion.VERSION_1_6 - targetCompatibility JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -53,7 +48,6 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 {{/java8}} - {{/supportJava6}} } // Rename the aar correctly @@ -98,11 +92,6 @@ if(hasProperty('target') && target == 'android') { apply plugin: 'java' apply plugin: 'maven' - {{#supportJava6}} - sourceCompatibility = JavaVersion.VERSION_1_6 - targetCompatibility = JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 @@ -111,7 +100,6 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility = JavaVersion.VERSION_1_7 targetCompatibility = JavaVersion.VERSION_1_7 {{/java8}} - {{/supportJava6}} install { repositories.mavenInstaller { diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index 598312cad6c..d99f278244e 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -327,7 +327,7 @@ - {{#supportJava6}}1.6{{/supportJava6}}{{^supportJava6}}{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}{{/supportJava6}} + {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}} ${java.version} ${java.version} 1.8.4 diff --git a/libraries/resteasy/ApiClient.mustache b/libraries/resteasy/ApiClient.mustache index 8f3486eb5db..a4489c1e8d1 100644 --- a/libraries/resteasy/ApiClient.mustache +++ b/libraries/resteasy/ApiClient.mustache @@ -560,13 +560,7 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { public File downloadFileFromResponse(Response response) throws ApiException { try { File file = prepareDownloadFile(response); -{{^supportJava6}} Files.copy(response.readEntity(InputStream.class), file.toPath()); -{{/supportJava6}} -{{#supportJava6}} - // Java6 falls back to commons.io for file copying - FileUtils.copyToFile(response.readEntity(InputStream.class), file); -{{/supportJava6}} return file; } catch (IOException e) { throw new ApiException(e); diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index ed3020519df..3823153acc7 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -33,11 +33,6 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 23 } compileOptions { - {{#supportJava6}} - sourceCompatibility JavaVersion.VERSION_1_6 - targetCompatibility JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -46,7 +41,6 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 {{/java8}} - {{/supportJava6}} } // Rename the aar correctly @@ -90,11 +84,6 @@ if(hasProperty('target') && target == 'android') { apply plugin: 'java' apply plugin: 'maven' - {{#supportJava6}} - sourceCompatibility = JavaVersion.VERSION_1_6 - targetCompatibility = JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 @@ -103,7 +92,6 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility = JavaVersion.VERSION_1_7 targetCompatibility = JavaVersion.VERSION_1_7 {{/java8}} - {{/supportJava6}} install { repositories.mavenInstaller { @@ -129,10 +117,6 @@ ext { {{^java8}} jodatime_version = "2.9.9" {{/java8}} - {{#supportJava6}} - commons_io_version=2.5 - commons_lang3_version=3.5 - {{/supportJava6}} junit_version = "4.13" } @@ -157,10 +141,6 @@ dependencies { implementation "joda-time:joda-time:$jodatime_version" implementation "com.brsanthu:migbase64:2.2" {{/java8}} - {{#supportJava6}} - implementation "commons-io:commons-io:$commons_io_version" - implementation "org.apache.commons:commons-lang3:$commons_lang3_version" - {{/supportJava6}} implementation 'javax.annotation:javax.annotation-api:1.3.2' testImplementation "junit:junit:$junit_version" } diff --git a/libraries/resteasy/build.sbt.mustache b/libraries/resteasy/build.sbt.mustache index 721e4620057..79600b7754c 100644 --- a/libraries/resteasy/build.sbt.mustache +++ b/libraries/resteasy/build.sbt.mustache @@ -25,10 +25,6 @@ lazy val root = (project in file(".")). "joda-time" % "joda-time" % "2.9.9" % "compile", "com.brsanthu" % "migbase64" % "2.2" % "compile", {{/java8}} - {{#supportJava6}} - "org.apache.commons" % "commons-lang3" % "3.5" % "compile", - "commons-io" % "commons-io" % "2.5" % "compile", - {{/supportJava6}} "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index 738f438da60..82c5a036087 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -142,11 +142,6 @@ maven-compiler-plugin 2.5.1 - {{#supportJava6}} - 1.6 - 1.6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} 1.8 1.8 @@ -155,7 +150,6 @@ 1.7 1.7 {{/java8}} - {{/supportJava6}} @@ -164,17 +158,12 @@ 3.1.1 none - {{#supportJava6}} - 1.6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} 1.8 {{/java8}} {{^java8}} 1.7 {{/java8}} - {{/supportJava6}} @@ -263,19 +252,6 @@ {{/java8}} - {{#supportJava6}} - - org.apache.commons - commons-lang3 - ${commons_lang3_version} - - - - commons-io - commons-io - ${commons_io_version} - - {{/supportJava6}} org.jboss.resteasy resteasy-jackson2-provider @@ -317,10 +293,6 @@ {{^java8}} 2.9.9 {{/java8}} - {{#supportJava6}} - 2.5 - 3.6 - {{/supportJava6}} 1.0.0 4.13 diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index d41aa90de15..11235a89bb7 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -33,11 +33,6 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 22 } compileOptions { - {{#supportJava6}} - sourceCompatibility JavaVersion.VERSION_1_6 - targetCompatibility JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -46,7 +41,6 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 {{/java8}} - {{/supportJava6}} } // Rename the aar correctly @@ -91,11 +85,6 @@ if(hasProperty('target') && target == 'android') { apply plugin: 'java' apply plugin: 'maven' - {{#supportJava6}} - sourceCompatibility = JavaVersion.VERSION_1_6 - targetCompatibility = JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 @@ -104,7 +93,6 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility = JavaVersion.VERSION_1_7 targetCompatibility = JavaVersion.VERSION_1_7 {{/java8}} - {{/supportJava6}} install { repositories.mavenInstaller { diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache index 2fdd99cf76f..ca273093471 100644 --- a/libraries/resttemplate/pom.mustache +++ b/libraries/resttemplate/pom.mustache @@ -144,11 +144,6 @@ maven-compiler-plugin 3.6.1 - {{#supportJava6}} - 1.6 - 1.6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} 1.8 1.8 @@ -157,7 +152,6 @@ 1.7 1.7 {{/java8}} - {{/supportJava6}} diff --git a/libraries/retrofit/build.gradle.mustache b/libraries/retrofit/build.gradle.mustache index cd1096e5723..ec85f6ec71b 100644 --- a/libraries/retrofit/build.gradle.mustache +++ b/libraries/retrofit/build.gradle.mustache @@ -33,11 +33,6 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 25 } compileOptions { - {{#supportJava6}} - sourceCompatibility JavaVersion.VERSION_1_6 - targetCompatibility JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -46,7 +41,6 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 {{/java8}} - {{/supportJava6}} } // Rename the aar correctly diff --git a/libraries/retrofit/pom.mustache b/libraries/retrofit/pom.mustache index d2d5bf60249..b495864db77 100644 --- a/libraries/retrofit/pom.mustache +++ b/libraries/retrofit/pom.mustache @@ -144,11 +144,6 @@ maven-compiler-plugin 3.6.1 - {{#supportJava6}} - 1.6 - 1.6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} 1.8 1.8 @@ -157,7 +152,6 @@ 1.7 1.7 {{/java8}} - {{/supportJava6}} @@ -166,17 +160,12 @@ 3.1.1 none - {{#supportJava6}} - 1.6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} 1.8 {{/java8}} {{^java8}} 1.7 {{/java8}} - {{/supportJava6}} diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index 517d6a4e844..2bb2fb35613 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -33,11 +33,6 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 25 } compileOptions { - {{#supportJava6}} - sourceCompatibility JavaVersion.VERSION_1_6 - targetCompatibility JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -46,7 +41,6 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 {{/java8}} - {{/supportJava6}} } // Rename the aar correctly @@ -91,11 +85,6 @@ if(hasProperty('target') && target == 'android') { apply plugin: 'java' apply plugin: 'maven' - {{#supportJava6}} - sourceCompatibility = JavaVersion.VERSION_1_6 - targetCompatibility = JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 @@ -104,7 +93,6 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility = JavaVersion.VERSION_1_7 targetCompatibility = JavaVersion.VERSION_1_7 {{/java8}} - {{/supportJava6}} install { repositories.mavenInstaller { diff --git a/libraries/retrofit2/play24/ApiClient.mustache b/libraries/retrofit2/play24/ApiClient.mustache index a80cefc31dc..c43f800a42c 100644 --- a/libraries/retrofit2/play24/ApiClient.mustache +++ b/libraries/retrofit2/play24/ApiClient.mustache @@ -44,7 +44,7 @@ public class ApiClient { public ApiClient() { // Setup authentications (key: authentication name, value: authentication). - authentications = new HashMap<{{#supportJava6}}String, Authentication{{/supportJava6}}>();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + authentications = new HashMap<>();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} // authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} // authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} @@ -62,9 +62,9 @@ public class ApiClient { basePath = basePath + "/"; } - Map extraHeaders = new HashMap<{{#supportJava6}}String, String{{/supportJava6}}>(); - Map extraCookies = new HashMap<{{#supportJava6}}String, String{{/supportJava6}}>(); - List extraQueryParams = new ArrayList<{{#supportJava6}}Pair{{/supportJava6}}>(); + Map extraHeaders = new HashMap<>(); + Map extraCookies = new HashMap<>(); + List extraQueryParams = new ArrayList<>(); for (String authName : authentications.keySet()) { Authentication auth = authentications.get(authName); diff --git a/libraries/retrofit2/play25/ApiClient.mustache b/libraries/retrofit2/play25/ApiClient.mustache index dcb9e2c58e0..849e0665e8c 100644 --- a/libraries/retrofit2/play25/ApiClient.mustache +++ b/libraries/retrofit2/play25/ApiClient.mustache @@ -44,7 +44,7 @@ public class ApiClient { public ApiClient() { // Setup authentications (key: authentication name, value: authentication). - authentications = new HashMap<{{#supportJava6}}String, Authentication{{/supportJava6}}>();{{#authMethods}}{{#isBasic}} + authentications = new HashMap<>();{{#authMethods}}{{#isBasic}} // authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"query"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} // authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} @@ -61,9 +61,9 @@ public class ApiClient { basePath = basePath + "/"; } - Map extraHeaders = new HashMap<{{#supportJava6}}String, String{{/supportJava6}}>(); - Map extraCookies = new HashMap<{{#supportJava6}}String, String{{/supportJava6}}>(); - List extraQueryParams = new ArrayList<{{#supportJava6}}Pair{{/supportJava6}}>(); + Map extraHeaders = new HashMap<>(); + Map extraCookies = new HashMap<>(); + List extraQueryParams = new ArrayList<>(); for (String authName : authentications.keySet()) { Authentication auth = authentications.get(authName); diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index 7cb390987b3..32d395bf02e 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -144,11 +144,6 @@ maven-compiler-plugin 3.6.1 - {{#supportJava6}} - 1.6 - 1.6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} 1.8 1.8 @@ -157,7 +152,6 @@ 1.7 1.7 {{/java8}} - {{/supportJava6}} @@ -166,17 +160,12 @@ 3.1.1 none - {{#supportJava6}} - 1.6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} 1.8 {{/java8}} {{^java8}} 1.7 {{/java8}} - {{/supportJava6}} @@ -414,7 +403,7 @@ UTF-8 - {{#supportJava6}}1.6{{/supportJava6}}{{^supportJava6}}{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}{{/supportJava6}} + {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}} ${java.version} ${java.version} 1.8.3 diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache index d9882a1866c..b4064662a98 100644 --- a/libraries/vertx/pom.mustache +++ b/libraries/vertx/pom.mustache @@ -154,17 +154,12 @@ 3.1.1 none - {{#supportJava6}} - 1.6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} 1.8 {{/java8}} {{^java8}} 1.7 {{/java8}} - {{/supportJava6}} diff --git a/libraries/webclient/build.gradle.mustache b/libraries/webclient/build.gradle.mustache index 028d9e5cc51..c892d189243 100644 --- a/libraries/webclient/build.gradle.mustache +++ b/libraries/webclient/build.gradle.mustache @@ -34,11 +34,6 @@ if(hasProperty('target') && target == 'android') { } compileOptions { - {{#supportJava6}} - sourceCompatibility JavaVersion.VERSION_1_6 - targetCompatibility JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -47,7 +42,6 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 {{/java8}} - {{/supportJava6}} } // Rename the aar correctly @@ -92,11 +86,6 @@ if(hasProperty('target') && target == 'android') { apply plugin: 'java' apply plugin: 'maven' - {{#supportJava6}} - sourceCompatibility = JavaVersion.VERSION_1_6 - targetCompatibility = JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 @@ -105,7 +94,6 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility = JavaVersion.VERSION_1_7 targetCompatibility = JavaVersion.VERSION_1_7 {{/java8}} - {{/supportJava6}} install { repositories.mavenInstaller { diff --git a/model.mustache b/model.mustache index d4d1447a1d4..dec0b7dc8ac 100644 --- a/model.mustache +++ b/model.mustache @@ -6,13 +6,8 @@ package {{package}}; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; {{/useReflectionEqualsHashCode}} -{{^supportJava6}} import java.util.Objects; import java.util.Arrays; -{{/supportJava6}} -{{#supportJava6}} -import org.apache.commons.lang3.ObjectUtils; -{{/supportJava6}} {{#imports}} import {{import}}; {{/imports}} diff --git a/pojo.mustache b/pojo.mustache index 03cf219b760..81eeb24af08 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -228,7 +228,6 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{/vars}} -{{^supportJava6}} @Override public boolean equals(Object o) { {{#useReflectionEqualsHashCode}} @@ -259,30 +258,6 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{/useReflectionEqualsHashCode}} } -{{/supportJava6}} -{{#supportJava6}} - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - }{{#hasVars}} - {{classname}} {{classVarName}} = ({{classname}}) o; - return {{#vars}}ObjectUtils.equals(this.{{name}}, {{classVarName}}.{{name}}){{^-last}} && - {{/-last}}{{/vars}}{{#parent}} && - super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} - return true;{{/hasVars}} - } - - @Override - public int hashCode() { - return ObjectUtils.hashCodeMulti({{#vars}}{{name}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); - } - -{{/supportJava6}} - @Override public String toString() { StringBuilder sb = new StringBuilder(); diff --git a/pom.mustache b/pom.mustache index 75b0e9ef5c6..efe442bef78 100644 --- a/pom.mustache +++ b/pom.mustache @@ -159,11 +159,6 @@ maven-compiler-plugin 3.6.1 - {{#supportJava6}} - 1.6 - 1.6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} 1.8 1.8 @@ -172,7 +167,6 @@ 1.7 1.7 {{/java8}} - {{/supportJava6}} @@ -181,17 +175,12 @@ 3.1.1 none - {{#supportJava6}} - 1.6 - {{/supportJava6}} - {{^supportJava6}} {{#java8}} 1.8 {{/java8}} {{^java8}} 1.7 {{/java8}} - {{/supportJava6}} @@ -329,18 +318,6 @@ 2.2 {{/java8}} - {{#supportJava6}} - - org.apache.commons - commons-lang3 - ${commons_lang3_version} - - - commons-io - commons-io - ${commons_io_version} - - {{/supportJava6}} {{#useBeanValidation}} @@ -385,10 +362,6 @@ UTF-8 1.5.21 1.19.4 - {{#supportJava6}} - 2.5 - 3.6 - {{/supportJava6}} 2.10.3 {{#threetenbp}} 2.9.10 From 745a348ff0b3abde722efa8f5d718886883f5798 Mon Sep 17 00:00:00 2001 From: Ricardo Zanini <1538000+ricardozanini@users.noreply.github.com> Date: Thu, 28 Jan 2021 04:26:42 -0300 Subject: [PATCH 339/370] Fix #8492 - Use Vertx reference instead of static class (#8501) --- libraries/vertx/ApiClient.mustache | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/vertx/ApiClient.mustache b/libraries/vertx/ApiClient.mustache index 3c17645d6c8..83b6e863ae2 100644 --- a/libraries/vertx/ApiClient.mustache +++ b/libraries/vertx/ApiClient.mustache @@ -123,10 +123,10 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { public synchronized WebClient getWebClient() { String webClientIdentifier = "web-client-" + identifier; - WebClient webClient = Vertx.currentContext().get(webClientIdentifier); + WebClient webClient = this.vertx.getOrCreateContext().get(webClientIdentifier); if (webClient == null) { webClient = buildWebClient(vertx, config); - Vertx.currentContext().put(webClientIdentifier, webClient); + this.vertx.getOrCreateContext().put(webClientIdentifier, webClient); } return webClient; } From e6d9f331f39536a41cee4d871ca0060290ca7f08 Mon Sep 17 00:00:00 2001 From: Oleh Kurpiak Date: Fri, 29 Jan 2021 05:22:37 +0200 Subject: [PATCH 340/370] [Java] fix generation for JavaTimeFormatter (#8348) * [Java] fix generation for JavaTimeFormatter * [Java] fix generation for JavaTimeFormatter * [Java] fix generation for JavaTimeFormatter * [Java] fix generation for JavaTimeFormatter * [Java] fix generation for JavaTimeFormatter * [Java] fix generation for JavaTimeFormatter * [Java] fix generation for JavaTimeFormatter * [Java] fix generation for JavaTimeFormatter * [Java] fix generation for JavaTimeFormatter --- ApiClient.mustache | 8 +++++--- JavaTimeFormatter.mustache | 7 +++++++ libraries/jersey2/ApiClient.mustache | 15 ++++++++++----- libraries/resteasy/ApiClient.mustache | 15 ++++++++++----- libraries/resttemplate/ApiClient.mustache | 10 +++++----- libraries/vertx/ApiClient.mustache | 15 ++++++++++----- libraries/webclient/ApiClient.mustache | 15 ++++++++++----- 7 files changed, 57 insertions(+), 28 deletions(-) diff --git a/ApiClient.mustache b/ApiClient.mustache index 262110a2992..d75e455961c 100644 --- a/ApiClient.mustache +++ b/ApiClient.mustache @@ -12,7 +12,9 @@ import com.fasterxml.jackson.datatype.joda.JodaModule; {{/joda}} {{#java8}} import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{^threetenbp}} import java.time.OffsetDateTime; +{{/threetenbp}} {{/java8}} {{#threetenbp}} import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; @@ -68,7 +70,7 @@ import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} {{>generatedAnnotation}} -public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { +public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { private Map defaultHeaderMap = new HashMap(); private Map defaultCookieMap = new HashMap(); private String basePath = "{{{basePath}}}"; @@ -500,9 +502,9 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { return ""; } else if (param instanceof Date) { return formatDate((Date) param); - } {{#java8}}else if (param instanceof OffsetDateTime) { + } {{#jsr310}}else if (param instanceof OffsetDateTime) { return formatOffsetDateTime((OffsetDateTime) param); - } {{/java8}}else if (param instanceof Collection) { + } {{/jsr310}}else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); for(Object o : (Collection)param) { if(b.length() > 0) { diff --git a/JavaTimeFormatter.mustache b/JavaTimeFormatter.mustache index f3fb34e559c..07d0eb6ce72 100644 --- a/JavaTimeFormatter.mustache +++ b/JavaTimeFormatter.mustache @@ -1,9 +1,16 @@ {{>licenseInfo}} package {{invokerPackage}}; +{{^threetenbp}} import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; +{{/threetenbp}} +{{#threetenbp}} +import org.threeten.bp.OffsetDateTime; +import org.threeten.bp.format.DateTimeFormatter; +import org.threeten.bp.format.DateTimeParseException; +{{/threetenbp}} /** * Class that add parsing/formatting support for Java 8+ {@code OffsetDateTime} class. diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 69727cd0ace..294949c6c77 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -49,9 +49,14 @@ import java.util.List; import java.util.Arrays; import java.util.ArrayList; import java.util.Date; -{{#java8}} +{{#jsr310}} +{{#threetenbp}} +import org.threeten.bp.OffsetDateTime; +{{/threetenbp}} +{{^threetenbp}} import java.time.OffsetDateTime; -{{/java8}} +{{/threetenbp}} +{{/jsr310}} import java.net.URLEncoder; @@ -74,7 +79,7 @@ import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} {{>generatedAnnotation}} -public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { +public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { protected Map defaultHeaderMap = new HashMap(); protected Map defaultCookieMap = new HashMap(); protected String basePath = "{{{basePath}}}"; @@ -714,9 +719,9 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { return ""; } else if (param instanceof Date) { return formatDate((Date) param); - } {{#java8}}else if (param instanceof OffsetDateTime) { + } {{#jsr310}}else if (param instanceof OffsetDateTime) { return formatOffsetDateTime((OffsetDateTime) param); - } {{/java8}}else if (param instanceof Collection) { + } {{/jsr310}}else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); for(Object o : (Collection)param) { if(b.length() > 0) { diff --git a/libraries/resteasy/ApiClient.mustache b/libraries/resteasy/ApiClient.mustache index a4489c1e8d1..f361ff551cd 100644 --- a/libraries/resteasy/ApiClient.mustache +++ b/libraries/resteasy/ApiClient.mustache @@ -22,9 +22,14 @@ import java.util.Map.Entry; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; -{{#java8}} +{{#jsr310}} +{{#threetenbp}} +import org.threeten.bp.OffsetDateTime; +{{/threetenbp}} +{{^threetenbp}} import java.time.OffsetDateTime; -{{/java8}} +{{/threetenbp}} +{{/jsr310}} import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; @@ -51,7 +56,7 @@ import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} {{>generatedAnnotation}} -public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { +public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { private Map defaultHeaderMap = new HashMap(); private Map defaultCookieMap = new HashMap(); private String basePath = "{{{basePath}}}"; @@ -336,9 +341,9 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { return ""; } else if (param instanceof Date) { return formatDate((Date) param); - } {{#java8}}else if (param instanceof OffsetDateTime) { + } {{#jsr310}}else if (param instanceof OffsetDateTime) { return formatOffsetDateTime((OffsetDateTime) param); - } {{/java8}}else if (param instanceof Collection) { + } {{/jsr310}}else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); for(Object o : (Collection)param) { if(b.length() > 0) { diff --git a/libraries/resttemplate/ApiClient.mustache b/libraries/resttemplate/ApiClient.mustache index 315fcdd4415..150f3d3ebbb 100644 --- a/libraries/resttemplate/ApiClient.mustache +++ b/libraries/resttemplate/ApiClient.mustache @@ -66,9 +66,9 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.TimeZone; -{{#java8}} +{{#jsr310}}{{^threetenbp}} import java.time.OffsetDateTime; -{{/java8}} +{{/threetenbp}}{{/jsr310}} import {{invokerPackage}}.auth.Authentication; {{#hasHttpBasicMethods}} @@ -86,7 +86,7 @@ import {{invokerPackage}}.auth.OAuth; {{>generatedAnnotation}} @Component("{{invokerPackage}}.ApiClient") -public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { +public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { public enum CollectionFormat { CSV(","), TSV("\t"), SSV(" "), PIPES("|"), MULTI(null); @@ -407,9 +407,9 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { return ""; } else if (param instanceof Date) { return formatDate( (Date) param); - } {{#java8}}else if (param instanceof OffsetDateTime) { + } {{#jsr310}}else if (param instanceof OffsetDateTime) { return formatOffsetDateTime((OffsetDateTime) param); - } {{/java8}}else if (param instanceof Collection) { + } {{/jsr310}}else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); for(Object o : (Collection) param) { if(b.length() > 0) { diff --git a/libraries/vertx/ApiClient.mustache b/libraries/vertx/ApiClient.mustache index 83b6e863ae2..95951e3c06a 100644 --- a/libraries/vertx/ApiClient.mustache +++ b/libraries/vertx/ApiClient.mustache @@ -33,9 +33,14 @@ import io.vertx.ext.web.client.HttpResponse; import io.vertx.ext.web.client.WebClient; import io.vertx.ext.web.client.WebClientOptions; -{{#java8}} +{{#jsr310}} +{{#threetenbp}} +import org.threeten.bp.OffsetDateTime; +{{/threetenbp}} +{{^threetenbp}} import java.time.OffsetDateTime; -{{/java8}} +{{/threetenbp}} +{{/jsr310}} import java.text.DateFormat; import java.util.*; import java.util.function.Consumer; @@ -45,7 +50,7 @@ import java.util.regex.Pattern; import static java.util.stream.Collectors.toMap; {{>generatedAnnotation}} -public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { +public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { private static final Pattern CONTENT_DISPOSITION_PATTERN = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?"); private static final OpenOptions FILE_DOWNLOAD_OPTIONS = new OpenOptions().setCreate(true).setTruncateExisting(true); @@ -298,9 +303,9 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { return ""; } else if (param instanceof Date) { return formatDate((Date) param); - } {{#java8}}else if (param instanceof OffsetDateTime) { + } {{#jsr310}}else if (param instanceof OffsetDateTime) { return formatOffsetDateTime((OffsetDateTime) param); - } {{/java8}}else if (param instanceof Collection) { + } {{/jsr310}}else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); for (Object o : (Collection) param) { if (b.length() > 0) { diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index dcd72c7e113..4d951239ea2 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -59,9 +59,14 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.TimeZone; -{{#java8}} +{{#jsr310}} +{{#threetenbp}} +import org.threeten.bp.OffsetDateTime; +{{/threetenbp}} +{{^threetenbp}} import java.time.OffsetDateTime; -{{/java8}} +{{/threetenbp}} +{{/jsr310}} import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; @@ -72,7 +77,7 @@ import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} {{>generatedAnnotation}} -public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { +public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { public enum CollectionFormat { CSV(","), TSV("\t"), SSV(" "), PIPES("|"), MULTI(null); @@ -357,9 +362,9 @@ public class ApiClient{{#java8}} extends JavaTimeFormatter{{/java8}} { return ""; } else if (param instanceof Date) { return formatDate( (Date) param); - } {{#java8}}else if (param instanceof OffsetDateTime) { + } {{#jsr310}}else if (param instanceof OffsetDateTime) { return formatOffsetDateTime((OffsetDateTime) param); - } {{/java8}}else if (param instanceof Collection) { + } {{/jsr310}}else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); for(Object o : (Collection) param) { if(b.length() > 0) { From 771924418b1a9ca67479b825d1a7e640cc080306 Mon Sep 17 00:00:00 2001 From: Jens Oberender <1905126+burberius@users.noreply.github.com> Date: Wed, 3 Feb 2021 02:45:09 +0100 Subject: [PATCH 341/370] Upgraded dependency versions in okhttp generator. (#8604) Co-authored-by: Jens Oberender --- libraries/okhttp-gson/pom.mustache | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/okhttp-gson/pom.mustache b/libraries/okhttp-gson/pom.mustache index d99f278244e..74a1b796dcd 100644 --- a/libraries/okhttp-gson/pom.mustache +++ b/libraries/okhttp-gson/pom.mustache @@ -330,16 +330,16 @@ {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}} ${java.version} ${java.version} - 1.8.4 - 1.5.24 - 3.14.7 + 1.8.5 + 1.6.2 + 4.9.1 2.8.6 - 3.10 + 3.11 {{#joda}} - 2.9.9 + 2.10.9 {{/joda}} {{#threetenbp}} - 1.4.3 + 1.5.0 {{/threetenbp}} 1.3.2 4.13.1 From e018744cbb8a205ba2f88b4bb41c905bfc0d47a1 Mon Sep 17 00:00:00 2001 From: Benjamin Klatt Date: Mon, 8 Feb 2021 03:33:57 +0100 Subject: [PATCH 342/370] FIX #8583 [BUG][JAVA] AbstractOpenApiSchema package (#8635) Fixed package declaration in AbstractOpenApiSchema.mustache template --- libraries/native/AbstractOpenApiSchema.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/native/AbstractOpenApiSchema.mustache b/libraries/native/AbstractOpenApiSchema.mustache index 5b2198dedb5..d7d9ee9e740 100644 --- a/libraries/native/AbstractOpenApiSchema.mustache +++ b/libraries/native/AbstractOpenApiSchema.mustache @@ -1,6 +1,6 @@ {{>licenseInfo}} -package {{invokerPackage}}.model; +package {{modelPackage}}; import {{invokerPackage}}.ApiException; import java.util.Objects; From 9ceed141b2ca92b06ab0d21ddd8a89d1a550fde8 Mon Sep 17 00:00:00 2001 From: Reinhard-PTV <77726540+Reinhard-PTV@users.noreply.github.com> Date: Mon, 8 Feb 2021 12:25:58 +0100 Subject: [PATCH 343/370] Do not use context timezone. (#8614) --- libraries/native/ApiClient.mustache | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/native/ApiClient.mustache b/libraries/native/ApiClient.mustache index 4fff8b5e962..d38af2abb69 100644 --- a/libraries/native/ApiClient.mustache +++ b/libraries/native/ApiClient.mustache @@ -156,6 +156,7 @@ public class ApiClient { mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); mapper.registerModule(new JavaTimeModule()); {{#openApiNullable}} JsonNullableModule jnm = new JsonNullableModule(); From 345df3d81e4692dc51e5f17d58f10237648e2c2f Mon Sep 17 00:00:00 2001 From: Reinhard-PTV <77726540+Reinhard-PTV@users.noreply.github.com> Date: Mon, 8 Feb 2021 16:03:29 +0100 Subject: [PATCH 344/370] Fixed serialization of date-time query parameters. (#8616) --- libraries/native/ApiClient.mustache | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libraries/native/ApiClient.mustache b/libraries/native/ApiClient.mustache index d38af2abb69..abdea5d8f27 100644 --- a/libraries/native/ApiClient.mustache +++ b/libraries/native/ApiClient.mustache @@ -18,6 +18,10 @@ import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.nio.charset.Charset; import java.time.Duration; +{{#java8}} +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +{{/java8}} import java.util.Collection; import java.util.Collections; import java.util.List; @@ -57,6 +61,11 @@ public class ApiClient { if (value == null) { return ""; } + {{#java8}} + if (value instanceof OffsetDateTime) { + return ((OffsetDateTime) value).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); + } + {{/java8}} return value.toString(); } @@ -87,7 +96,7 @@ public class ApiClient { if (name == null || name.isEmpty() || value == null) { return Collections.emptyList(); } - return Collections.singletonList(new Pair(urlEncode(name), urlEncode(value.toString()))); + return Collections.singletonList(new Pair(urlEncode(name), urlEncode(valueToString(value)))); } /** From 7bdc76e11630fa953a6f38e8dd2d204c60ddebc3 Mon Sep 17 00:00:00 2001 From: Moshe Elisha Date: Fri, 12 Feb 2021 17:02:13 +0200 Subject: [PATCH 345/370] [JAVA][native] - Fix #8027 - import the auto generated supporting JSON class only when discriminator is needed (#8554) * Fix #8027 - import the auto generated supporting JSON class only when generateSupportingFiles is true * Fix #8027 - import the auto generated supporting JSON class only when generateSupportingFiles is true * Fix #8027 - import the auto generated supporting JSON class only when generateSupportingFiles is true * Revert "Fix #8027 - import the auto generated supporting JSON class only when generateSupportingFiles is true" This reverts commit 56e2b1fb * Revert "Fix #8027 - import the auto generated supporting JSON class only when generateSupportingFiles is true" This reverts commit 335c304d * Fix #8027 - import the auto generated supporting JSON class only when generateSupportingFiles is true * Fix #8027 - import the auto generated supporting JSON class only when discriminator is needed * Fix #8027 - import the auto generated supporting JSON class only when discriminator is needed * Fix #8027 - import the auto generated supporting JSON class only when discriminator is needed --- libraries/native/model.mustache | 1 - libraries/native/pojo.mustache | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/native/model.mustache b/libraries/native/model.mustache index 18ee1211785..db4fbfd9fbc 100644 --- a/libraries/native/model.mustache +++ b/libraries/native/model.mustache @@ -46,7 +46,6 @@ import javax.validation.Valid; {{#performBeanValidation}} import org.hibernate.validator.constraints.*; {{/performBeanValidation}} -import {{invokerPackage}}.JSON; {{#models}} {{#model}} diff --git a/libraries/native/pojo.mustache b/libraries/native/pojo.mustache index e7053dcc39a..b2a919dea3f 100644 --- a/libraries/native/pojo.mustache +++ b/libraries/native/pojo.mustache @@ -1,3 +1,6 @@ +{{#discriminator}} +import {{invokerPackage}}.JSON; +{{/discriminator}} /** * {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}} */{{#description}} From b4fae8006f216376e0eda3942b12a4cf7cde40e7 Mon Sep 17 00:00:00 2001 From: Reinhard-PTV <77726540+Reinhard-PTV@users.noreply.github.com> Date: Sun, 14 Feb 2021 04:03:08 +0100 Subject: [PATCH 346/370] [java native][dotnetcore] Implement QueryParameter deepObject style for client generators java native and dotnetcore. (#8563) --- libraries/native/api.mustache | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libraries/native/api.mustache b/libraries/native/api.mustache index b974f790ee8..2adef3a6b0e 100644 --- a/libraries/native/api.mustache +++ b/libraries/native/api.mustache @@ -283,7 +283,16 @@ public class {{classname}} { localVarQueryParams.addAll(ApiClient.parameterToPairs("{{{collectionFormat}}}", "{{baseName}}", {{paramName}})); {{/collectionFormat}} {{^collectionFormat}} + {{#isDeepObject}} + if ({{paramName}} != null) { + {{#items.vars}} + localVarQueryParams.addAll(ApiClient.parameterToPairs("{{baseName}}", {{paramName}}.{{getter}}())); + {{/items.vars}} + } + {{/isDeepObject}} + {{^isDeepObject}} localVarQueryParams.addAll(ApiClient.parameterToPairs("{{baseName}}", {{paramName}})); + {{/isDeepObject}} {{/collectionFormat}} {{/queryParams}} From 471e82c3587e1261d41310ba513ebb31337c99e1 Mon Sep 17 00:00:00 2001 From: Oleh Kurpiak Date: Tue, 16 Feb 2021 15:47:44 +0200 Subject: [PATCH 347/370] [Java][native] extend native ApiClient (#8557) --- libraries/native/ApiClient.mustache | 52 ++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/libraries/native/ApiClient.mustache b/libraries/native/ApiClient.mustache index abdea5d8f27..4c915fb3f38 100644 --- a/libraries/native/ApiClient.mustache +++ b/libraries/native/ApiClient.mustache @@ -157,8 +157,28 @@ public class ApiClient { * Ctor. */ public ApiClient() { - builder = HttpClient.newBuilder(); - mapper = new ObjectMapper(); + this.builder = createDefaultHttpClientBuilder(); + this.mapper = createDefaultObjectMapper(); + updateBaseUri(getDefaultBaseUri()); + interceptor = null; + readTimeout = null; + responseInterceptor = null; + } + + /** + * Ctor. + */ + public ApiClient(HttpClient.Builder builder, ObjectMapper mapper, String baseUri) { + this.builder = builder; + this.mapper = mapper; + updateBaseUri(baseUri); + interceptor = null; + readTimeout = null; + responseInterceptor = null; + } + + protected ObjectMapper createDefaultObjectMapper() { + ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); @@ -168,17 +188,25 @@ public class ApiClient { mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); mapper.registerModule(new JavaTimeModule()); {{#openApiNullable}} - JsonNullableModule jnm = new JsonNullableModule(); - mapper.registerModule(jnm); + mapper.registerModule(new JsonNullableModule()); {{/openApiNullable}} - URI baseURI = URI.create("{{{basePath}}}"); - scheme = baseURI.getScheme(); - host = baseURI.getHost(); - port = baseURI.getPort(); - basePath = baseURI.getRawPath(); - interceptor = null; - readTimeout = null; - responseInterceptor = null; + return mapper; + } + + protected String getDefaultBaseUri() { + return "{{{basePath}}}"; + } + + protected HttpClient.Builder createDefaultHttpClientBuilder() { + return HttpClient.newBuilder(); + } + + public void updateBaseUri(String baseUri) { + URI uri = URI.create(baseUri); + scheme = uri.getScheme(); + host = uri.getHost(); + port = uri.getPort(); + basePath = uri.getRawPath(); } /** From 32d27f898c0caeb402792fb05ab514e66c9634d1 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Sun, 21 Feb 2021 11:40:24 +0800 Subject: [PATCH 348/370] update jackson dependencies to address security issues (#8778) --- build.gradle.mustache | 2 +- libraries/google-api-client/build.gradle.mustache | 2 +- libraries/google-api-client/build.sbt.mustache | 2 +- libraries/jersey2/build.gradle.mustache | 4 ++-- libraries/jersey2/build.sbt.mustache | 6 +++--- libraries/jersey2/pom.mustache | 4 ++-- libraries/resteasy/build.gradle.mustache | 4 ++-- libraries/resteasy/build.sbt.mustache | 6 +++--- libraries/resteasy/pom.mustache | 4 ++-- libraries/resttemplate/build.gradle.mustache | 4 ++-- libraries/resttemplate/pom.mustache | 4 ++-- libraries/retrofit2/build.gradle.mustache | 4 ++-- libraries/retrofit2/build.sbt.mustache | 6 +++--- libraries/retrofit2/pom.mustache | 2 +- libraries/vertx/build.gradle.mustache | 4 ++-- libraries/vertx/pom.mustache | 4 ++-- 16 files changed, 31 insertions(+), 31 deletions(-) diff --git a/build.gradle.mustache b/build.gradle.mustache index a14862d3a81..fb6dece5726 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -125,7 +125,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" jackson_version = "2.10.3" - jackson_databind_version = "2.10.4" + jackson_databind_version = "2.10.5.1" {{#openApiNullable}} jackson_databind_nullable_version = "0.2.1" {{/openApiNullable}} diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache index 14d93d588dc..661917bc42b 100644 --- a/libraries/google-api-client/build.gradle.mustache +++ b/libraries/google-api-client/build.gradle.mustache @@ -109,7 +109,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" jackson_version = "2.10.1" - jackson_databind_version = "2.10.4" + jackson_databind_version = "2.10.5.1" {{#openApiNullable}} jackson_databind_nullable_version = "0.2.1" {{/openApiNullable}} diff --git a/libraries/google-api-client/build.sbt.mustache b/libraries/google-api-client/build.sbt.mustache index f22448cb04f..c3f91793bbc 100644 --- a/libraries/google-api-client/build.sbt.mustache +++ b/libraries/google-api-client/build.sbt.mustache @@ -14,7 +14,7 @@ lazy val root = (project in file(".")). "org.glassfish.jersey.core" % "jersey-common" % "2.25.1", "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.4" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.5.1" % "compile", {{#withXml}} "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.9.10" % "compile", {{/withXml}} diff --git a/libraries/jersey2/build.gradle.mustache b/libraries/jersey2/build.gradle.mustache index a15919fb9bb..378de9fb1e1 100644 --- a/libraries/jersey2/build.gradle.mustache +++ b/libraries/jersey2/build.gradle.mustache @@ -107,8 +107,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.10.3" - jackson_databind_version = "2.10.4" + jackson_version = "2.10.5" + jackson_databind_version = "2.10.5.1" {{#openApiNullable}} jackson_databind_nullable_version = "0.2.1" {{/openApiNullable}} diff --git a/libraries/jersey2/build.sbt.mustache b/libraries/jersey2/build.sbt.mustache index 52f17959a63..9823c3c657e 100644 --- a/libraries/jersey2/build.sbt.mustache +++ b/libraries/jersey2/build.sbt.mustache @@ -15,9 +15,9 @@ lazy val root = (project in file(".")). "org.glassfish.jersey.media" % "jersey-media-multipart" % "2.27", "org.glassfish.jersey.media" % "jersey-media-json-jackson" % "2.27", "org.glassfish.jersey.connectors" % "jersey-apache-connector" % "2.27", - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.4" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.4" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.4" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.5" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.5.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.5.1" % "compile", {{#joda}} "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.10" % "compile", {{/joda}} diff --git a/libraries/jersey2/pom.mustache b/libraries/jersey2/pom.mustache index e7765a50d1b..f36f0cd8817 100644 --- a/libraries/jersey2/pom.mustache +++ b/libraries/jersey2/pom.mustache @@ -373,8 +373,8 @@ UTF-8 1.6.1 2.30.1 - 2.10.4 - 2.10.4 + 2.10.5 + 2.10.5.1 0.2.1 {{#threetenbp}} 2.9.10 diff --git a/libraries/resteasy/build.gradle.mustache b/libraries/resteasy/build.gradle.mustache index 3823153acc7..fe6c7b1f8d0 100644 --- a/libraries/resteasy/build.gradle.mustache +++ b/libraries/resteasy/build.gradle.mustache @@ -107,8 +107,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.10.4" - jackson_databind_version = "2.10.4" + jackson_version = "2.10.5" + jackson_databind_version = "2.10.5.1" {{#openApiNullable}} jackson_databind_nullable_version = "0.2.1" {{/openApiNullable}} diff --git a/libraries/resteasy/build.sbt.mustache b/libraries/resteasy/build.sbt.mustache index 79600b7754c..c2dfff284b0 100644 --- a/libraries/resteasy/build.sbt.mustache +++ b/libraries/resteasy/build.sbt.mustache @@ -13,9 +13,9 @@ lazy val root = (project in file(".")). "org.jboss.resteasy" % "resteasy-client" % "3.1.3.Final" % "compile", "org.jboss.resteasy" % "resteasy-multipart-provider" % "3.1.3.Final" % "compile", "org.jboss.resteasy" % "resteasy-jackson2-provider" % "3.1.3.Final" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.4" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.4" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.4" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.5" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.5" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.5.1" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", {{#java8}} "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.10" % "compile", diff --git a/libraries/resteasy/pom.mustache b/libraries/resteasy/pom.mustache index 82c5a036087..084f42df9bd 100644 --- a/libraries/resteasy/pom.mustache +++ b/libraries/resteasy/pom.mustache @@ -285,8 +285,8 @@ UTF-8 1.5.22 3.1.3.Final - 2.10.4 - 2.10.4 + 2.10.5 + 2.10.5.1 0.2.1 1.3.2 2.9.10 diff --git a/libraries/resttemplate/build.gradle.mustache b/libraries/resttemplate/build.gradle.mustache index 11235a89bb7..433d396baf4 100644 --- a/libraries/resttemplate/build.gradle.mustache +++ b/libraries/resttemplate/build.gradle.mustache @@ -108,8 +108,8 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.10.4" - jackson_databind_version = "2.10.4" + jackson_version = "2.10.5" + jackson_databind_version = "2.10.5.1" {{#openApiNullable}} jackson_databind_nullable_version = "0.2.1" {{/openApiNullable}} diff --git a/libraries/resttemplate/pom.mustache b/libraries/resttemplate/pom.mustache index ca273093471..17dd7024edd 100644 --- a/libraries/resttemplate/pom.mustache +++ b/libraries/resttemplate/pom.mustache @@ -317,8 +317,8 @@ UTF-8 1.5.22 5.2.5.RELEASE - 2.10.4 - 2.10.4 + 2.10.5 + 2.10.5.1 0.2.1 1.3.2 {{#joda}} diff --git a/libraries/retrofit2/build.gradle.mustache b/libraries/retrofit2/build.gradle.mustache index 2bb2fb35613..090eefa3383 100644 --- a/libraries/retrofit2/build.gradle.mustache +++ b/libraries/retrofit2/build.gradle.mustache @@ -110,8 +110,8 @@ ext { oltu_version = "1.0.1" retrofit_version = "2.3.0" {{#usePlayWS}} - jackson_version = "2.10.4" - jackson_databind_version = "2.10.4" + jackson_version = "2.10.5" + jackson_databind_version = "2.10.5.1" {{#openApiNullable}} jackson_databind_nullable_version = "0.2.1" {{/openApiNullable}} diff --git a/libraries/retrofit2/build.sbt.mustache b/libraries/retrofit2/build.sbt.mustache index 8d386e34d84..a9301f736a4 100644 --- a/libraries/retrofit2/build.sbt.mustache +++ b/libraries/retrofit2/build.sbt.mustache @@ -26,9 +26,9 @@ lazy val root = (project in file(".")). "javax.validation" % "validation-api" % "1.1.0.Final" % "compile", {{/play26}} "com.squareup.retrofit2" % "converter-jackson" % "2.3.0" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.4" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.4" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.4" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.5" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.5" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.5.1" % "compile", {{/usePlayWS}} {{#useRxJava}} "com.squareup.retrofit2" % "adapter-rxjava" % "2.3.0" % "compile", diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index 32d395bf02e..b48bd384bd1 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -409,7 +409,7 @@ 1.8.3 1.5.22 {{#usePlayWS}} - 2.10.4 + 2.10.5 {{#play24}} 2.4.11 {{/play24}} diff --git a/libraries/vertx/build.gradle.mustache b/libraries/vertx/build.gradle.mustache index cb2910c8430..143a1936217 100644 --- a/libraries/vertx/build.gradle.mustache +++ b/libraries/vertx/build.gradle.mustache @@ -28,8 +28,8 @@ task execute(type:JavaExec) { ext { swagger_annotations_version = "1.5.21" - jackson_version = "2.10.4" - jackson_databind_version = "2.10.4" + jackson_version = "2.10.5" + jackson_databind_version = "2.10.5.1" vertx_version = "3.4.2" junit_version = "4.13.1" {{#openApiNullable}} diff --git a/libraries/vertx/pom.mustache b/libraries/vertx/pom.mustache index b4064662a98..cbd5d580b12 100644 --- a/libraries/vertx/pom.mustache +++ b/libraries/vertx/pom.mustache @@ -306,8 +306,8 @@ UTF-8 3.4.2 1.5.22 - 2.10.4 - 2.10.4 + 2.10.5 + 2.10.5.1 0.2.1 1.3.2 4.13.1 From 79fffc5ee2d6b94b912af614ab9c066482f35d55 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Sun, 21 Feb 2021 17:53:23 +0800 Subject: [PATCH 349/370] update jackson to 2.12.1 (#8783) --- build.gradle.mustache | 2 +- libraries/google-api-client/build.gradle.mustache | 2 +- libraries/google-api-client/build.sbt.mustache | 2 +- libraries/google-api-client/pom.mustache | 2 +- libraries/retrofit2/pom.mustache | 2 +- pom.mustache | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build.gradle.mustache b/build.gradle.mustache index fb6dece5726..95fc41cbf42 100644 --- a/build.gradle.mustache +++ b/build.gradle.mustache @@ -124,7 +124,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.10.3" + jackson_version = "2.12.1" jackson_databind_version = "2.10.5.1" {{#openApiNullable}} jackson_databind_nullable_version = "0.2.1" diff --git a/libraries/google-api-client/build.gradle.mustache b/libraries/google-api-client/build.gradle.mustache index 661917bc42b..6be8600c7da 100644 --- a/libraries/google-api-client/build.gradle.mustache +++ b/libraries/google-api-client/build.gradle.mustache @@ -108,7 +108,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.22" - jackson_version = "2.10.1" + jackson_version = "2.12.1" jackson_databind_version = "2.10.5.1" {{#openApiNullable}} jackson_databind_nullable_version = "0.2.1" diff --git a/libraries/google-api-client/build.sbt.mustache b/libraries/google-api-client/build.sbt.mustache index c3f91793bbc..be30ae48caf 100644 --- a/libraries/google-api-client/build.sbt.mustache +++ b/libraries/google-api-client/build.sbt.mustache @@ -12,7 +12,7 @@ lazy val root = (project in file(".")). "io.swagger" % "swagger-annotations" % "1.5.22", "com.google.api-client" % "google-api-client" % "1.23.0", "org.glassfish.jersey.core" % "jersey-common" % "2.25.1", - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.12.1" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.5.1" % "compile", {{#withXml}} diff --git a/libraries/google-api-client/pom.mustache b/libraries/google-api-client/pom.mustache index 3a4b62e203b..fdcb6953faf 100644 --- a/libraries/google-api-client/pom.mustache +++ b/libraries/google-api-client/pom.mustache @@ -317,7 +317,7 @@ 1.5.22 1.30.2 2.25.1 - 2.10.4 + 2.12.1 2.10.4 {{#openApiNullable}} 0.2.1 diff --git a/libraries/retrofit2/pom.mustache b/libraries/retrofit2/pom.mustache index b48bd384bd1..b8b3d5dcb28 100644 --- a/libraries/retrofit2/pom.mustache +++ b/libraries/retrofit2/pom.mustache @@ -409,7 +409,7 @@ 1.8.3 1.5.22 {{#usePlayWS}} - 2.10.5 + 2.12.1 {{#play24}} 2.4.11 {{/play24}} diff --git a/pom.mustache b/pom.mustache index efe442bef78..20b602c5421 100644 --- a/pom.mustache +++ b/pom.mustache @@ -362,7 +362,7 @@ UTF-8 1.5.21 1.19.4 - 2.10.3 + 2.12.1 {{#threetenbp}} 2.9.10 {{/threetenbp}} From f7089c502917284b68626f6ad582fb171d300508 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Tue, 23 Feb 2021 11:40:37 +0800 Subject: [PATCH 350/370] [Java] use Files.createTempFile instead (#8787) * use Files.createTempFile * fix import * add missing import --- libraries/jersey2/ApiClient.mustache | 7 ++++--- libraries/okhttp-gson/ApiClient.mustache | 10 ++++++---- libraries/resteasy/ApiClient.mustache | 9 +++++---- libraries/retrofit2/play26/ApiClient.mustache | 7 ++++--- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/libraries/jersey2/ApiClient.mustache b/libraries/jersey2/ApiClient.mustache index 294949c6c77..d12dec1bbdb 100644 --- a/libraries/jersey2/ApiClient.mustache +++ b/libraries/jersey2/ApiClient.mustache @@ -35,6 +35,7 @@ import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.nio.file.Files; +import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import org.glassfish.jersey.logging.LoggingFeature; import java.util.logging.Level; @@ -1027,15 +1028,15 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { prefix = filename.substring(0, pos) + "-"; suffix = filename.substring(pos); } - // File.createTempFile requires the prefix to be at least three characters long + // Files.createTempFile requires the prefix to be at least three characters long if (prefix.length() < 3) prefix = "download-"; } if (tempFolderPath == null) - return File.createTempFile(prefix, suffix); + return Files.createTempFile(prefix, suffix).toFile(); else - return File.createTempFile(prefix, suffix, new File(tempFolderPath)); + return Files.createTempFile(Paths.get(tempFolderPath), prefix, suffix).toFile(); } /** diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index f12320b3e4b..e3eceebf93d 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -41,6 +41,8 @@ import java.lang.reflect.Type; import java.net.URI; import java.net.URLConnection; import java.net.URLEncoder; +import java.nio.file.Files; +import java.nio.file.Paths; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.SecureRandom; @@ -578,7 +580,7 @@ public class ApiClient { * with file response. The default value is null, i.e. using * the system's default tempopary folder. * - * @see createTempFile + * @see createTempFile * @return Temporary folder path */ public String getTempFolderPath() { @@ -1077,15 +1079,15 @@ public class ApiClient { prefix = filename.substring(0, pos) + "-"; suffix = filename.substring(pos); } - // File.createTempFile requires the prefix to be at least three characters long + // Files.createTempFile requires the prefix to be at least three characters long if (prefix.length() < 3) prefix = "download-"; } if (tempFolderPath == null) - return File.createTempFile(prefix, suffix); + return Files.createTempFile(prefix, suffix).toFile(); else - return File.createTempFile(prefix, suffix, new File(tempFolderPath)); + return Files.createTempFile(Paths.get(tempFolderPath), prefix, suffix).toFile(); } /** diff --git a/libraries/resteasy/ApiClient.mustache b/libraries/resteasy/ApiClient.mustache index f361ff551cd..775e0efea40 100644 --- a/libraries/resteasy/ApiClient.mustache +++ b/libraries/resteasy/ApiClient.mustache @@ -8,6 +8,7 @@ import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.file.Files; +import java.nio.file.Paths; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -278,7 +279,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { * the system's default tempopary folder. * * @return the temporary folder path - * @see + * @see createTempFile */ public String getTempFolderPath() { return tempFolderPath; @@ -596,15 +597,15 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { prefix = filename.substring(0, pos) + "-"; suffix = filename.substring(pos); } - // File.createTempFile requires the prefix to be at least three characters long + // Files.createTempFile requires the prefix to be at least three characters long if (prefix.length() < 3) prefix = "download-"; } if (tempFolderPath == null) - return File.createTempFile(prefix, suffix); + return Files.createTempFile(prefix, suffix).toFile(); else - return File.createTempFile(prefix, suffix, new File(tempFolderPath)); + return Files.createTempFile(Paths.get(tempFolderPath), prefix, suffix).toFile(); } /** diff --git a/libraries/retrofit2/play26/ApiClient.mustache b/libraries/retrofit2/play26/ApiClient.mustache index 55db0729449..b752b433d05 100644 --- a/libraries/retrofit2/play26/ApiClient.mustache +++ b/libraries/retrofit2/play26/ApiClient.mustache @@ -5,6 +5,7 @@ import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; @@ -202,9 +203,9 @@ public class ApiClient { @Override public File convert(ResponseBody value) throws IOException { - File file = File.createTempFile("retrofit-file", ".tmp"); - Files.write(Paths.get(file.getPath()), value.bytes()); - return file; + Path path = Files.createTempFile("retrofit-file", ".tmp"); + Files.write(path, value.bytes()); + return path.toFile(); } }; } From 41888fe3c987f9ae448f086ef6359c72da69e5cc Mon Sep 17 00:00:00 2001 From: nitschy Date: Sat, 27 Feb 2021 07:47:11 +0100 Subject: [PATCH 351/370] FIX: Error in mustache.api (#8800) When a GET/PUT/POST operations includes queryParams, then the feign generator wrongly generates the Basename instead of the paramName. That leads to a java.illegalstateException ("Body parameters cannot be used with form parameters") in Feign Contract when attempting to invoke the Method. i.e: a generated feign client: public interface PersonClientTest extends RestApi { @RequestLine("GET /personen/{kundenNummer}?mitUnterstruktur={mitUnterstruktur}") @Headers({ "Accept: application/json", "If-None-Match: {ifNoneMatch}" }) PersonOut getPersonByKundenNummer(@Param(value="kundenNummer", expander=ParamExpander.class) String kundenNummer, @Param(value="If-None-Match", expander=ParamExpander.class) String ifNoneMatch, @Param(value="mitUnterstruktur", expander=ParamExpander.class) Boolean mitUnterstruktur); } in the headers: "If-None-Match: {ifNoneMatch}" but in the method: @Param(value="If-None-Match", expander=ParamExpander.class) String ifNoneMatch the value should be ifNoneMatch instead of "If-None-Match" --- libraries/feign/api.mustache | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/feign/api.mustache b/libraries/feign/api.mustache index f6319c5da5a..df70b712737 100644 --- a/libraries/feign/api.mustache +++ b/libraries/feign/api.mustache @@ -42,7 +42,7 @@ public interface {{classname}} extends ApiClient.Api { "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{^-last}}, {{/-last}}{{/headerParams}} }) - {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{baseName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{paramName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); {{#hasQueryParams}} /** @@ -80,7 +80,7 @@ public interface {{classname}} extends ApiClient.Api { "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{^-last}}, {{/-last}}{{/headerParams}} }) - {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isQueryParam}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{baseName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}, {{/isQueryParam}}{{/allParams}}@QueryMap(encoded=true) Map queryParams); + {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isQueryParam}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{paramName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}, {{/isQueryParam}}{{/allParams}}@QueryMap(encoded=true) Map queryParams); /** * A convenience class for generating query parameters for the From 4473e3dc1ce639924cbb55405ce649f96346f897 Mon Sep 17 00:00:00 2001 From: Dheeraj Nalluri Date: Sat, 27 Feb 2021 01:32:46 -0600 Subject: [PATCH 352/370] [Java][Client] JSON-B serialization support (#8729) * Added JSON-B support. * Mention jsonb in docs --- model.mustache | 12 ++++++++++++ modelEnum.mustache | 27 +++++++++++++++++++++++++++ modelInnerEnum.mustache | 31 +++++++++++++++++++++++++++++++ pojo.mustache | 5 ++++- 4 files changed, 74 insertions(+), 1 deletion(-) diff --git a/model.mustache b/model.mustache index dec0b7dc8ac..8fd078eb3d6 100644 --- a/model.mustache +++ b/model.mustache @@ -23,6 +23,18 @@ import com.fasterxml.jackson.dataformat.xml.annotation.*; {{#withXml}} import javax.xml.bind.annotation.*; {{/withXml}} +{{#jsonb}} +import java.lang.reflect.Type; +import javax.json.bind.annotation.JsonbTypeDeserializer; +import javax.json.bind.annotation.JsonbTypeSerializer; +import javax.json.bind.serializer.DeserializationContext; +import javax.json.bind.serializer.JsonbDeserializer; +import javax.json.bind.serializer.JsonbSerializer; +import javax.json.bind.serializer.SerializationContext; +import javax.json.stream.JsonGenerator; +import javax.json.stream.JsonParser; +import javax.json.bind.annotation.JsonbProperty; +{{/jsonb}} {{#parcelableModel}} import android.os.Parcelable; import android.os.Parcel; diff --git a/modelEnum.mustache b/modelEnum.mustache index 9428bc70f99..10ad58e443b 100644 --- a/modelEnum.mustache +++ b/modelEnum.mustache @@ -16,6 +16,10 @@ import com.google.gson.stream.JsonWriter; {{#gson}} @JsonAdapter({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.Adapter.class) {{/gson}} +{{#jsonb}} +@JsonbTypeSerializer({{datatypeWithEnum}}.Serializer.class) +@JsonbTypeDeserializer({{datatypeWithEnum}}.Deserializer.class) +{{/jsonb}} public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} { {{#allowableValues}}{{#enumVars}} {{#enumDescription}} @@ -23,6 +27,9 @@ public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum * {{enumDescription}} */ {{/enumDescription}} + {{#withXml}} + @XmlEnumValue({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) + {{/withXml}} {{{name}}}({{{value}}}){{^-last}}, {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}} @@ -70,4 +77,24 @@ public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum } } {{/gson}} +{{#jsonb}} + public static final class Deserializer implements JsonbDeserializer<{{datatypeWithEnum}}> { + @Override + public {{datatypeWithEnum}} deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) { + for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + if (String.valueOf(b.value).equals(parser.getString())) { + return b; + } + } + {{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + parser.getString() + "'");{{/useNullForUnknownEnumValue}} + } + } + + public static final class Serializer implements JsonbSerializer<{{datatypeWithEnum}}> { + @Override + public void serialize({{datatypeWithEnum}} obj, JsonGenerator generator, SerializationContext ctx) { + generator.write(obj.value); + } + } +{{/jsonb}} } diff --git a/modelInnerEnum.mustache b/modelInnerEnum.mustache index 101870341f5..942be42b518 100644 --- a/modelInnerEnum.mustache +++ b/modelInnerEnum.mustache @@ -4,6 +4,14 @@ {{#gson}} @JsonAdapter({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.Adapter.class) {{/gson}} +{{#jsonb}} + @JsonbTypeSerializer({{datatypeWithEnum}}.Serializer.class) + @JsonbTypeDeserializer({{datatypeWithEnum}}.Deserializer.class) +{{/jsonb}} +{{#withXml}} + @XmlType(name="{{datatypeWithEnum}}") + @XmlEnum({{dataType}}.class) +{{/withXml}} public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} { {{#allowableValues}} {{#enumVars}} @@ -12,6 +20,9 @@ * {{enumDescription}} */ {{/enumDescription}} + {{#withXml}} + @XmlEnumValue({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) + {{/withXml}} {{{name}}}({{{value}}}){{^-last}}, {{/-last}}{{#-last}};{{/-last}} {{/enumVars}} @@ -61,4 +72,24 @@ } } {{/gson}} +{{#jsonb}} + public static final class Deserializer implements JsonbDeserializer<{{datatypeWithEnum}}> { + @Override + public {{datatypeWithEnum}} deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) { + for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + if (String.valueOf(b.value).equals(parser.getString())) { + return b; + } + } + {{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + parser.getString() + "'");{{/useNullForUnknownEnumValue}} + } + } + + public static final class Serializer implements JsonbSerializer<{{datatypeWithEnum}}> { + @Override + public void serialize({{datatypeWithEnum}} obj, JsonGenerator generator, SerializationContext ctx) { + generator.write(obj.value); + } + } +{{/jsonb}} } diff --git a/pojo.mustache b/pojo.mustache index 81eeb24af08..30454970acf 100644 --- a/pojo.mustache +++ b/pojo.mustache @@ -179,6 +179,9 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{^required}} @javax.annotation.Nullable {{/required}} +{{#jsonb}} + @JsonbProperty("{{baseName}}") +{{/jsonb}} {{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} @ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") {{#vendorExtensions.x-extra-annotation}} {{{vendorExtensions.x-extra-annotation}}} @@ -276,7 +279,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ - private String toIndentedString(Object o) { + private{{#jsonb}} static{{/jsonb}} String toIndentedString(Object o) { if (o == null) { return "null"; } From a6aa6c373f48edb5f5b1dc9eb52c40718c44f637 Mon Sep 17 00:00:00 2001 From: Oleh Kurpiak Date: Thu, 4 Mar 2021 17:33:00 +0200 Subject: [PATCH 353/370] [Java] Additional enum type annotations (#8389) * [Java] Additional enum type annotations * [Java] Additional enum type annotations --- additionalEnumTypeAnnotations.mustache | 2 ++ libraries/microprofile/enumClass.mustache | 2 +- libraries/microprofile/enumOuterClass.mustache | 2 +- modelEnum.mustache | 2 +- modelInnerEnum.mustache | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 additionalEnumTypeAnnotations.mustache diff --git a/additionalEnumTypeAnnotations.mustache b/additionalEnumTypeAnnotations.mustache new file mode 100644 index 00000000000..aa524798b42 --- /dev/null +++ b/additionalEnumTypeAnnotations.mustache @@ -0,0 +1,2 @@ +{{#additionalEnumTypeAnnotations}}{{{.}}} +{{/additionalEnumTypeAnnotations}} \ No newline at end of file diff --git a/libraries/microprofile/enumClass.mustache b/libraries/microprofile/enumClass.mustache index 67e776cbf59..87d5ee699a5 100644 --- a/libraries/microprofile/enumClass.mustache +++ b/libraries/microprofile/enumClass.mustache @@ -6,7 +6,7 @@ @JsonbTypeSerializer({{datatypeWithEnum}}.Serializer.class) @JsonbTypeDeserializer({{datatypeWithEnum}}.Deserializer.class) {{/withXml}} - public enum {{datatypeWithEnum}} { + {{>additionalEnumTypeAnnotations}}public enum {{datatypeWithEnum}} { {{#allowableValues}} {{#withXml}} diff --git a/libraries/microprofile/enumOuterClass.mustache b/libraries/microprofile/enumOuterClass.mustache index df2c7287396..c56eca64b1e 100644 --- a/libraries/microprofile/enumOuterClass.mustache +++ b/libraries/microprofile/enumOuterClass.mustache @@ -6,7 +6,7 @@ import com.fasterxml.jackson.annotation.JsonValue; /** * {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}} */ -public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} { +{{>additionalEnumTypeAnnotations}}public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} { {{#gson}} {{#allowableValues}}{{#enumVars}} @SerializedName({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) diff --git a/modelEnum.mustache b/modelEnum.mustache index 10ad58e443b..207a937ebde 100644 --- a/modelEnum.mustache +++ b/modelEnum.mustache @@ -20,7 +20,7 @@ import com.google.gson.stream.JsonWriter; @JsonbTypeSerializer({{datatypeWithEnum}}.Serializer.class) @JsonbTypeDeserializer({{datatypeWithEnum}}.Deserializer.class) {{/jsonb}} -public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} { +{{>additionalEnumTypeAnnotations}}public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} { {{#allowableValues}}{{#enumVars}} {{#enumDescription}} /** diff --git a/modelInnerEnum.mustache b/modelInnerEnum.mustache index 942be42b518..e0a194d6ba6 100644 --- a/modelInnerEnum.mustache +++ b/modelInnerEnum.mustache @@ -12,7 +12,7 @@ @XmlType(name="{{datatypeWithEnum}}") @XmlEnum({{dataType}}.class) {{/withXml}} - public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} { + {{>additionalEnumTypeAnnotations}}public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} { {{#allowableValues}} {{#enumVars}} {{#enumDescription}} From 1a386bec30abd1d0ce1e476614a2ddf07bcc781d Mon Sep 17 00:00:00 2001 From: Tyler Ballast Date: Mon, 8 Mar 2021 14:40:54 +0100 Subject: [PATCH 354/370] Add whitespace to SDK documentation where necessary (#8919) * Add a space between table title and the line above it to resolve issues when translating markdown to asciidoc * Regenerate Samples Co-authored-by: Tyler Ballast Co-authored-by: tballast --- api_doc.mustache | 1 + pojo_doc.mustache | 1 + 2 files changed, 2 insertions(+) diff --git a/api_doc.mustache b/api_doc.mustache index e68b9b1aef1..55d0244e3a5 100644 --- a/api_doc.mustache +++ b/api_doc.mustache @@ -95,6 +95,7 @@ Name | Type | Description | Notes - **Accept**: {{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}{{^produces}}Not defined{{/produces}} {{#responses.0}} + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/pojo_doc.mustache b/pojo_doc.mustache index 0a42c19469a..f5643754465 100644 --- a/pojo_doc.mustache +++ b/pojo_doc.mustache @@ -3,6 +3,7 @@ {{#description}}{{&description}} {{/description}} {{^vendorExtensions.x-is-one-of-interface}} + ## Properties Name | Type | Description | Notes From 397d28801540be6aa60e3466c8175c38158e7793 Mon Sep 17 00:00:00 2001 From: Backfighter Date: Sat, 13 Mar 2021 17:12:48 +0100 Subject: [PATCH 355/370] [Java][webclient] Fix deprecation warning: BodyInserters.fromObject (#8963) * Fix deprecation warning: BodyInserters.fromObject See for more information #8553 * [Java][webclient] Upgrade to spring 5.2.13 --- libraries/webclient/ApiClient.mustache | 2 +- libraries/webclient/build.gradle.mustache | 2 +- libraries/webclient/pom.mustache | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index 4d951239ea2..0eb66705d9e 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -517,7 +517,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { } else if(MediaType.MULTIPART_FORM_DATA.equals(contentType)) { return BodyInserters.fromMultipartData(formParams); } else { - return obj != null ? BodyInserters.fromObject(obj) : null; + return obj != null ? BodyInserters.fromValue(obj) : null; } } diff --git a/libraries/webclient/build.gradle.mustache b/libraries/webclient/build.gradle.mustache index c892d189243..793ad63cbfe 100644 --- a/libraries/webclient/build.gradle.mustache +++ b/libraries/webclient/build.gradle.mustache @@ -124,7 +124,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.6.2" - spring_web_version = "5.0.16.RELEASE" + spring_web_version = "5.2.13.RELEASE" jackson_version = "2.11.3" jackson_databind_version = "2.11.3" {{#openApiNullable}} diff --git a/libraries/webclient/pom.mustache b/libraries/webclient/pom.mustache index 5aaeec6823d..39c55beb122 100644 --- a/libraries/webclient/pom.mustache +++ b/libraries/webclient/pom.mustache @@ -149,7 +149,7 @@ UTF-8 1.6.2 - 5.0.16.RELEASE + 5.2.13.RELEASE 2.11.3 2.11.3 {{#openApiNullable}} From 524033816778840c7536c1925d8c1270ec7e9c5d Mon Sep 17 00:00:00 2001 From: William Cheng Date: Mon, 15 Mar 2021 09:45:17 +0800 Subject: [PATCH 356/370] fix deprecation warnings (#8969) --- JSON.mustache | 5 +++-- libraries/okhttp-gson/ApiClient.mustache | 12 ++++++------ .../okhttp-gson/auth/OAuthOkHttpClient.mustache | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/JSON.mustache b/JSON.mustache index 590ba386ea2..77b72ddc7fc 100644 --- a/JSON.mustache +++ b/JSON.mustache @@ -61,14 +61,15 @@ public class JSON { {{/jsr310}} private ByteArrayAdapter byteArrayAdapter = new ByteArrayAdapter(); + @SuppressWarnings("unchecked") public static GsonBuilder createGson() { GsonFireBuilder fireBuilder = new GsonFireBuilder() {{#models}} {{#model}} {{#discriminator}} - .registerTypeSelector({{classname}}.class, new TypeSelector() { + .registerTypeSelector({{classname}}.class, new TypeSelector<{{classname}}>() { @Override - public Class getClassForElement(JsonElement readElement) { + public Class getClassForElement(JsonElement readElement) { Map classByDiscriminatorValue = new HashMap(); {{#mappedModels}} classByDiscriminatorValue.put("{{mappingName}}"{{^discriminatorCaseSensitive}}.toUpperCase(Locale.ROOT){{/discriminatorCaseSensitive}}, {{modelName}}.class); diff --git a/libraries/okhttp-gson/ApiClient.mustache b/libraries/okhttp-gson/ApiClient.mustache index e3eceebf93d..37ebae04830 100644 --- a/libraries/okhttp-gson/ApiClient.mustache +++ b/libraries/okhttp-gson/ApiClient.mustache @@ -1011,10 +1011,10 @@ public class ApiClient { public RequestBody serialize(Object obj, String contentType) throws ApiException { if (obj instanceof byte[]) { // Binary (byte array) body parameter support. - return RequestBody.create(MediaType.parse(contentType), (byte[]) obj); + return RequestBody.create((byte[]) obj, MediaType.parse(contentType)); } else if (obj instanceof File) { // File body parameter support. - return RequestBody.create(MediaType.parse(contentType), (File) obj); + return RequestBody.create((File) obj, MediaType.parse(contentType)); } else if (isJsonMime(contentType)) { String content; if (obj != null) { @@ -1022,7 +1022,7 @@ public class ApiClient { } else { content = null; } - return RequestBody.create(MediaType.parse(contentType), content); + return RequestBody.create(content, MediaType.parse(contentType)); } else { throw new ApiException("Content type \"" + contentType + "\" is not supported"); } @@ -1272,7 +1272,7 @@ public class ApiClient { reqBody = null; } else { // use an empty request body (for POST, PUT and PATCH) - reqBody = RequestBody.create(MediaType.parse(contentType), ""); + reqBody = RequestBody.create("", MediaType.parse(contentType)); } } else { reqBody = serialize(body, contentType); @@ -1423,10 +1423,10 @@ public class ApiClient { File file = (File) param.getValue(); Headers partHeaders = Headers.of("Content-Disposition", "form-data; name=\"" + param.getKey() + "\"; filename=\"" + file.getName() + "\""); MediaType mediaType = MediaType.parse(guessContentTypeFromFile(file)); - mpBuilder.addPart(partHeaders, RequestBody.create(mediaType, file)); + mpBuilder.addPart(partHeaders, RequestBody.create(file, mediaType)); } else { Headers partHeaders = Headers.of("Content-Disposition", "form-data; name=\"" + param.getKey() + "\""); - mpBuilder.addPart(partHeaders, RequestBody.create(null, parameterToString(param.getValue()))); + mpBuilder.addPart(partHeaders, RequestBody.create(parameterToString(param.getValue()), null)); } } return mpBuilder.build(); diff --git a/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache b/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache index 46b2021c958..cb0e8250550 100644 --- a/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache +++ b/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache @@ -47,7 +47,7 @@ public class OAuthOkHttpClient implements HttpClient { } } - RequestBody body = request.getBody() != null ? RequestBody.create(mediaType, request.getBody()) : null; + RequestBody body = request.getBody() != null ? RequestBody.create(request.getBody(), mediaType) : null; requestBuilder.method(requestMethod, body); try { From 09525618121ab3947d7f5df81ba153a8da491136 Mon Sep 17 00:00:00 2001 From: Oleh Kurpiak Date: Mon, 15 Mar 2021 15:25:48 +0200 Subject: [PATCH 357/370] [Java][Server] fix default value (#8577) * [Java][Server] fix default value * [Java][Server] fix default value --- libraries/microprofile/queryParams.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/microprofile/queryParams.mustache b/libraries/microprofile/queryParams.mustache index ca2c6e106f7..f89529fdb5d 100644 --- a/libraries/microprofile/queryParams.mustache +++ b/libraries/microprofile/queryParams.mustache @@ -1 +1 @@ -{{#isQueryParam}}@QueryParam("{{baseName}}"){{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}} {{^isContainer}}{{#defaultValue}}@DefaultValue({{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{{defaultValue}}}{{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}) {{/defaultValue}}{{/isContainer}}{{{dataType}}} {{paramName}}{{/isQueryParam}} \ No newline at end of file +{{#isQueryParam}}@QueryParam("{{baseName}}"){{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}} {{^isContainer}}{{#defaultValue}}@DefaultValue("{{{defaultValue}}}") {{/defaultValue}}{{/isContainer}}{{{dataType}}} {{paramName}}{{/isQueryParam}} \ No newline at end of file From e7eb2ed541bb9609e671e94ec53bbf6f09bcac98 Mon Sep 17 00:00:00 2001 From: David Gerber Date: Mon, 15 Mar 2021 15:48:43 +0100 Subject: [PATCH 358/370] fix: remove double URL encoding (#8660) DefaultWebClient() already encodes URL query parameters. --- libraries/webclient/ApiClient.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/webclient/ApiClient.mustache b/libraries/webclient/ApiClient.mustache index 0eb66705d9e..0fe89ccb026 100644 --- a/libraries/webclient/ApiClient.mustache +++ b/libraries/webclient/ApiClient.mustache @@ -573,7 +573,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { builder.queryParams(queryParams); } - final WebClient.RequestBodySpec requestBuilder = webClient.method(method).uri(builder.encode().toUriString(), pathParams); + final WebClient.RequestBodySpec requestBuilder = webClient.method(method).uri(builder.build(false).toUriString(), pathParams); if(accept != null) { requestBuilder.accept(accept.toArray(new MediaType[accept.size()])); } From dea0e05e21c8ef2a81c758927d09c2da57f4ae9a Mon Sep 17 00:00:00 2001 From: William Cheng Date: Mon, 22 Mar 2021 13:58:04 +0800 Subject: [PATCH 359/370] [Java] Update WebClient dependencies (#8972) * update webclient dependencies * update build.gradle --- libraries/webclient/build.gradle.mustache | 6 +++--- libraries/webclient/pom.mustache | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/webclient/build.gradle.mustache b/libraries/webclient/build.gradle.mustache index 793ad63cbfe..c335e7ad441 100644 --- a/libraries/webclient/build.gradle.mustache +++ b/libraries/webclient/build.gradle.mustache @@ -124,14 +124,14 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.6.2" - spring_web_version = "5.2.13.RELEASE" + spring_web_version = "2.4.3" jackson_version = "2.11.3" jackson_databind_version = "2.11.3" {{#openApiNullable}} jackson_databind_nullable_version = "0.2.1" {{/openApiNullable}} javax_annotation_version = "1.3.2" - reactor_version = "3.3.10.RELEASE" + reactor_version = "3.4.3" reactor_netty_version = "0.7.15.RELEASE" jodatime_version = "2.9.9" junit_version = "4.13.1" @@ -141,7 +141,7 @@ dependencies { implementation "io.swagger:swagger-annotations:$swagger_annotations_version" implementation "com.google.code.findbugs:jsr305:3.0.2" implementation "io.projectreactor:reactor-core:$reactor_version" - implementation "org.springframework:spring-webflux:$spring_web_version" + implementation "org.springframework.boot:spring-boot-starter-webflux:$spring_web_version" implementation "io.projectreactor.ipc:reactor-netty:$reactor_netty_version" implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" diff --git a/libraries/webclient/pom.mustache b/libraries/webclient/pom.mustache index 39c55beb122..67a888863b4 100644 --- a/libraries/webclient/pom.mustache +++ b/libraries/webclient/pom.mustache @@ -85,10 +85,10 @@ ${reactor-version} - + - org.springframework - spring-webflux + org.springframework.boot + spring-boot-starter-webflux ${spring-web-version} @@ -149,7 +149,7 @@ UTF-8 1.6.2 - 5.2.13.RELEASE + 2.4.3 2.11.3 2.11.3 {{#openApiNullable}} @@ -157,7 +157,7 @@ {{/openApiNullable}} 1.3.2 4.13.1 - 3.3.10.RELEASE + 3.4.3 0.7.15.RELEASE {{#joda}} 2.9.9 From 0eecb2ab32e40dee637a565b5c88a02b543501c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Herv=C3=A9?= Date: Tue, 23 Mar 2021 10:36:51 +0100 Subject: [PATCH 360/370] Apply template-patches/java-0002-custom-license-header.patch --- .generator/templates/licenseInfo.mustache | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.generator/templates/licenseInfo.mustache b/.generator/templates/licenseInfo.mustache index abc2f4578eb..764d7f952d8 100644 --- a/.generator/templates/licenseInfo.mustache +++ b/.generator/templates/licenseInfo.mustache @@ -1,9 +1,7 @@ /* - * {{{appName}}} - * {{{appDescription}}} - * - * {{#version}}The version of the OpenAPI document: {{{version}}}{{/version}} - * {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}} + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2019-Present Datadog, Inc. * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). * https://openapi-generator.tech From d088c82ed27a09816abb15c532d9477aa056be95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Herv=C3=A9?= Date: Tue, 23 Mar 2021 10:36:51 +0100 Subject: [PATCH 361/370] Apply template-patches/java-0004-unescaped-descriptions.patch --- .generator/templates/api_doc.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.generator/templates/api_doc.mustache b/.generator/templates/api_doc.mustache index 55d0244e3a5..cd7ecc6aefb 100644 --- a/.generator/templates/api_doc.mustache +++ b/.generator/templates/api_doc.mustache @@ -18,7 +18,7 @@ Method | HTTP request | Description {{summary}}{{#notes}} -{{notes}}{{/notes}} +{{{unescapedNotes}}}{{/notes}} ### Example From ff551155d2c4f582e666564408cf81d2d3449468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Herv=C3=A9?= Date: Tue, 23 Mar 2021 10:36:51 +0100 Subject: [PATCH 362/370] Apply template-patches/java-0005-unstable-operations.patch --- .../libraries/jersey2/ApiClient.mustache | 69 +++++++++++++++++++ .../templates/libraries/jersey2/api.mustache | 8 +++ 2 files changed, 77 insertions(+) diff --git a/.generator/templates/libraries/jersey2/ApiClient.mustache b/.generator/templates/libraries/jersey2/ApiClient.mustache index d12dec1bbdb..cbba30eb82f 100644 --- a/.generator/templates/libraries/jersey2/ApiClient.mustache +++ b/.generator/templates/libraries/jersey2/ApiClient.mustache @@ -49,6 +49,7 @@ import java.util.HashSet; import java.util.List; import java.util.Arrays; import java.util.ArrayList; +import java.util.Set; import java.util.Date; {{#jsr310}} {{#threetenbp}} @@ -168,6 +169,20 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { protected Map authenticationLookup; protected DateFormat dateFormat; + protected final Map unstableOperations = new HashMap() {{ + {{#apiInfo}} + {{#apis}} + {{#operations}} + {{#operation}} + {{#vendorExtensions.x-unstable}} + put("{{operationId}}", false); + {{/vendorExtensions.x-unstable}} + {{/operation}} + {{/operations}} + {{/apis}} + {{/apiInfo}} + }}; + protected static final java.util.logging.Logger logger = java.util.logging.Logger.getLogger(ApiClient.class.getName()); /** * Constructs a new ApiClient with default parameters. @@ -688,6 +703,60 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { return this; } + /** + * Get list of all unstable operations + * @return set of all unstable operations Ids + */ + public Set getUnstableOperations() { + return unstableOperations.keySet(); + } + + /** + * Mark an unstable operation as enabled/disabled. + * @param operation operation Id - this is the name of the method on the API class, e.g. "createFoo" + * @param enabled whether to mark the operation as enabled (true) or disabled (false) + * @return true if the operation is marked as unstable and thus was enabled/disabled, false otherwise + */ + public boolean setUnstableOperationEnabled(String operation, boolean enabled) { + if (unstableOperations.containsKey(operation)) { + unstableOperations.put(operation, enabled); + return true; + } + logger.warning(String.format("'%s' is not an unstable operation, can't enable/disable", operation)); + return false; + } + + /** + * Determine whether an operation is an unstable operation. + * @param operation operation Id - this is the name of the method on the API class, e.g. "createFoo" + * @return true if the operation is an unstable operation, false otherwise + */ + public boolean isUnstableOperation(String operation) { + return unstableOperations.containsKey(operation); + } + + /** + * Determine whether an unstable operation is enabled. + * @param operation operation Id - this is the name of the method on the API class, e.g. "createFoo" + * @return true if the operation is unstable and it is enabled, false otherwise + */ + public boolean isUnstableOperationEnabled(String operation) { + if (unstableOperations.containsKey(operation)) { + return unstableOperations.get(operation); + } else { + logger.warning(String.format("'%s' is not an unstable operation, is always enabled", operation)); + return true; + } + } + + /** + * Get the ApiClient logger + * @return ApiClient logger + */ + public java.util.logging.Logger getLogger() { + return logger; + } + /** * Parse the given string into Date object. * @param str String diff --git a/.generator/templates/libraries/jersey2/api.mustache b/.generator/templates/libraries/jersey2/api.mustache index 666430c834e..20bcc127e1b 100644 --- a/.generator/templates/libraries/jersey2/api.mustache +++ b/.generator/templates/libraries/jersey2/api.mustache @@ -254,6 +254,14 @@ public class {{classname}} { @Deprecated {{/isDeprecated}} public API{{operationId}}Request {{operationId}}({{#pathParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}) throws ApiException { + {{#vendorExtensions.x-unstable}} + String operationId = "{{operationId}}"; + if (apiClient.isUnstableOperationEnabled(operationId)) { + apiClient.getLogger().warning(String.format("Using unstable operation '%s'", operationId)); + } else { + throw new ApiException(0, String.format("Unstable operation '%s' is disabled", operationId)); + } + {{/vendorExtensions.x-unstable}} return new API{{operationId}}Request({{#pathParams}}{{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}); } {{/vendorExtensions.x-group-parameters}} From a9c5e9693cee0393d71ca16a26c759c505955d52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Herv=C3=A9?= Date: Tue, 23 Mar 2021 10:36:51 +0100 Subject: [PATCH 363/370] Apply template-patches/java-0007-operation-id-header.patch --- .generator/templates/libraries/jersey2/api.mustache | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.generator/templates/libraries/jersey2/api.mustache b/.generator/templates/libraries/jersey2/api.mustache index 20bcc127e1b..809694a6dfc 100644 --- a/.generator/templates/libraries/jersey2/api.mustache +++ b/.generator/templates/libraries/jersey2/api.mustache @@ -137,6 +137,9 @@ public class {{classname}} { localVarQueryParams.addAll(apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); {{/queryParams}} + // Set Operation-ID header for telemetry + localVarHeaderParams.put("DD-OPERATION-ID", "{{operationId}}"); + {{#headerParams}}if ({{paramName}} != null) localVarHeaderParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); {{/headerParams}} From 6e640df3876b778feddcfd152ae2dd5619d3a47b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Herv=C3=A9?= Date: Tue, 23 Mar 2021 10:36:51 +0100 Subject: [PATCH 364/370] Apply template-patches/java-0008-user-agent.patch --- .../libraries/jersey2/ApiClient.mustache | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/.generator/templates/libraries/jersey2/ApiClient.mustache b/.generator/templates/libraries/jersey2/ApiClient.mustache index cbba30eb82f..554335e3c63 100644 --- a/.generator/templates/libraries/jersey2/ApiClient.mustache +++ b/.generator/templates/libraries/jersey2/ApiClient.mustache @@ -51,6 +51,7 @@ import java.util.Arrays; import java.util.ArrayList; import java.util.Set; import java.util.Date; +import java.util.Properties; {{#jsr310}} {{#threetenbp}} import org.threeten.bp.OffsetDateTime; @@ -203,7 +204,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { this.dateFormat = new RFC3339DateFormat(); // Set default User-Agent. - setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + setUserAgent(); // Setup authentications (key: authentication name, value: authentication). authentications = new HashMap(); @@ -554,6 +555,31 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { return userAgent; } + /** + * Set the default User-Agent header's value with telemetry information (by adding to the default header map). + * @return API client + */ + public ApiClient setUserAgent() { + final Properties properties = new Properties(); + try { + properties.load(getClass().getClassLoader().getResourceAsStream("com/datadog/api/project.properties")); + } catch (IOException e) { + logger.severe("Could not load client version: " + e.toString()); + } + + String userAgent = "datadog-api-client-java/" + properties.getProperty("version") + + " (" + + "java " + System.getProperty("java.version") + "; " + + "java_vendor " + System.getProperty("java.vendor") + "; " + + "os " + System.getProperty("os.name") + "; " + + "os_version " + System.getProperty("os.version") + "; " + + "arch " + System.getProperty("os.arch") + + ")"; + addDefaultHeader("User-Agent", userAgent); + this.userAgent = userAgent; + return this; + } + /** * Add a default header. * From 0654b8121f9d001342749d93ebb740cdb1800523 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Herv=C3=A9?= Date: Tue, 23 Mar 2021 10:36:51 +0100 Subject: [PATCH 365/370] Apply template-patches/java-0009-document-auth.patch --- .../libraries/jersey2/api_doc.mustache | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/.generator/templates/libraries/jersey2/api_doc.mustache b/.generator/templates/libraries/jersey2/api_doc.mustache index e9270ceb18f..c83f8b7446c 100644 --- a/.generator/templates/libraries/jersey2/api_doc.mustache +++ b/.generator/templates/libraries/jersey2/api_doc.mustache @@ -32,6 +32,7 @@ Method | HTTP request | Description import {{.}}; {{/vendorExtensions.x-java-import}} // Import classes: +import java.util.*; import {{{invokerPackage}}}.ApiClient; import {{{invokerPackage}}}.ApiException; import {{{invokerPackage}}}.Configuration;{{#hasAuthMethods}} @@ -42,26 +43,23 @@ import {{{package}}}.{{{classname}}}; public class Example { public static void main(String[] args) { ApiClient defaultClient = Configuration.getDefaultApiClient(); - defaultClient.setBasePath("{{{basePath}}}"); - {{#hasAuthMethods}} - {{#authMethods}}{{#isBasic}}{{#isBasicBasic}} - // Configure HTTP basic authorization: {{{name}}} - HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); - {{{name}}}.setUsername("YOUR USERNAME"); - {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasicBasic}}{{#isBasicBearer}} - // Configure HTTP bearer authorization: {{{name}}} - HttpBearerAuth {{{name}}} = (HttpBearerAuth) defaultClient.getAuthentication("{{{name}}}"); - {{{name}}}.setBearerToken("BEARER TOKEN");{{/isBasicBearer}}{{/isBasic}}{{#isApiKey}} + // Configure the Datadog site to send API calls to + HashMap serverVariables = new HashMap(); + String site = System.getenv("DD_SITE"); + if (site != null) { + serverVariables.put("site", site); + defaultClient.setServerVariables(serverVariables); + } // Configure API key authorization: {{{name}}} - ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); - {{{name}}}.setApiKey("YOUR API KEY"); - // Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null) - //{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} - // Configure OAuth2 access token for authorization: {{{name}}} - OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); - {{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}} + HashMap secrets = new HashMap(); + {{#hasAuthMethods}} + {{#authMethods}} + {{#isApiKey}} + secrets.put("{{{name}}}", System.getenv("{{{vendorExtensions.x-env-name}}}")); + {{/isApiKey}} {{/authMethods}} {{/hasAuthMethods}} + defaultClient.configureApiKeys(secrets); {{{classname}}} apiInstance = new {{{classname}}}(defaultClient); {{#allParams}} @@ -72,7 +70,7 @@ public class Example { {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}); {{/vendorExtensions.x-group-parameters}} {{#vendorExtensions.x-group-parameters}} - {{#returnType}}{{{returnType}}} result = {{/returnType}}api.{{operationId}}({{#pathParams}}{{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}){{#allParams}}{{^isPathParam}} + {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{operationId}}({{#pathParams}}{{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}){{#allParams}}{{^isPathParam}} .{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}} .execute(); {{/vendorExtensions.x-group-parameters}} From f6feeaad7434178dd07eb7864d20684e68d67fba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Herv=C3=A9?= Date: Tue, 23 Mar 2021 10:36:51 +0100 Subject: [PATCH 366/370] Apply template-patches/java-0011-allow-unknown-properties.patch --- .generator/templates/libraries/jersey2/JSON.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.generator/templates/libraries/jersey2/JSON.mustache b/.generator/templates/libraries/jersey2/JSON.mustache index 3297c77e49b..aed16b34010 100644 --- a/.generator/templates/libraries/jersey2/JSON.mustache +++ b/.generator/templates/libraries/jersey2/JSON.mustache @@ -37,7 +37,7 @@ public class JSON implements ContextResolver { mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); mapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true); mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); From afe221ef99549f709d321719d6cd57b28b37c83a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Herv=C3=A9?= Date: Tue, 23 Mar 2021 10:36:51 +0100 Subject: [PATCH 367/370] Apply template-patches/java-0014-fix-multipart-requests.patch --- .generator/templates/libraries/jersey2/ApiClient.mustache | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.generator/templates/libraries/jersey2/ApiClient.mustache b/.generator/templates/libraries/jersey2/ApiClient.mustache index 554335e3c63..0a4a61aedd5 100644 --- a/.generator/templates/libraries/jersey2/ApiClient.mustache +++ b/.generator/templates/libraries/jersey2/ApiClient.mustache @@ -1226,7 +1226,8 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { queryParams, allHeaderParams, cookieParams, - serializeToString(body, formParams, contentType, isBodyNullable), + // NOTE: this is not used in ApiKeyAuthentication anyway, so we comment it out to enable multipart requests + "", // serializeToString(body, formParams, contentType, isBodyNullable), method, target.getUri()); From aaf0a716c9e8938b562d264d62c02ba89a504fd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Herv=C3=A9?= Date: Tue, 23 Mar 2021 10:36:51 +0100 Subject: [PATCH 368/370] Apply template-patches/java-0015-readme-links.patch --- .generator/templates/README.mustache | 177 +----------------- .../libraries/jersey2/api_doc.mustache | 2 +- 2 files changed, 3 insertions(+), 176 deletions(-) diff --git a/.generator/templates/README.mustache b/.generator/templates/README.mustache index fd9abd28241..a5b66abc2e2 100644 --- a/.generator/templates/README.mustache +++ b/.generator/templates/README.mustache @@ -1,188 +1,15 @@ -# {{artifactId}} - -{{appName}} - -- API version: {{appVersion}} -{{^hideGenerationTimestamp}} - -- Build date: {{generatedDate}} -{{/hideGenerationTimestamp}} - -{{#appDescriptionWithNewLines}}{{{appDescriptionWithNewLines}}}{{/appDescriptionWithNewLines}} - -{{#infoUrl}} - For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) -{{/infoUrl}} - -*Automatically generated by the [OpenAPI Generator](https://openapi-generator.tech)* - -## Requirements - -Building the API client library requires: - -1. Java {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}+ -2. Maven/Gradle - -## Installation - -To install the API client library to your local Maven repository, simply execute: - -```shell -mvn clean install -``` - -To deploy it to a remote Maven repository instead, configure the settings of the repository and execute: - -```shell -mvn clean deploy -``` - -Refer to the [OSSRH Guide](http://central.sonatype.org/pages/ossrh-guide.html) for more information. - -### Maven users - -Add this dependency to your project's POM: - -```xml - - {{{groupId}}} - {{{artifactId}}} - {{{artifactVersion}}} - compile - -``` - -### Gradle users - -Add this dependency to your project's build file: - -```groovy -compile "{{{groupId}}}:{{{artifactId}}}:{{{artifactVersion}}}" -``` - -### Others - -At first generate the JAR by executing: - -```shell -mvn clean package -``` - -Then manually install the following JARs: - -- `target/{{{artifactId}}}-{{{artifactVersion}}}.jar` -- `target/lib/*.jar` - -{{#jersey2}} -## Usage - -To add a HTTP proxy for the API client, use `ClientConfig`: -```java -{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}} -import org.glassfish.jersey.apache.connector.ApacheConnectorProvider; -import org.glassfish.jersey.client.ClientConfig; -import org.glassfish.jersey.client.ClientProperties; -import {{{invokerPackage}}}.*; -import {{{package}}}.{{{classname}}}; - -... - -ApiClient defaultClient = Configuration.getDefaultApiClient(); -ClientConfig clientConfig = defaultClient.getClientConfig(); -clientConfig.connectorProvider(new ApacheConnectorProvider()); -clientConfig.property(ClientProperties.PROXY_URI, "http://proxy_url_here"); -clientConfig.property(ClientProperties.PROXY_USERNAME, "proxy_username"); -clientConfig.property(ClientProperties.PROXY_PASSWORD, "proxy_password"); -defaultClient.setClientConfig(clientConfig); - -{{{classname}}} apiInstance = new {{{classname}}}(defaultClient); -{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} -``` - -{{/jersey2}} -## Getting Started - -Please follow the [installation](#installation) instruction and execute the following Java code: - -```java -{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}} -import {{{invokerPackage}}}.*; -import {{{invokerPackage}}}.auth.*; -import {{{modelPackage}}}.*; -import {{{package}}}.{{{classname}}}; - -public class {{{classname}}}Example { - - public static void main(String[] args) { - ApiClient defaultClient = Configuration.getDefaultApiClient(); - defaultClient.setBasePath("{{{basePath}}}"); - {{#hasAuthMethods}}{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} - // Configure HTTP basic authorization: {{{name}}} - HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); - {{{name}}}.setUsername("YOUR USERNAME"); - {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasicBasic}}{{#isBasicBearer}} - // Configure HTTP bearer authorization: {{{name}}} - HttpBearerAuth {{{name}}} = (HttpBearerAuth) defaultClient.getAuthentication("{{{name}}}"); - {{{name}}}.setBearerToken("BEARER TOKEN");{{/isBasicBearer}}{{/isBasic}}{{#isApiKey}} - // Configure API key authorization: {{{name}}} - ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); - {{{name}}}.setApiKey("YOUR API KEY"); - // Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null) - //{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} - // Configure OAuth2 access token for authorization: {{{name}}} - OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); - {{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}}{{#isHttpSignature}} - // Configure HTTP signature authorization: {{{name}}} - HttpSignatureAuth {{{name}}} = (HttpSignatureAuth) defaultClient.getAuthentication("{{{name}}}"); - // All the HTTP signature parameters below should be customized to your environment. - // Configure the keyId - {{{name}}}.setKeyId("YOUR KEY ID"); - // Configure the signature algorithm - {{{name}}}.setSigningAlgorithm(SigningAlgorithm.HS2019); - // Configure the specific cryptographic algorithm - {{{name}}}.setAlgorithm(Algorithm.ECDSA_SHA256); - // Configure the cryptographic algorithm parameters, if applicable - {{{name}}}.setAlgorithmParameterSpec(null); - // Set the cryptographic digest algorithm. - {{{name}}}.setDigestAlgorithm("SHA-256"); - // Set the HTTP headers that should be included in the HTTP signature. - {{{name}}}.setHeaders(Arrays.asList("date", "host")); - // Set the private key used to sign the HTTP messages - {{{name}}}.setPrivateKey();{{/isHttpSignature}} - {{/authMethods}} - {{/hasAuthMethods}} - - {{{classname}}} apiInstance = new {{{classname}}}(defaultClient); - {{#allParams}} - {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} - {{/allParams}} - try { - {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}});{{#returnType}} - System.out.println(result);{{/returnType}} - } catch (ApiException e) { - System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); - System.err.println("Status code: " + e.getCode()); - System.err.println("Reason: " + e.getResponseBody()); - System.err.println("Response headers: " + e.getResponseHeaders()); - e.printStackTrace(); - } - } -} -{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} -``` - ## Documentation for API Endpoints All URIs are relative to *{{basePath}}* Class | Method | HTTP request | Description ------------ | ------------- | ------------- | ------------- -{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{commonPath}}{{path}} | {{#summary}}{{summary}}{{/summary}} +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{commonPath}}{{path}} | {{#summary}}{{summary}}{{/summary}} {{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} ## Documentation for Models -{{#models}}{{#model}} - [{{classname}}]({{modelDocPath}}{{classname}}.md) +{{#models}}{{#model}} - [{{classname}}]({{classname}}.md) {{/model}}{{/models}} ## Documentation for Authorization diff --git a/.generator/templates/libraries/jersey2/api_doc.mustache b/.generator/templates/libraries/jersey2/api_doc.mustache index c83f8b7446c..eaf50994059 100644 --- a/.generator/templates/libraries/jersey2/api_doc.mustache +++ b/.generator/templates/libraries/jersey2/api_doc.mustache @@ -102,7 +102,7 @@ Name | Type | Description | Notes ### Authorization -{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{name}}](../README.md#{{name}}){{^-last}}, {{/-last}}{{/authMethods}} +{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{name}}](README.md#{{name}}){{^-last}}, {{/-last}}{{/authMethods}} ### HTTP request headers From 527d1481e8bef79738851ba778ed6ee3fe64ba6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Herv=C3=A9?= Date: Tue, 23 Mar 2021 10:36:51 +0100 Subject: [PATCH 369/370] Apply template-patches/java-0016-remove-download-files.patch --- .../libraries/jersey2/ApiClient.mustache | 66 ------------------- 1 file changed, 66 deletions(-) diff --git a/.generator/templates/libraries/jersey2/ApiClient.mustache b/.generator/templates/libraries/jersey2/ApiClient.mustache index 0a4a61aedd5..5c3f0de8fa3 100644 --- a/.generator/templates/libraries/jersey2/ApiClient.mustache +++ b/.generator/templates/libraries/jersey2/ApiClient.mustache @@ -646,17 +646,6 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { return this; } - /** - * The path of temporary folder used to store downloaded files from endpoints - * with file response. The default value is null, i.e. using - * the system's default tempopary folder. - * - * @return Temp folder path - */ - public String getTempFolderPath() { - return tempFolderPath; - } - /** * Set temp folder path * @param tempFolderPath Temp folder path @@ -1066,10 +1055,6 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { if ("byte[]".equals(returnType.toString())) { // Handle binary response (byte array). return (T) response.readEntity(byte[].class); - } else if (returnType.getRawType() == File.class) { - // Handle file downloading. - T file = (T) downloadFileFromResponse(response); - return file; } String contentType = null; @@ -1083,57 +1068,6 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { return response.readEntity(returnType); } - /** - * Download file from the given response. - * @param response Response - * @return File - * @throws ApiException If fail to read file content from response and write to disk - */ - public File downloadFileFromResponse(Response response) throws ApiException { - try { - File file = prepareDownloadFile(response); - Files.copy(response.readEntity(InputStream.class), file.toPath(), StandardCopyOption.REPLACE_EXISTING); - return file; - } catch (IOException e) { - throw new ApiException(e); - } - } - - public File prepareDownloadFile(Response response) throws IOException { - String filename = null; - String contentDisposition = (String) response.getHeaders().getFirst("Content-Disposition"); - if (contentDisposition != null && !"".equals(contentDisposition)) { - // Get filename from the Content-Disposition header. - Pattern pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?"); - Matcher matcher = pattern.matcher(contentDisposition); - if (matcher.find()) - filename = matcher.group(1); - } - - String prefix; - String suffix = null; - if (filename == null) { - prefix = "download-"; - suffix = ""; - } else { - int pos = filename.lastIndexOf('.'); - if (pos == -1) { - prefix = filename + "-"; - } else { - prefix = filename.substring(0, pos) + "-"; - suffix = filename.substring(pos); - } - // Files.createTempFile requires the prefix to be at least three characters long - if (prefix.length() < 3) - prefix = "download-"; - } - - if (tempFolderPath == null) - return Files.createTempFile(prefix, suffix).toFile(); - else - return Files.createTempFile(Paths.get(tempFolderPath), prefix, suffix).toFile(); - } - /** * Invoke API by sending HTTP request with the given options. * From 7bb35b5eb67e0595d5147a51037c03cbbd7a77e7 Mon Sep 17 00:00:00 2001 From: "ci.datadog-api-spec" Date: Tue, 23 Mar 2021 14:03:06 +0000 Subject: [PATCH 370/370] Regenerate client from commit 7e667f1 of spec repo --- .apigentools-info | 8 ++++---- api_docs/v1/APIErrorResponse.md | 1 + api_docs/v1/AWSAccount.md | 1 + api_docs/v1/AWSAccountAndLambdaRequest.md | 1 + api_docs/v1/AWSAccountCreateResponse.md | 1 + api_docs/v1/AWSAccountListResponse.md | 1 + api_docs/v1/AWSLogsAsyncError.md | 1 + api_docs/v1/AWSLogsAsyncResponse.md | 1 + api_docs/v1/AWSLogsLambda.md | 1 + api_docs/v1/AWSLogsListResponse.md | 1 + api_docs/v1/AWSLogsListServicesResponse.md | 1 + api_docs/v1/AWSLogsServicesRequest.md | 1 + api_docs/v1/AWSTagFilter.md | 1 + api_docs/v1/AWSTagFilterCreateRequest.md | 1 + api_docs/v1/AWSTagFilterDeleteRequest.md | 1 + api_docs/v1/AWSTagFilterListResponse.md | 1 + api_docs/v1/AlertGraphWidgetDefinition.md | 1 + api_docs/v1/AlertValueWidgetDefinition.md | 1 + api_docs/v1/ApiKey.md | 1 + api_docs/v1/ApiKeyListResponse.md | 1 + api_docs/v1/ApiKeyResponse.md | 1 + api_docs/v1/ApmStatsQueryColumnType.md | 1 + api_docs/v1/ApmStatsQueryDefinition.md | 1 + api_docs/v1/ApplicationKey.md | 1 + api_docs/v1/ApplicationKeyListResponse.md | 1 + api_docs/v1/ApplicationKeyResponse.md | 1 + api_docs/v1/AuthenticationValidationResponse.md | 1 + api_docs/v1/AzureAccount.md | 1 + api_docs/v1/CancelDowntimesByScopeRequest.md | 1 + api_docs/v1/CanceledDowntimesIds.md | 1 + api_docs/v1/ChangeWidgetDefinition.md | 1 + api_docs/v1/ChangeWidgetRequest.md | 1 + api_docs/v1/CheckCanDeleteMonitorResponse.md | 1 + api_docs/v1/CheckCanDeleteMonitorResponseData.md | 1 + api_docs/v1/CheckCanDeleteSLOResponse.md | 1 + api_docs/v1/CheckCanDeleteSLOResponseData.md | 1 + api_docs/v1/CheckStatusWidgetDefinition.md | 1 + api_docs/v1/Creator.md | 1 + api_docs/v1/Dashboard.md | 1 + api_docs/v1/DashboardDeleteResponse.md | 1 + api_docs/v1/DashboardList.md | 1 + api_docs/v1/DashboardListDeleteResponse.md | 1 + api_docs/v1/DashboardListListResponse.md | 1 + api_docs/v1/DashboardSummary.md | 1 + api_docs/v1/DashboardSummaryDefinition.md | 1 + api_docs/v1/DashboardTemplateVariable.md | 1 + api_docs/v1/DashboardTemplateVariablePreset.md | 1 + api_docs/v1/DashboardTemplateVariablePresetValue.md | 1 + api_docs/v1/DeletedMonitor.md | 1 + api_docs/v1/DistributionWidgetDefinition.md | 1 + api_docs/v1/DistributionWidgetRequest.md | 1 + api_docs/v1/Downtime.md | 1 + api_docs/v1/DowntimeRecurrence.md | 1 + api_docs/v1/Event.md | 1 + api_docs/v1/EventListResponse.md | 1 + api_docs/v1/EventQueryDefinition.md | 1 + api_docs/v1/EventResponse.md | 1 + api_docs/v1/EventStreamWidgetDefinition.md | 1 + api_docs/v1/EventTimelineWidgetDefinition.md | 1 + api_docs/v1/FormulaAndFunctionEventQueryDefinition.md | 1 + .../v1/FormulaAndFunctionEventQueryDefinitionCompute.md | 1 + .../v1/FormulaAndFunctionEventQueryDefinitionSearch.md | 1 + api_docs/v1/FormulaAndFunctionEventQueryGroupBy.md | 1 + api_docs/v1/FormulaAndFunctionEventQueryGroupBySort.md | 1 + api_docs/v1/FormulaAndFunctionMetricQueryDefinition.md | 1 + api_docs/v1/FormulaAndFunctionProcessQueryDefinition.md | 1 + api_docs/v1/FreeTextWidgetDefinition.md | 1 + api_docs/v1/GCPAccount.md | 1 + api_docs/v1/GeomapWidgetDefinition.md | 1 + api_docs/v1/GeomapWidgetDefinitionStyle.md | 1 + api_docs/v1/GeomapWidgetDefinitionView.md | 1 + api_docs/v1/GeomapWidgetRequest.md | 1 + api_docs/v1/GraphSnapshot.md | 1 + api_docs/v1/GroupWidgetDefinition.md | 1 + api_docs/v1/HeatMapWidgetDefinition.md | 1 + api_docs/v1/HeatMapWidgetRequest.md | 1 + api_docs/v1/Host.md | 1 + api_docs/v1/HostListResponse.md | 1 + api_docs/v1/HostMapRequest.md | 1 + api_docs/v1/HostMapWidgetDefinition.md | 1 + api_docs/v1/HostMapWidgetDefinitionRequests.md | 1 + api_docs/v1/HostMapWidgetDefinitionStyle.md | 1 + api_docs/v1/HostMeta.md | 1 + api_docs/v1/HostMetrics.md | 1 + api_docs/v1/HostMuteResponse.md | 1 + api_docs/v1/HostMuteSettings.md | 1 + api_docs/v1/HostTags.md | 1 + api_docs/v1/HostTotals.md | 1 + api_docs/v1/IFrameWidgetDefinition.md | 1 + api_docs/v1/IPPrefixesAPI.md | 1 + api_docs/v1/IPPrefixesAPM.md | 1 + api_docs/v1/IPPrefixesAgents.md | 1 + api_docs/v1/IPPrefixesLogs.md | 1 + api_docs/v1/IPPrefixesProcess.md | 1 + api_docs/v1/IPPrefixesSynthetics.md | 1 + api_docs/v1/IPPrefixesWebhooks.md | 1 + api_docs/v1/IPRanges.md | 1 + api_docs/v1/IdpFormData.md | 1 + api_docs/v1/IdpResponse.md | 1 + api_docs/v1/ImageWidgetDefinition.md | 1 + api_docs/v1/Log.md | 1 + api_docs/v1/LogContent.md | 1 + api_docs/v1/LogQueryDefinition.md | 1 + api_docs/v1/LogQueryDefinitionGroupBy.md | 1 + api_docs/v1/LogQueryDefinitionGroupBySort.md | 1 + api_docs/v1/LogQueryDefinitionSearch.md | 1 + api_docs/v1/LogStreamWidgetDefinition.md | 1 + api_docs/v1/LogsAPIError.md | 1 + api_docs/v1/LogsAPIErrorResponse.md | 1 + api_docs/v1/LogsArithmeticProcessor.md | 1 + api_docs/v1/LogsAttributeRemapper.md | 1 + api_docs/v1/LogsCategoryProcessor.md | 1 + api_docs/v1/LogsCategoryProcessorCategory.md | 1 + api_docs/v1/LogsDateRemapper.md | 1 + api_docs/v1/LogsExclusion.md | 1 + api_docs/v1/LogsExclusionFilter.md | 1 + api_docs/v1/LogsFilter.md | 1 + api_docs/v1/LogsGeoIPParser.md | 1 + api_docs/v1/LogsGrokParser.md | 1 + api_docs/v1/LogsGrokParserRules.md | 1 + api_docs/v1/LogsIndex.md | 1 + api_docs/v1/LogsIndexListResponse.md | 1 + api_docs/v1/LogsIndexUpdateRequest.md | 1 + api_docs/v1/LogsIndexesOrder.md | 1 + api_docs/v1/LogsListRequest.md | 1 + api_docs/v1/LogsListRequestTime.md | 1 + api_docs/v1/LogsListResponse.md | 1 + api_docs/v1/LogsLookupProcessor.md | 1 + api_docs/v1/LogsMessageRemapper.md | 1 + api_docs/v1/LogsPipeline.md | 1 + api_docs/v1/LogsPipelineProcessor.md | 1 + api_docs/v1/LogsPipelinesOrder.md | 1 + api_docs/v1/LogsQueryCompute.md | 1 + api_docs/v1/LogsServiceRemapper.md | 1 + api_docs/v1/LogsStatusRemapper.md | 1 + api_docs/v1/LogsStringBuilderProcessor.md | 1 + api_docs/v1/LogsTraceRemapper.md | 1 + api_docs/v1/LogsURLParser.md | 1 + api_docs/v1/LogsUserAgentParser.md | 1 + api_docs/v1/MetricMetadata.md | 1 + api_docs/v1/MetricSearchResponse.md | 1 + api_docs/v1/MetricSearchResponseResults.md | 1 + api_docs/v1/MetricsListResponse.md | 1 + api_docs/v1/MetricsQueryMetadata.md | 1 + api_docs/v1/MetricsQueryResponse.md | 1 + api_docs/v1/MetricsQueryUnit.md | 1 + api_docs/v1/Monitor.md | 1 + api_docs/v1/MonitorOptions.md | 1 + api_docs/v1/MonitorOptionsAggregation.md | 1 + api_docs/v1/MonitorState.md | 1 + api_docs/v1/MonitorStateGroup.md | 1 + api_docs/v1/MonitorSummaryWidgetDefinition.md | 1 + api_docs/v1/MonitorThresholdWindowOptions.md | 1 + api_docs/v1/MonitorThresholds.md | 1 + api_docs/v1/MonitorUpdateRequest.md | 1 + api_docs/v1/NoteWidgetDefinition.md | 1 + api_docs/v1/Organization.md | 1 + api_docs/v1/OrganizationBilling.md | 1 + api_docs/v1/OrganizationCreateBody.md | 1 + api_docs/v1/OrganizationCreateResponse.md | 1 + api_docs/v1/OrganizationListResponse.md | 1 + api_docs/v1/OrganizationResponse.md | 1 + api_docs/v1/OrganizationSettings.md | 1 + api_docs/v1/OrganizationSettingsSaml.md | 1 + .../v1/OrganizationSettingsSamlAutocreateUsersDomains.md | 1 + api_docs/v1/OrganizationSettingsSamlIdpInitiatedLogin.md | 1 + api_docs/v1/OrganizationSettingsSamlStrictMode.md | 1 + api_docs/v1/OrganizationSubscription.md | 1 + api_docs/v1/PagerDutyService.md | 1 + api_docs/v1/PagerDutyServiceKey.md | 1 + api_docs/v1/PagerDutyServiceName.md | 1 + api_docs/v1/ProcessQueryDefinition.md | 1 + api_docs/v1/QueryValueWidgetDefinition.md | 1 + api_docs/v1/QueryValueWidgetRequest.md | 1 + api_docs/v1/SLOBulkDeleteError.md | 1 + api_docs/v1/SLOBulkDeleteResponse.md | 1 + api_docs/v1/SLOBulkDeleteResponseData.md | 1 + api_docs/v1/SLOCorrection.md | 1 + api_docs/v1/SLOCorrectionCreateData.md | 1 + api_docs/v1/SLOCorrectionCreateRequest.md | 1 + api_docs/v1/SLOCorrectionCreateRequestAttributes.md | 1 + api_docs/v1/SLOCorrectionListResponse.md | 1 + api_docs/v1/SLOCorrectionResponse.md | 1 + api_docs/v1/SLOCorrectionResponseAttributes.md | 1 + api_docs/v1/SLOCorrectionUpdateData.md | 1 + api_docs/v1/SLOCorrectionUpdateRequest.md | 1 + api_docs/v1/SLOCorrectionUpdateRequestAttributes.md | 1 + api_docs/v1/SLODeleteResponse.md | 1 + api_docs/v1/SLOHistoryMetrics.md | 1 + api_docs/v1/SLOHistoryMetricsSeries.md | 1 + api_docs/v1/SLOHistoryMetricsSeriesMetadata.md | 1 + api_docs/v1/SLOHistoryMetricsSeriesMetadataUnit.md | 1 + api_docs/v1/SLOHistoryResponse.md | 1 + api_docs/v1/SLOHistoryResponseData.md | 1 + api_docs/v1/SLOHistoryResponseError.md | 1 + api_docs/v1/SLOHistorySLIData.md | 1 + api_docs/v1/SLOListResponse.md | 1 + api_docs/v1/SLOResponse.md | 1 + api_docs/v1/SLOThreshold.md | 1 + api_docs/v1/SLOWidgetDefinition.md | 1 + api_docs/v1/ScatterPlotRequest.md | 1 + api_docs/v1/ScatterPlotWidgetDefinition.md | 1 + api_docs/v1/ScatterPlotWidgetDefinitionRequests.md | 1 + api_docs/v1/ServiceLevelObjective.md | 1 + api_docs/v1/ServiceLevelObjectiveQuery.md | 1 + api_docs/v1/ServiceLevelObjectiveRequest.md | 1 + api_docs/v1/ServiceMapWidgetDefinition.md | 1 + api_docs/v1/ServiceSummaryWidgetDefinition.md | 1 + api_docs/v1/SlackIntegrationChannel.md | 1 + api_docs/v1/SlackIntegrationChannelDisplay.md | 1 + api_docs/v1/SyntheticsAPIStep.md | 1 + api_docs/v1/SyntheticsAPITest.md | 1 + api_docs/v1/SyntheticsAPITestConfig.md | 1 + api_docs/v1/SyntheticsAPITestResultData.md | 1 + api_docs/v1/SyntheticsAPITestResultFull.md | 1 + api_docs/v1/SyntheticsAPITestResultFullCheck.md | 1 + api_docs/v1/SyntheticsAPITestResultShort.md | 1 + api_docs/v1/SyntheticsAPITestResultShortResult.md | 1 + api_docs/v1/SyntheticsAssertionJSONPathTarget.md | 1 + api_docs/v1/SyntheticsAssertionJSONPathTargetTarget.md | 1 + api_docs/v1/SyntheticsAssertionTarget.md | 1 + api_docs/v1/SyntheticsBasicAuth.md | 1 + api_docs/v1/SyntheticsBrowserError.md | 1 + api_docs/v1/SyntheticsBrowserTest.md | 1 + api_docs/v1/SyntheticsBrowserTestConfig.md | 1 + api_docs/v1/SyntheticsBrowserTestResultData.md | 1 + api_docs/v1/SyntheticsBrowserTestResultFull.md | 1 + api_docs/v1/SyntheticsBrowserTestResultFullCheck.md | 1 + api_docs/v1/SyntheticsBrowserTestResultShort.md | 1 + api_docs/v1/SyntheticsBrowserTestResultShortResult.md | 1 + api_docs/v1/SyntheticsBrowserVariable.md | 1 + api_docs/v1/SyntheticsCITest.md | 1 + api_docs/v1/SyntheticsCITestBody.md | 1 + api_docs/v1/SyntheticsCITestMetadata.md | 1 + api_docs/v1/SyntheticsCITestMetadataCi.md | 1 + api_docs/v1/SyntheticsCITestMetadataGit.md | 1 + api_docs/v1/SyntheticsConfigVariable.md | 1 + api_docs/v1/SyntheticsCoreWebVitals.md | 1 + api_docs/v1/SyntheticsDeleteTestsPayload.md | 1 + api_docs/v1/SyntheticsDeleteTestsResponse.md | 1 + api_docs/v1/SyntheticsDeletedTest.md | 1 + api_docs/v1/SyntheticsDevice.md | 1 + api_docs/v1/SyntheticsGetAPITestLatestResultsResponse.md | 1 + .../v1/SyntheticsGetBrowserTestLatestResultsResponse.md | 1 + api_docs/v1/SyntheticsGlobalVariable.md | 1 + api_docs/v1/SyntheticsGlobalVariableParseTestOptions.md | 1 + api_docs/v1/SyntheticsGlobalVariableValue.md | 1 + api_docs/v1/SyntheticsListTestsResponse.md | 1 + api_docs/v1/SyntheticsLocation.md | 1 + api_docs/v1/SyntheticsLocations.md | 1 + api_docs/v1/SyntheticsParsingOptions.md | 1 + api_docs/v1/SyntheticsPrivateLocation.md | 1 + api_docs/v1/SyntheticsPrivateLocationCreationResponse.md | 1 + ...ticsPrivateLocationCreationResponseResultEncryption.md | 1 + api_docs/v1/SyntheticsPrivateLocationSecrets.md | 1 + .../v1/SyntheticsPrivateLocationSecretsAuthentication.md | 1 + .../SyntheticsPrivateLocationSecretsConfigDecryption.md | 1 + api_docs/v1/SyntheticsSSLCertificate.md | 1 + api_docs/v1/SyntheticsSSLCertificateIssuer.md | 1 + api_docs/v1/SyntheticsSSLCertificateSubject.md | 1 + api_docs/v1/SyntheticsStep.md | 1 + api_docs/v1/SyntheticsStepDetail.md | 1 + api_docs/v1/SyntheticsStepDetailWarning.md | 1 + api_docs/v1/SyntheticsTestConfig.md | 1 + api_docs/v1/SyntheticsTestDetails.md | 1 + api_docs/v1/SyntheticsTestOptions.md | 1 + api_docs/v1/SyntheticsTestOptionsMonitorOptions.md | 1 + api_docs/v1/SyntheticsTestOptionsRetry.md | 1 + api_docs/v1/SyntheticsTestRequest.md | 1 + api_docs/v1/SyntheticsTestRequestCertificate.md | 1 + api_docs/v1/SyntheticsTestRequestCertificateItem.md | 1 + api_docs/v1/SyntheticsTiming.md | 1 + api_docs/v1/SyntheticsTriggerCITestLocation.md | 1 + api_docs/v1/SyntheticsTriggerCITestRunResult.md | 1 + api_docs/v1/SyntheticsTriggerCITestsResponse.md | 1 + api_docs/v1/SyntheticsUpdateTestPauseStatusPayload.md | 1 + api_docs/v1/SyntheticsVariableParser.md | 1 + api_docs/v1/TableWidgetDefinition.md | 1 + api_docs/v1/TableWidgetRequest.md | 1 + api_docs/v1/TagToHosts.md | 1 + api_docs/v1/TimeseriesWidgetDefinition.md | 1 + api_docs/v1/TimeseriesWidgetExpressionAlias.md | 1 + api_docs/v1/TimeseriesWidgetRequest.md | 1 + api_docs/v1/ToplistWidgetDefinition.md | 1 + api_docs/v1/ToplistWidgetRequest.md | 1 + api_docs/v1/UsageAnalyzedLogsHour.md | 1 + api_docs/v1/UsageAnalyzedLogsResponse.md | 1 + api_docs/v1/UsageAttributionAggregatesBody.md | 1 + api_docs/v1/UsageAttributionBody.md | 1 + api_docs/v1/UsageAttributionMetadata.md | 1 + api_docs/v1/UsageAttributionPagination.md | 1 + api_docs/v1/UsageAttributionResponse.md | 1 + api_docs/v1/UsageAttributionValues.md | 1 + api_docs/v1/UsageBillableSummaryBody.md | 1 + api_docs/v1/UsageBillableSummaryHour.md | 1 + api_docs/v1/UsageBillableSummaryKeys.md | 1 + api_docs/v1/UsageBillableSummaryResponse.md | 1 + api_docs/v1/UsageCustomReportsAttributes.md | 1 + api_docs/v1/UsageCustomReportsData.md | 1 + api_docs/v1/UsageCustomReportsMeta.md | 1 + api_docs/v1/UsageCustomReportsPage.md | 1 + api_docs/v1/UsageCustomReportsResponse.md | 1 + api_docs/v1/UsageFargateHour.md | 1 + api_docs/v1/UsageFargateResponse.md | 1 + api_docs/v1/UsageHostHour.md | 1 + api_docs/v1/UsageHostsResponse.md | 1 + api_docs/v1/UsageIncidentManagementHour.md | 1 + api_docs/v1/UsageIncidentManagementResponse.md | 1 + api_docs/v1/UsageIndexedSpansHour.md | 1 + api_docs/v1/UsageIndexedSpansResponse.md | 1 + api_docs/v1/UsageIngestedSpansHour.md | 1 + api_docs/v1/UsageIngestedSpansResponse.md | 1 + api_docs/v1/UsageIoTHour.md | 1 + api_docs/v1/UsageIoTResponse.md | 1 + api_docs/v1/UsageLambdaHour.md | 1 + api_docs/v1/UsageLambdaResponse.md | 1 + api_docs/v1/UsageLogsByIndexHour.md | 1 + api_docs/v1/UsageLogsByIndexResponse.md | 1 + api_docs/v1/UsageLogsHour.md | 1 + api_docs/v1/UsageLogsResponse.md | 1 + api_docs/v1/UsageNetworkFlowsHour.md | 1 + api_docs/v1/UsageNetworkFlowsResponse.md | 1 + api_docs/v1/UsageNetworkHostsHour.md | 1 + api_docs/v1/UsageNetworkHostsResponse.md | 1 + api_docs/v1/UsageProfilingHour.md | 1 + api_docs/v1/UsageProfilingResponse.md | 1 + api_docs/v1/UsageRumSessionsHour.md | 1 + api_docs/v1/UsageRumSessionsResponse.md | 1 + api_docs/v1/UsageSNMPHour.md | 1 + api_docs/v1/UsageSNMPResponse.md | 1 + api_docs/v1/UsageSpecifiedCustomReportsAttributes.md | 1 + api_docs/v1/UsageSpecifiedCustomReportsData.md | 1 + api_docs/v1/UsageSpecifiedCustomReportsMeta.md | 1 + api_docs/v1/UsageSpecifiedCustomReportsPage.md | 1 + api_docs/v1/UsageSpecifiedCustomReportsResponse.md | 1 + api_docs/v1/UsageSummaryDate.md | 1 + api_docs/v1/UsageSummaryDateOrg.md | 1 + api_docs/v1/UsageSummaryResponse.md | 1 + api_docs/v1/UsageSyntheticsAPIHour.md | 1 + api_docs/v1/UsageSyntheticsAPIResponse.md | 1 + api_docs/v1/UsageSyntheticsBrowserHour.md | 1 + api_docs/v1/UsageSyntheticsBrowserResponse.md | 1 + api_docs/v1/UsageSyntheticsHour.md | 1 + api_docs/v1/UsageSyntheticsResponse.md | 1 + api_docs/v1/UsageTimeseriesHour.md | 1 + api_docs/v1/UsageTimeseriesResponse.md | 1 + api_docs/v1/UsageTopAvgMetricsHour.md | 1 + api_docs/v1/UsageTopAvgMetricsResponse.md | 1 + api_docs/v1/UsageTraceHour.md | 1 + api_docs/v1/UsageTraceResponse.md | 1 + api_docs/v1/UsageTracingWithoutLimitsHour.md | 1 + api_docs/v1/UsageTracingWithoutLimitsResponse.md | 1 + api_docs/v1/User.md | 1 + api_docs/v1/UserDisableResponse.md | 1 + api_docs/v1/UserListResponse.md | 1 + api_docs/v1/UserResponse.md | 1 + api_docs/v1/Widget.md | 1 + api_docs/v1/WidgetAxis.md | 1 + api_docs/v1/WidgetConditionalFormat.md | 1 + api_docs/v1/WidgetCustomLink.md | 1 + api_docs/v1/WidgetEvent.md | 1 + api_docs/v1/WidgetFieldSort.md | 1 + api_docs/v1/WidgetFormula.md | 1 + api_docs/v1/WidgetFormulaLimit.md | 1 + api_docs/v1/WidgetLayout.md | 1 + api_docs/v1/WidgetMarker.md | 1 + api_docs/v1/WidgetRequestStyle.md | 1 + api_docs/v1/WidgetStyle.md | 1 + api_docs/v1/WidgetTime.md | 1 + api_docs/v2/APIErrorResponse.md | 1 + api_docs/v2/APIKeyCreateAttributes.md | 1 + api_docs/v2/APIKeyCreateData.md | 1 + api_docs/v2/APIKeyCreateRequest.md | 1 + api_docs/v2/APIKeyRelationships.md | 1 + api_docs/v2/APIKeyResponse.md | 1 + api_docs/v2/APIKeyUpdateAttributes.md | 1 + api_docs/v2/APIKeyUpdateData.md | 1 + api_docs/v2/APIKeyUpdateRequest.md | 1 + api_docs/v2/APIKeysResponse.md | 1 + api_docs/v2/ApplicationKeyCreateAttributes.md | 1 + api_docs/v2/ApplicationKeyCreateData.md | 1 + api_docs/v2/ApplicationKeyCreateRequest.md | 1 + api_docs/v2/ApplicationKeyRelationships.md | 1 + api_docs/v2/ApplicationKeyResponse.md | 1 + api_docs/v2/ApplicationKeyUpdateAttributes.md | 1 + api_docs/v2/ApplicationKeyUpdateData.md | 1 + api_docs/v2/ApplicationKeyUpdateRequest.md | 1 + api_docs/v2/Creator.md | 1 + api_docs/v2/DashboardListAddItemsRequest.md | 1 + api_docs/v2/DashboardListAddItemsResponse.md | 1 + api_docs/v2/DashboardListDeleteItemsRequest.md | 1 + api_docs/v2/DashboardListDeleteItemsResponse.md | 1 + api_docs/v2/DashboardListItem.md | 1 + api_docs/v2/DashboardListItemRequest.md | 1 + api_docs/v2/DashboardListItemResponse.md | 1 + api_docs/v2/DashboardListItems.md | 1 + api_docs/v2/DashboardListUpdateItemsRequest.md | 1 + api_docs/v2/DashboardListUpdateItemsResponse.md | 1 + api_docs/v2/FullAPIKey.md | 1 + api_docs/v2/FullAPIKeyAttributes.md | 1 + api_docs/v2/FullApplicationKey.md | 1 + api_docs/v2/FullApplicationKeyAttributes.md | 1 + api_docs/v2/IncidentCreateAttributes.md | 1 + api_docs/v2/IncidentCreateData.md | 1 + api_docs/v2/IncidentCreateRelationships.md | 1 + api_docs/v2/IncidentCreateRequest.md | 1 + api_docs/v2/IncidentFieldAttributesMultipleValue.md | 1 + api_docs/v2/IncidentFieldAttributesSingleValue.md | 1 + api_docs/v2/IncidentResponse.md | 1 + api_docs/v2/IncidentResponseAttributes.md | 1 + api_docs/v2/IncidentResponseData.md | 1 + api_docs/v2/IncidentResponseRelationships.md | 1 + api_docs/v2/IncidentServiceCreateAttributes.md | 1 + api_docs/v2/IncidentServiceCreateData.md | 1 + api_docs/v2/IncidentServiceCreateRequest.md | 1 + api_docs/v2/IncidentServiceRelationships.md | 1 + api_docs/v2/IncidentServiceResponse.md | 1 + api_docs/v2/IncidentServiceResponseAttributes.md | 1 + api_docs/v2/IncidentServiceResponseData.md | 1 + api_docs/v2/IncidentServiceUpdateAttributes.md | 1 + api_docs/v2/IncidentServiceUpdateData.md | 1 + api_docs/v2/IncidentServiceUpdateRequest.md | 1 + api_docs/v2/IncidentServicesResponse.md | 1 + api_docs/v2/IncidentServicesResponseMeta.md | 1 + api_docs/v2/IncidentServicesResponseMetaPagination.md | 1 + api_docs/v2/IncidentTeamCreateAttributes.md | 1 + api_docs/v2/IncidentTeamCreateData.md | 1 + api_docs/v2/IncidentTeamCreateRequest.md | 1 + api_docs/v2/IncidentTeamRelationships.md | 1 + api_docs/v2/IncidentTeamResponse.md | 1 + api_docs/v2/IncidentTeamResponseAttributes.md | 1 + api_docs/v2/IncidentTeamResponseData.md | 1 + api_docs/v2/IncidentTeamUpdateAttributes.md | 1 + api_docs/v2/IncidentTeamUpdateData.md | 1 + api_docs/v2/IncidentTeamUpdateRequest.md | 1 + api_docs/v2/IncidentTeamsResponse.md | 1 + .../v2/IncidentTimelineCellMarkdownCreateAttributes.md | 1 + ...IncidentTimelineCellMarkdownCreateAttributesContent.md | 1 + api_docs/v2/IncidentUpdateAttributes.md | 1 + api_docs/v2/IncidentUpdateData.md | 1 + api_docs/v2/IncidentUpdateRelationships.md | 1 + api_docs/v2/IncidentUpdateRequest.md | 1 + api_docs/v2/IncidentsResponse.md | 1 + api_docs/v2/ListApplicationKeysResponse.md | 1 + api_docs/v2/Log.md | 1 + api_docs/v2/LogAttributes.md | 1 + api_docs/v2/LogsAggregateBucket.md | 1 + api_docs/v2/LogsAggregateBucketValueTimeseries.md | 1 + api_docs/v2/LogsAggregateBucketValueTimeseriesPoint.md | 1 + api_docs/v2/LogsAggregateRequest.md | 1 + api_docs/v2/LogsAggregateRequestPage.md | 1 + api_docs/v2/LogsAggregateResponse.md | 1 + api_docs/v2/LogsAggregateResponseData.md | 1 + api_docs/v2/LogsAggregateSort.md | 1 + api_docs/v2/LogsArchive.md | 1 + api_docs/v2/LogsArchiveAttributes.md | 1 + api_docs/v2/LogsArchiveCreateRequest.md | 1 + api_docs/v2/LogsArchiveCreateRequestAttributes.md | 1 + api_docs/v2/LogsArchiveCreateRequestDefinition.md | 1 + api_docs/v2/LogsArchiveDefinition.md | 1 + api_docs/v2/LogsArchiveDestinationAzure.md | 1 + api_docs/v2/LogsArchiveDestinationGCS.md | 1 + api_docs/v2/LogsArchiveDestinationS3.md | 1 + api_docs/v2/LogsArchiveIntegrationAzure.md | 1 + api_docs/v2/LogsArchiveIntegrationGCS.md | 1 + api_docs/v2/LogsArchiveIntegrationS3.md | 1 + api_docs/v2/LogsArchiveOrder.md | 1 + api_docs/v2/LogsArchiveOrderAttributes.md | 1 + api_docs/v2/LogsArchiveOrderDefinition.md | 1 + api_docs/v2/LogsArchives.md | 1 + api_docs/v2/LogsCompute.md | 1 + api_docs/v2/LogsGroupBy.md | 1 + api_docs/v2/LogsGroupByHistogram.md | 1 + api_docs/v2/LogsListRequest.md | 1 + api_docs/v2/LogsListRequestPage.md | 1 + api_docs/v2/LogsListResponse.md | 1 + api_docs/v2/LogsListResponseLinks.md | 1 + api_docs/v2/LogsMetricCompute.md | 1 + api_docs/v2/LogsMetricCreateAttributes.md | 1 + api_docs/v2/LogsMetricCreateData.md | 1 + api_docs/v2/LogsMetricCreateRequest.md | 1 + api_docs/v2/LogsMetricFilter.md | 1 + api_docs/v2/LogsMetricGroupBy.md | 1 + api_docs/v2/LogsMetricResponse.md | 1 + api_docs/v2/LogsMetricResponseAttributes.md | 1 + api_docs/v2/LogsMetricResponseCompute.md | 1 + api_docs/v2/LogsMetricResponseData.md | 1 + api_docs/v2/LogsMetricResponseFilter.md | 1 + api_docs/v2/LogsMetricResponseGroupBy.md | 1 + api_docs/v2/LogsMetricUpdateAttributes.md | 1 + api_docs/v2/LogsMetricUpdateData.md | 1 + api_docs/v2/LogsMetricUpdateRequest.md | 1 + api_docs/v2/LogsMetricsResponse.md | 1 + api_docs/v2/LogsQueryFilter.md | 1 + api_docs/v2/LogsQueryOptions.md | 1 + api_docs/v2/LogsResponseMetadata.md | 1 + api_docs/v2/LogsResponseMetadataPage.md | 1 + api_docs/v2/LogsWarning.md | 1 + api_docs/v2/Metric.md | 1 + api_docs/v2/MetricAllTags.md | 1 + api_docs/v2/MetricAllTagsAttributes.md | 1 + api_docs/v2/MetricAllTagsResponse.md | 1 + api_docs/v2/MetricDistinctVolume.md | 1 + api_docs/v2/MetricDistinctVolumeAttributes.md | 1 + api_docs/v2/MetricIngestedIndexedVolume.md | 1 + api_docs/v2/MetricIngestedIndexedVolumeAttributes.md | 1 + api_docs/v2/MetricTagConfiguration.md | 1 + api_docs/v2/MetricTagConfigurationAttributes.md | 1 + api_docs/v2/MetricTagConfigurationCreateAttributes.md | 1 + api_docs/v2/MetricTagConfigurationCreateData.md | 1 + api_docs/v2/MetricTagConfigurationCreateRequest.md | 1 + api_docs/v2/MetricTagConfigurationResponse.md | 1 + api_docs/v2/MetricTagConfigurationUpdateAttributes.md | 1 + api_docs/v2/MetricTagConfigurationUpdateData.md | 1 + api_docs/v2/MetricTagConfigurationUpdateRequest.md | 1 + api_docs/v2/MetricVolumesResponse.md | 1 + api_docs/v2/MetricsAndMetricTagConfigurationsResponse.md | 1 + api_docs/v2/Organization.md | 1 + api_docs/v2/OrganizationAttributes.md | 1 + api_docs/v2/Pagination.md | 1 + api_docs/v2/PartialAPIKey.md | 1 + api_docs/v2/PartialAPIKeyAttributes.md | 1 + api_docs/v2/PartialApplicationKey.md | 1 + api_docs/v2/PartialApplicationKeyAttributes.md | 1 + api_docs/v2/Permission.md | 1 + api_docs/v2/PermissionAttributes.md | 1 + api_docs/v2/PermissionsResponse.md | 1 + api_docs/v2/ProcessSummariesMeta.md | 1 + api_docs/v2/ProcessSummariesMetaPage.md | 1 + api_docs/v2/ProcessSummariesResponse.md | 1 + api_docs/v2/ProcessSummary.md | 1 + api_docs/v2/ProcessSummaryAttributes.md | 1 + .../v2/RelationshipToIncidentIntegrationMetadataData.md | 1 + api_docs/v2/RelationshipToIncidentIntegrationMetadatas.md | 1 + api_docs/v2/RelationshipToIncidentPostmortem.md | 1 + api_docs/v2/RelationshipToIncidentPostmortemData.md | 1 + api_docs/v2/RelationshipToOrganization.md | 1 + api_docs/v2/RelationshipToOrganizationData.md | 1 + api_docs/v2/RelationshipToOrganizations.md | 1 + api_docs/v2/RelationshipToPermission.md | 1 + api_docs/v2/RelationshipToPermissionData.md | 1 + api_docs/v2/RelationshipToPermissions.md | 1 + api_docs/v2/RelationshipToRole.md | 1 + api_docs/v2/RelationshipToRoleData.md | 1 + api_docs/v2/RelationshipToRoles.md | 1 + api_docs/v2/RelationshipToUser.md | 1 + api_docs/v2/RelationshipToUserData.md | 1 + api_docs/v2/RelationshipToUsers.md | 1 + api_docs/v2/ResponseMetaAttributes.md | 1 + api_docs/v2/Role.md | 1 + api_docs/v2/RoleAttributes.md | 1 + api_docs/v2/RoleCreateAttributes.md | 1 + api_docs/v2/RoleCreateData.md | 1 + api_docs/v2/RoleCreateRequest.md | 1 + api_docs/v2/RoleCreateResponse.md | 1 + api_docs/v2/RoleCreateResponseData.md | 1 + api_docs/v2/RoleRelationships.md | 1 + api_docs/v2/RoleResponse.md | 1 + api_docs/v2/RoleResponseRelationships.md | 1 + api_docs/v2/RoleUpdateAttributes.md | 1 + api_docs/v2/RoleUpdateData.md | 1 + api_docs/v2/RoleUpdateRequest.md | 1 + api_docs/v2/RoleUpdateResponse.md | 1 + api_docs/v2/RoleUpdateResponseData.md | 1 + api_docs/v2/RolesResponse.md | 1 + api_docs/v2/SecurityMonitoringFilter.md | 1 + api_docs/v2/SecurityMonitoringListRulesResponse.md | 1 + api_docs/v2/SecurityMonitoringRuleCase.md | 1 + api_docs/v2/SecurityMonitoringRuleCaseCreate.md | 1 + api_docs/v2/SecurityMonitoringRuleCreatePayload.md | 1 + api_docs/v2/SecurityMonitoringRuleNewValueOptions.md | 1 + api_docs/v2/SecurityMonitoringRuleOptions.md | 1 + api_docs/v2/SecurityMonitoringRuleQuery.md | 1 + api_docs/v2/SecurityMonitoringRuleQueryCreate.md | 1 + api_docs/v2/SecurityMonitoringRuleResponse.md | 1 + api_docs/v2/SecurityMonitoringRuleUpdatePayload.md | 1 + api_docs/v2/SecurityMonitoringSignal.md | 1 + api_docs/v2/SecurityMonitoringSignalAttributes.md | 1 + api_docs/v2/SecurityMonitoringSignalListRequest.md | 1 + api_docs/v2/SecurityMonitoringSignalListRequestFilter.md | 1 + api_docs/v2/SecurityMonitoringSignalListRequestPage.md | 1 + api_docs/v2/SecurityMonitoringSignalsListResponse.md | 1 + api_docs/v2/SecurityMonitoringSignalsListResponseLinks.md | 1 + api_docs/v2/SecurityMonitoringSignalsListResponseMeta.md | 1 + .../v2/SecurityMonitoringSignalsListResponseMetaPage.md | 1 + api_docs/v2/User.md | 1 + api_docs/v2/UserAttributes.md | 1 + api_docs/v2/UserCreateAttributes.md | 1 + api_docs/v2/UserCreateData.md | 1 + api_docs/v2/UserCreateRequest.md | 1 + api_docs/v2/UserInvitationData.md | 1 + api_docs/v2/UserInvitationDataAttributes.md | 1 + api_docs/v2/UserInvitationRelationships.md | 1 + api_docs/v2/UserInvitationResponse.md | 1 + api_docs/v2/UserInvitationResponseData.md | 1 + api_docs/v2/UserInvitationsRequest.md | 1 + api_docs/v2/UserInvitationsResponse.md | 1 + api_docs/v2/UserRelationships.md | 1 + api_docs/v2/UserResponse.md | 1 + api_docs/v2/UserResponseRelationships.md | 1 + api_docs/v2/UserUpdateAttributes.md | 1 + api_docs/v2/UserUpdateData.md | 1 + api_docs/v2/UserUpdateRequest.md | 1 + api_docs/v2/UsersResponse.md | 1 + 604 files changed, 607 insertions(+), 4 deletions(-) diff --git a/.apigentools-info b/.apigentools-info index 74505b8097a..770e445bdc3 100644 --- a/.apigentools-info +++ b/.apigentools-info @@ -4,13 +4,13 @@ "spec_versions": { "v1": { "apigentools_version": "1.4.1.dev6", - "regenerated": "2021-03-23 10:52:32.731196", - "spec_repo_commit": "34cf37f" + "regenerated": "2021-03-23 14:02:16.829328", + "spec_repo_commit": "7e667f1" }, "v2": { "apigentools_version": "1.4.1.dev6", - "regenerated": "2021-03-23 10:53:17.035331", - "spec_repo_commit": "34cf37f" + "regenerated": "2021-03-23 14:03:03.589201", + "spec_repo_commit": "7e667f1" } } } \ No newline at end of file diff --git a/api_docs/v1/APIErrorResponse.md b/api_docs/v1/APIErrorResponse.md index 11e6de06b3a..a4a6f95c369 100644 --- a/api_docs/v1/APIErrorResponse.md +++ b/api_docs/v1/APIErrorResponse.md @@ -3,6 +3,7 @@ # APIErrorResponse Error response object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSAccount.md b/api_docs/v1/AWSAccount.md index 54b4d7dd151..fda8ab041fd 100644 --- a/api_docs/v1/AWSAccount.md +++ b/api_docs/v1/AWSAccount.md @@ -3,6 +3,7 @@ # AWSAccount Returns the AWS account associated with this integration. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSAccountAndLambdaRequest.md b/api_docs/v1/AWSAccountAndLambdaRequest.md index eef09b09859..c4419d941c8 100644 --- a/api_docs/v1/AWSAccountAndLambdaRequest.md +++ b/api_docs/v1/AWSAccountAndLambdaRequest.md @@ -3,6 +3,7 @@ # AWSAccountAndLambdaRequest AWS account ID and Lambda ARN. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSAccountCreateResponse.md b/api_docs/v1/AWSAccountCreateResponse.md index 0f0c6d805ee..c5c3031ce42 100644 --- a/api_docs/v1/AWSAccountCreateResponse.md +++ b/api_docs/v1/AWSAccountCreateResponse.md @@ -3,6 +3,7 @@ # AWSAccountCreateResponse The Response returned by the AWS Create Account call. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSAccountListResponse.md b/api_docs/v1/AWSAccountListResponse.md index 3e38bdf337a..ccac6c22bcd 100644 --- a/api_docs/v1/AWSAccountListResponse.md +++ b/api_docs/v1/AWSAccountListResponse.md @@ -3,6 +3,7 @@ # AWSAccountListResponse List of enabled AWS accounts. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSLogsAsyncError.md b/api_docs/v1/AWSLogsAsyncError.md index eb674141062..74c24f27b21 100644 --- a/api_docs/v1/AWSLogsAsyncError.md +++ b/api_docs/v1/AWSLogsAsyncError.md @@ -3,6 +3,7 @@ # AWSLogsAsyncError Description of errors. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSLogsAsyncResponse.md b/api_docs/v1/AWSLogsAsyncResponse.md index 11c17275b85..e148335a2dd 100644 --- a/api_docs/v1/AWSLogsAsyncResponse.md +++ b/api_docs/v1/AWSLogsAsyncResponse.md @@ -3,6 +3,7 @@ # AWSLogsAsyncResponse A list of all Datadog-AWS logs integrations available in your Datadog organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSLogsLambda.md b/api_docs/v1/AWSLogsLambda.md index 26ed1ef4fd2..73d9e89d1a6 100644 --- a/api_docs/v1/AWSLogsLambda.md +++ b/api_docs/v1/AWSLogsLambda.md @@ -3,6 +3,7 @@ # AWSLogsLambda Description of the Lambdas. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSLogsListResponse.md b/api_docs/v1/AWSLogsListResponse.md index 471087b48e7..e1604f73650 100644 --- a/api_docs/v1/AWSLogsListResponse.md +++ b/api_docs/v1/AWSLogsListResponse.md @@ -3,6 +3,7 @@ # AWSLogsListResponse A list of all Datadog-AWS logs integrations available in your Datadog organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSLogsListServicesResponse.md b/api_docs/v1/AWSLogsListServicesResponse.md index b55a2041ab0..0fc15ad74e0 100644 --- a/api_docs/v1/AWSLogsListServicesResponse.md +++ b/api_docs/v1/AWSLogsListServicesResponse.md @@ -3,6 +3,7 @@ # AWSLogsListServicesResponse The list of current AWS services for which Datadog offers automatic log collection. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSLogsServicesRequest.md b/api_docs/v1/AWSLogsServicesRequest.md index 6bf08fe8e1e..12df66ec6a3 100644 --- a/api_docs/v1/AWSLogsServicesRequest.md +++ b/api_docs/v1/AWSLogsServicesRequest.md @@ -3,6 +3,7 @@ # AWSLogsServicesRequest A list of current AWS services for which Datadog offers automatic log collection. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSTagFilter.md b/api_docs/v1/AWSTagFilter.md index ab441b3d5dd..5d2297d3050 100644 --- a/api_docs/v1/AWSTagFilter.md +++ b/api_docs/v1/AWSTagFilter.md @@ -3,6 +3,7 @@ # AWSTagFilter A tag filter. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSTagFilterCreateRequest.md b/api_docs/v1/AWSTagFilterCreateRequest.md index 3a67077cf96..ea924645741 100644 --- a/api_docs/v1/AWSTagFilterCreateRequest.md +++ b/api_docs/v1/AWSTagFilterCreateRequest.md @@ -3,6 +3,7 @@ # AWSTagFilterCreateRequest The objects used to set an AWS tag filter. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSTagFilterDeleteRequest.md b/api_docs/v1/AWSTagFilterDeleteRequest.md index f43dd2119d7..752c2a04ba4 100644 --- a/api_docs/v1/AWSTagFilterDeleteRequest.md +++ b/api_docs/v1/AWSTagFilterDeleteRequest.md @@ -3,6 +3,7 @@ # AWSTagFilterDeleteRequest The objects used to delete an AWS tag filter entry. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AWSTagFilterListResponse.md b/api_docs/v1/AWSTagFilterListResponse.md index ac9691eb137..afeb2143135 100644 --- a/api_docs/v1/AWSTagFilterListResponse.md +++ b/api_docs/v1/AWSTagFilterListResponse.md @@ -3,6 +3,7 @@ # AWSTagFilterListResponse An array of tag filter rules by `namespace` and tag filter string. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AlertGraphWidgetDefinition.md b/api_docs/v1/AlertGraphWidgetDefinition.md index 225abb8d5eb..8d0e70dba36 100644 --- a/api_docs/v1/AlertGraphWidgetDefinition.md +++ b/api_docs/v1/AlertGraphWidgetDefinition.md @@ -3,6 +3,7 @@ # AlertGraphWidgetDefinition Alert graphs are timeseries graphs showing the current status of any monitor defined on your system. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AlertValueWidgetDefinition.md b/api_docs/v1/AlertValueWidgetDefinition.md index e2f6e189d0a..a66b98d627e 100644 --- a/api_docs/v1/AlertValueWidgetDefinition.md +++ b/api_docs/v1/AlertValueWidgetDefinition.md @@ -3,6 +3,7 @@ # AlertValueWidgetDefinition Alert values are query values showing the current value of the metric in any monitor defined on your system. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ApiKey.md b/api_docs/v1/ApiKey.md index b432827df47..68392005f34 100644 --- a/api_docs/v1/ApiKey.md +++ b/api_docs/v1/ApiKey.md @@ -3,6 +3,7 @@ # ApiKey Datadog API key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ApiKeyListResponse.md b/api_docs/v1/ApiKeyListResponse.md index 81ac36c12ab..a0f68042470 100644 --- a/api_docs/v1/ApiKeyListResponse.md +++ b/api_docs/v1/ApiKeyListResponse.md @@ -3,6 +3,7 @@ # ApiKeyListResponse List of API and application keys available for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ApiKeyResponse.md b/api_docs/v1/ApiKeyResponse.md index ab1fde513a4..253efeab018 100644 --- a/api_docs/v1/ApiKeyResponse.md +++ b/api_docs/v1/ApiKeyResponse.md @@ -3,6 +3,7 @@ # ApiKeyResponse An API key with its associated metadata. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ApmStatsQueryColumnType.md b/api_docs/v1/ApmStatsQueryColumnType.md index 5869084bfbf..af498078d25 100644 --- a/api_docs/v1/ApmStatsQueryColumnType.md +++ b/api_docs/v1/ApmStatsQueryColumnType.md @@ -3,6 +3,7 @@ # ApmStatsQueryColumnType Column properties. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ApmStatsQueryDefinition.md b/api_docs/v1/ApmStatsQueryDefinition.md index 52c191988a8..58f88e39d56 100644 --- a/api_docs/v1/ApmStatsQueryDefinition.md +++ b/api_docs/v1/ApmStatsQueryDefinition.md @@ -3,6 +3,7 @@ # ApmStatsQueryDefinition The APM stats query for table and distributions widgets. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ApplicationKey.md b/api_docs/v1/ApplicationKey.md index b48fbf6a6a4..abbd7268cf6 100644 --- a/api_docs/v1/ApplicationKey.md +++ b/api_docs/v1/ApplicationKey.md @@ -3,6 +3,7 @@ # ApplicationKey An application key with its associated metadata. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ApplicationKeyListResponse.md b/api_docs/v1/ApplicationKeyListResponse.md index 4b6d161299d..52e697d357a 100644 --- a/api_docs/v1/ApplicationKeyListResponse.md +++ b/api_docs/v1/ApplicationKeyListResponse.md @@ -3,6 +3,7 @@ # ApplicationKeyListResponse An application key response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ApplicationKeyResponse.md b/api_docs/v1/ApplicationKeyResponse.md index 665bf6cb341..89cf2edeb0e 100644 --- a/api_docs/v1/ApplicationKeyResponse.md +++ b/api_docs/v1/ApplicationKeyResponse.md @@ -3,6 +3,7 @@ # ApplicationKeyResponse An application key response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AuthenticationValidationResponse.md b/api_docs/v1/AuthenticationValidationResponse.md index 7706c0f8675..a153072a550 100644 --- a/api_docs/v1/AuthenticationValidationResponse.md +++ b/api_docs/v1/AuthenticationValidationResponse.md @@ -3,6 +3,7 @@ # AuthenticationValidationResponse Represent validation endpoint responses. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/AzureAccount.md b/api_docs/v1/AzureAccount.md index b6d745aef74..a8a5c4cdb68 100644 --- a/api_docs/v1/AzureAccount.md +++ b/api_docs/v1/AzureAccount.md @@ -3,6 +3,7 @@ # AzureAccount Datadog-Azure integrations configured for your organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/CancelDowntimesByScopeRequest.md b/api_docs/v1/CancelDowntimesByScopeRequest.md index 660956c32d6..15cc7749f75 100644 --- a/api_docs/v1/CancelDowntimesByScopeRequest.md +++ b/api_docs/v1/CancelDowntimesByScopeRequest.md @@ -3,6 +3,7 @@ # CancelDowntimesByScopeRequest Cancel downtimes according to scope. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/CanceledDowntimesIds.md b/api_docs/v1/CanceledDowntimesIds.md index fa8a36a49aa..b723591e2ba 100644 --- a/api_docs/v1/CanceledDowntimesIds.md +++ b/api_docs/v1/CanceledDowntimesIds.md @@ -3,6 +3,7 @@ # CanceledDowntimesIds Object containing array of IDs of canceled downtimes. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ChangeWidgetDefinition.md b/api_docs/v1/ChangeWidgetDefinition.md index 7f7ea38029b..dabd3029e0f 100644 --- a/api_docs/v1/ChangeWidgetDefinition.md +++ b/api_docs/v1/ChangeWidgetDefinition.md @@ -3,6 +3,7 @@ # ChangeWidgetDefinition The Change graph shows you the change in a value over the time period chosen. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ChangeWidgetRequest.md b/api_docs/v1/ChangeWidgetRequest.md index 1a49bf31d7f..673228f7a11 100644 --- a/api_docs/v1/ChangeWidgetRequest.md +++ b/api_docs/v1/ChangeWidgetRequest.md @@ -3,6 +3,7 @@ # ChangeWidgetRequest Updated change widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/CheckCanDeleteMonitorResponse.md b/api_docs/v1/CheckCanDeleteMonitorResponse.md index 5e621e06fd4..df7cebed16b 100644 --- a/api_docs/v1/CheckCanDeleteMonitorResponse.md +++ b/api_docs/v1/CheckCanDeleteMonitorResponse.md @@ -3,6 +3,7 @@ # CheckCanDeleteMonitorResponse Response of monitor IDs that can or can't be safely deleted. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/CheckCanDeleteMonitorResponseData.md b/api_docs/v1/CheckCanDeleteMonitorResponseData.md index 8407492da6f..b7959d744a9 100644 --- a/api_docs/v1/CheckCanDeleteMonitorResponseData.md +++ b/api_docs/v1/CheckCanDeleteMonitorResponseData.md @@ -3,6 +3,7 @@ # CheckCanDeleteMonitorResponseData Wrapper object with the list of monitor IDs. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/CheckCanDeleteSLOResponse.md b/api_docs/v1/CheckCanDeleteSLOResponse.md index d632d5e7c65..0e63de22b74 100644 --- a/api_docs/v1/CheckCanDeleteSLOResponse.md +++ b/api_docs/v1/CheckCanDeleteSLOResponse.md @@ -3,6 +3,7 @@ # CheckCanDeleteSLOResponse A service level objective response containing the requested object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/CheckCanDeleteSLOResponseData.md b/api_docs/v1/CheckCanDeleteSLOResponseData.md index 8f91fb5ebb6..15686c59f51 100644 --- a/api_docs/v1/CheckCanDeleteSLOResponseData.md +++ b/api_docs/v1/CheckCanDeleteSLOResponseData.md @@ -3,6 +3,7 @@ # CheckCanDeleteSLOResponseData An array of service level objective objects. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/CheckStatusWidgetDefinition.md b/api_docs/v1/CheckStatusWidgetDefinition.md index 5942e93ecc8..28448bf785d 100644 --- a/api_docs/v1/CheckStatusWidgetDefinition.md +++ b/api_docs/v1/CheckStatusWidgetDefinition.md @@ -3,6 +3,7 @@ # CheckStatusWidgetDefinition Check status shows the current status or number of results for any check performed. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/Creator.md b/api_docs/v1/Creator.md index 6b3678871e5..5fcddcb80fc 100644 --- a/api_docs/v1/Creator.md +++ b/api_docs/v1/Creator.md @@ -3,6 +3,7 @@ # Creator Object describing the creator of the shared element. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/Dashboard.md b/api_docs/v1/Dashboard.md index d000bcd5771..7ada7bee3be 100644 --- a/api_docs/v1/Dashboard.md +++ b/api_docs/v1/Dashboard.md @@ -3,6 +3,7 @@ # Dashboard A dashboard is Datadog’s tool for visually tracking, analyzing, and displaying key performance metrics, which enable you to monitor the health of your infrastructure. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DashboardDeleteResponse.md b/api_docs/v1/DashboardDeleteResponse.md index 1a497cde87a..8a56dd00c28 100644 --- a/api_docs/v1/DashboardDeleteResponse.md +++ b/api_docs/v1/DashboardDeleteResponse.md @@ -3,6 +3,7 @@ # DashboardDeleteResponse Response from the delete dashboard call. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DashboardList.md b/api_docs/v1/DashboardList.md index efe681816a9..d97304453ef 100644 --- a/api_docs/v1/DashboardList.md +++ b/api_docs/v1/DashboardList.md @@ -3,6 +3,7 @@ # DashboardList Your Datadog Dashboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DashboardListDeleteResponse.md b/api_docs/v1/DashboardListDeleteResponse.md index ab74c5f49c6..dd6bea28451 100644 --- a/api_docs/v1/DashboardListDeleteResponse.md +++ b/api_docs/v1/DashboardListDeleteResponse.md @@ -3,6 +3,7 @@ # DashboardListDeleteResponse Deleted dashboard details. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DashboardListListResponse.md b/api_docs/v1/DashboardListListResponse.md index 62b3c10c8ca..57478be4191 100644 --- a/api_docs/v1/DashboardListListResponse.md +++ b/api_docs/v1/DashboardListListResponse.md @@ -3,6 +3,7 @@ # DashboardListListResponse Information on your dashboard lists. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DashboardSummary.md b/api_docs/v1/DashboardSummary.md index 1e4c27d52a4..b6a26e44746 100644 --- a/api_docs/v1/DashboardSummary.md +++ b/api_docs/v1/DashboardSummary.md @@ -3,6 +3,7 @@ # DashboardSummary Dashboard summary response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DashboardSummaryDefinition.md b/api_docs/v1/DashboardSummaryDefinition.md index 1c2c018d343..e55943393b1 100644 --- a/api_docs/v1/DashboardSummaryDefinition.md +++ b/api_docs/v1/DashboardSummaryDefinition.md @@ -3,6 +3,7 @@ # DashboardSummaryDefinition Dashboard definition. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DashboardTemplateVariable.md b/api_docs/v1/DashboardTemplateVariable.md index 5cf4e0376fa..894f6197be1 100644 --- a/api_docs/v1/DashboardTemplateVariable.md +++ b/api_docs/v1/DashboardTemplateVariable.md @@ -3,6 +3,7 @@ # DashboardTemplateVariable Template variable. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DashboardTemplateVariablePreset.md b/api_docs/v1/DashboardTemplateVariablePreset.md index 0e758b9c3bc..7094fe63562 100644 --- a/api_docs/v1/DashboardTemplateVariablePreset.md +++ b/api_docs/v1/DashboardTemplateVariablePreset.md @@ -3,6 +3,7 @@ # DashboardTemplateVariablePreset Template variables saved views. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DashboardTemplateVariablePresetValue.md b/api_docs/v1/DashboardTemplateVariablePresetValue.md index d22b045ea03..b5978357c0f 100644 --- a/api_docs/v1/DashboardTemplateVariablePresetValue.md +++ b/api_docs/v1/DashboardTemplateVariablePresetValue.md @@ -3,6 +3,7 @@ # DashboardTemplateVariablePresetValue Template variables saved views. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DeletedMonitor.md b/api_docs/v1/DeletedMonitor.md index c5c494f32fb..88721bf78f4 100644 --- a/api_docs/v1/DeletedMonitor.md +++ b/api_docs/v1/DeletedMonitor.md @@ -3,6 +3,7 @@ # DeletedMonitor Response from the delete monitor call. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DistributionWidgetDefinition.md b/api_docs/v1/DistributionWidgetDefinition.md index a5441f5e04c..2d8abdcdb20 100644 --- a/api_docs/v1/DistributionWidgetDefinition.md +++ b/api_docs/v1/DistributionWidgetDefinition.md @@ -3,6 +3,7 @@ # DistributionWidgetDefinition The Distribution visualization is another way of showing metrics aggregated across one or several tags, such as hosts. Unlike the heat map, a distribution graph’s x-axis is quantity rather than time. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DistributionWidgetRequest.md b/api_docs/v1/DistributionWidgetRequest.md index 6c50d9d4dd5..57f92ef37a8 100644 --- a/api_docs/v1/DistributionWidgetRequest.md +++ b/api_docs/v1/DistributionWidgetRequest.md @@ -3,6 +3,7 @@ # DistributionWidgetRequest Updated distribution widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/Downtime.md b/api_docs/v1/Downtime.md index 70dd36c8fb7..0ab93d282ae 100644 --- a/api_docs/v1/Downtime.md +++ b/api_docs/v1/Downtime.md @@ -3,6 +3,7 @@ # Downtime Downtiming gives you greater control over monitor notifications by allowing you to globally exclude scopes from alerting. Downtime settings, which can be scheduled with start and end times, prevent all alerting related to specified Datadog tags. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/DowntimeRecurrence.md b/api_docs/v1/DowntimeRecurrence.md index 0ece4edfcd6..bf34de88257 100644 --- a/api_docs/v1/DowntimeRecurrence.md +++ b/api_docs/v1/DowntimeRecurrence.md @@ -3,6 +3,7 @@ # DowntimeRecurrence An object defining the recurrence of the downtime. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/Event.md b/api_docs/v1/Event.md index ec4e78ec490..04b48b640c7 100644 --- a/api_docs/v1/Event.md +++ b/api_docs/v1/Event.md @@ -3,6 +3,7 @@ # Event Object representing an event. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/EventListResponse.md b/api_docs/v1/EventListResponse.md index 72af834ce1d..cfa305391c9 100644 --- a/api_docs/v1/EventListResponse.md +++ b/api_docs/v1/EventListResponse.md @@ -3,6 +3,7 @@ # EventListResponse An event list response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/EventQueryDefinition.md b/api_docs/v1/EventQueryDefinition.md index 7ad884308ee..fa69fb4978f 100644 --- a/api_docs/v1/EventQueryDefinition.md +++ b/api_docs/v1/EventQueryDefinition.md @@ -3,6 +3,7 @@ # EventQueryDefinition The event query. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/EventResponse.md b/api_docs/v1/EventResponse.md index db8a622c417..bac5f5c59af 100644 --- a/api_docs/v1/EventResponse.md +++ b/api_docs/v1/EventResponse.md @@ -3,6 +3,7 @@ # EventResponse Object containing an event response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/EventStreamWidgetDefinition.md b/api_docs/v1/EventStreamWidgetDefinition.md index d86bae3802c..000fb7216a6 100644 --- a/api_docs/v1/EventStreamWidgetDefinition.md +++ b/api_docs/v1/EventStreamWidgetDefinition.md @@ -3,6 +3,7 @@ # EventStreamWidgetDefinition The event stream is a widget version of the stream of events on the Event Stream view. Only available on FREE layout dashboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/EventTimelineWidgetDefinition.md b/api_docs/v1/EventTimelineWidgetDefinition.md index 337b7318cbc..17cfd271a91 100644 --- a/api_docs/v1/EventTimelineWidgetDefinition.md +++ b/api_docs/v1/EventTimelineWidgetDefinition.md @@ -3,6 +3,7 @@ # EventTimelineWidgetDefinition The event timeline is a widget version of the timeline that appears at the top of the Event Stream view. Only available on FREE layout dashboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/FormulaAndFunctionEventQueryDefinition.md b/api_docs/v1/FormulaAndFunctionEventQueryDefinition.md index 47a84c56426..fbf537f5020 100644 --- a/api_docs/v1/FormulaAndFunctionEventQueryDefinition.md +++ b/api_docs/v1/FormulaAndFunctionEventQueryDefinition.md @@ -3,6 +3,7 @@ # FormulaAndFunctionEventQueryDefinition A formula and functions events query. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/FormulaAndFunctionEventQueryDefinitionCompute.md b/api_docs/v1/FormulaAndFunctionEventQueryDefinitionCompute.md index b90ae5eac4b..b1da3439075 100644 --- a/api_docs/v1/FormulaAndFunctionEventQueryDefinitionCompute.md +++ b/api_docs/v1/FormulaAndFunctionEventQueryDefinitionCompute.md @@ -3,6 +3,7 @@ # FormulaAndFunctionEventQueryDefinitionCompute Compute options. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/FormulaAndFunctionEventQueryDefinitionSearch.md b/api_docs/v1/FormulaAndFunctionEventQueryDefinitionSearch.md index 6ce4d53fb23..c9edcb23a77 100644 --- a/api_docs/v1/FormulaAndFunctionEventQueryDefinitionSearch.md +++ b/api_docs/v1/FormulaAndFunctionEventQueryDefinitionSearch.md @@ -3,6 +3,7 @@ # FormulaAndFunctionEventQueryDefinitionSearch Search options. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/FormulaAndFunctionEventQueryGroupBy.md b/api_docs/v1/FormulaAndFunctionEventQueryGroupBy.md index b232a8fe84f..42222719d53 100644 --- a/api_docs/v1/FormulaAndFunctionEventQueryGroupBy.md +++ b/api_docs/v1/FormulaAndFunctionEventQueryGroupBy.md @@ -3,6 +3,7 @@ # FormulaAndFunctionEventQueryGroupBy List of objects used to group by. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/FormulaAndFunctionEventQueryGroupBySort.md b/api_docs/v1/FormulaAndFunctionEventQueryGroupBySort.md index e3ea039d3ba..ce6e3d7c6db 100644 --- a/api_docs/v1/FormulaAndFunctionEventQueryGroupBySort.md +++ b/api_docs/v1/FormulaAndFunctionEventQueryGroupBySort.md @@ -3,6 +3,7 @@ # FormulaAndFunctionEventQueryGroupBySort Options for sorting group by results. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/FormulaAndFunctionMetricQueryDefinition.md b/api_docs/v1/FormulaAndFunctionMetricQueryDefinition.md index a6a0d24794b..b2eaf47b05e 100644 --- a/api_docs/v1/FormulaAndFunctionMetricQueryDefinition.md +++ b/api_docs/v1/FormulaAndFunctionMetricQueryDefinition.md @@ -3,6 +3,7 @@ # FormulaAndFunctionMetricQueryDefinition A formula and functions metrics query. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/FormulaAndFunctionProcessQueryDefinition.md b/api_docs/v1/FormulaAndFunctionProcessQueryDefinition.md index bcab31e627a..609ee5be855 100644 --- a/api_docs/v1/FormulaAndFunctionProcessQueryDefinition.md +++ b/api_docs/v1/FormulaAndFunctionProcessQueryDefinition.md @@ -3,6 +3,7 @@ # FormulaAndFunctionProcessQueryDefinition Process query using formulas and functions. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/FreeTextWidgetDefinition.md b/api_docs/v1/FreeTextWidgetDefinition.md index 3aa72a94312..5aab4166105 100644 --- a/api_docs/v1/FreeTextWidgetDefinition.md +++ b/api_docs/v1/FreeTextWidgetDefinition.md @@ -3,6 +3,7 @@ # FreeTextWidgetDefinition Free text is a widget that allows you to add headings to your screenboard. Commonly used to state the overall purpose of the dashboard. Only available on FREE layout dashboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/GCPAccount.md b/api_docs/v1/GCPAccount.md index 0388346626e..860fdd4ccd0 100644 --- a/api_docs/v1/GCPAccount.md +++ b/api_docs/v1/GCPAccount.md @@ -3,6 +3,7 @@ # GCPAccount Your Google Cloud Platform Account. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/GeomapWidgetDefinition.md b/api_docs/v1/GeomapWidgetDefinition.md index 2ddd9bfadd9..c23fb9abeb3 100644 --- a/api_docs/v1/GeomapWidgetDefinition.md +++ b/api_docs/v1/GeomapWidgetDefinition.md @@ -3,6 +3,7 @@ # GeomapWidgetDefinition This visualization displays a series of values by country on a world map. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/GeomapWidgetDefinitionStyle.md b/api_docs/v1/GeomapWidgetDefinitionStyle.md index f80416bcca8..a01f562e01e 100644 --- a/api_docs/v1/GeomapWidgetDefinitionStyle.md +++ b/api_docs/v1/GeomapWidgetDefinitionStyle.md @@ -3,6 +3,7 @@ # GeomapWidgetDefinitionStyle The style to apply to the widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/GeomapWidgetDefinitionView.md b/api_docs/v1/GeomapWidgetDefinitionView.md index e02920fca48..552685b21e1 100644 --- a/api_docs/v1/GeomapWidgetDefinitionView.md +++ b/api_docs/v1/GeomapWidgetDefinitionView.md @@ -3,6 +3,7 @@ # GeomapWidgetDefinitionView The view of the world that the map should render. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/GeomapWidgetRequest.md b/api_docs/v1/GeomapWidgetRequest.md index de6effc990e..903ade2f8b1 100644 --- a/api_docs/v1/GeomapWidgetRequest.md +++ b/api_docs/v1/GeomapWidgetRequest.md @@ -3,6 +3,7 @@ # GeomapWidgetRequest An updated geomap widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/GraphSnapshot.md b/api_docs/v1/GraphSnapshot.md index d941280a0e1..919f57ce866 100644 --- a/api_docs/v1/GraphSnapshot.md +++ b/api_docs/v1/GraphSnapshot.md @@ -3,6 +3,7 @@ # GraphSnapshot Object representing a graph snapshot. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/GroupWidgetDefinition.md b/api_docs/v1/GroupWidgetDefinition.md index c3e5372197d..6c47f59d785 100644 --- a/api_docs/v1/GroupWidgetDefinition.md +++ b/api_docs/v1/GroupWidgetDefinition.md @@ -3,6 +3,7 @@ # GroupWidgetDefinition The groups widget allows you to keep similar graphs together on your timeboard. Each group has a custom header, can hold one to many graphs, and is collapsible. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HeatMapWidgetDefinition.md b/api_docs/v1/HeatMapWidgetDefinition.md index e7dcc523b06..cc6d7e44dec 100644 --- a/api_docs/v1/HeatMapWidgetDefinition.md +++ b/api_docs/v1/HeatMapWidgetDefinition.md @@ -3,6 +3,7 @@ # HeatMapWidgetDefinition The heat map visualization shows metrics aggregated across many tags, such as hosts. The more hosts that have a particular value, the darker that square is. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HeatMapWidgetRequest.md b/api_docs/v1/HeatMapWidgetRequest.md index 3b408b90d8e..4a7f07d2e5e 100644 --- a/api_docs/v1/HeatMapWidgetRequest.md +++ b/api_docs/v1/HeatMapWidgetRequest.md @@ -3,6 +3,7 @@ # HeatMapWidgetRequest Updated heat map widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/Host.md b/api_docs/v1/Host.md index 741fd9a0477..8dfe1b21acf 100644 --- a/api_docs/v1/Host.md +++ b/api_docs/v1/Host.md @@ -3,6 +3,7 @@ # Host Object representing a host. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HostListResponse.md b/api_docs/v1/HostListResponse.md index 6ae60a5d96b..e3484c17cb5 100644 --- a/api_docs/v1/HostListResponse.md +++ b/api_docs/v1/HostListResponse.md @@ -3,6 +3,7 @@ # HostListResponse Response with Host information from Datadog. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HostMapRequest.md b/api_docs/v1/HostMapRequest.md index 65ad4f294d7..6a02c2467e3 100644 --- a/api_docs/v1/HostMapRequest.md +++ b/api_docs/v1/HostMapRequest.md @@ -3,6 +3,7 @@ # HostMapRequest Updated host map. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HostMapWidgetDefinition.md b/api_docs/v1/HostMapWidgetDefinition.md index 4f02849c67b..e4f372c6aa1 100644 --- a/api_docs/v1/HostMapWidgetDefinition.md +++ b/api_docs/v1/HostMapWidgetDefinition.md @@ -3,6 +3,7 @@ # HostMapWidgetDefinition The host map widget graphs any metric across your hosts using the same visualization available from the main Host Map page. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HostMapWidgetDefinitionRequests.md b/api_docs/v1/HostMapWidgetDefinitionRequests.md index 2f3d3de3dff..e97afd8d2d0 100644 --- a/api_docs/v1/HostMapWidgetDefinitionRequests.md +++ b/api_docs/v1/HostMapWidgetDefinitionRequests.md @@ -3,6 +3,7 @@ # HostMapWidgetDefinitionRequests List of definitions. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HostMapWidgetDefinitionStyle.md b/api_docs/v1/HostMapWidgetDefinitionStyle.md index b84fd8c2cb1..e9f27e2f88b 100644 --- a/api_docs/v1/HostMapWidgetDefinitionStyle.md +++ b/api_docs/v1/HostMapWidgetDefinitionStyle.md @@ -3,6 +3,7 @@ # HostMapWidgetDefinitionStyle The style to apply to the widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HostMeta.md b/api_docs/v1/HostMeta.md index 249c3883dba..7aa4458d4d9 100644 --- a/api_docs/v1/HostMeta.md +++ b/api_docs/v1/HostMeta.md @@ -3,6 +3,7 @@ # HostMeta Metadata associated with your host. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HostMetrics.md b/api_docs/v1/HostMetrics.md index 4d002bbe2f6..ceb57a3e1aa 100644 --- a/api_docs/v1/HostMetrics.md +++ b/api_docs/v1/HostMetrics.md @@ -3,6 +3,7 @@ # HostMetrics Host Metrics collected. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HostMuteResponse.md b/api_docs/v1/HostMuteResponse.md index 55e6b002386..19c4e085dd1 100644 --- a/api_docs/v1/HostMuteResponse.md +++ b/api_docs/v1/HostMuteResponse.md @@ -3,6 +3,7 @@ # HostMuteResponse Response with the list of muted host for your organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HostMuteSettings.md b/api_docs/v1/HostMuteSettings.md index 1a8ace227bb..993c63a30ad 100644 --- a/api_docs/v1/HostMuteSettings.md +++ b/api_docs/v1/HostMuteSettings.md @@ -3,6 +3,7 @@ # HostMuteSettings Combination of settings to mute a host. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HostTags.md b/api_docs/v1/HostTags.md index cfa226c2cdd..4269849b570 100644 --- a/api_docs/v1/HostTags.md +++ b/api_docs/v1/HostTags.md @@ -3,6 +3,7 @@ # HostTags Set of tags to associate with your host. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/HostTotals.md b/api_docs/v1/HostTotals.md index c58ddbf19c9..3c6766767a5 100644 --- a/api_docs/v1/HostTotals.md +++ b/api_docs/v1/HostTotals.md @@ -3,6 +3,7 @@ # HostTotals Total number of host currently monitored by Datadog. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/IFrameWidgetDefinition.md b/api_docs/v1/IFrameWidgetDefinition.md index 43322480078..5cfb4803326 100644 --- a/api_docs/v1/IFrameWidgetDefinition.md +++ b/api_docs/v1/IFrameWidgetDefinition.md @@ -3,6 +3,7 @@ # IFrameWidgetDefinition The iframe widget allows you to embed a portion of any other web page on your dashboard. Only available on FREE layout dashboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/IPPrefixesAPI.md b/api_docs/v1/IPPrefixesAPI.md index 7b530d7f252..e050138046e 100644 --- a/api_docs/v1/IPPrefixesAPI.md +++ b/api_docs/v1/IPPrefixesAPI.md @@ -3,6 +3,7 @@ # IPPrefixesAPI Available prefix information for the API endpoints. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/IPPrefixesAPM.md b/api_docs/v1/IPPrefixesAPM.md index c057d57febf..5d3e3461635 100644 --- a/api_docs/v1/IPPrefixesAPM.md +++ b/api_docs/v1/IPPrefixesAPM.md @@ -3,6 +3,7 @@ # IPPrefixesAPM Available prefix information for the APM endpoints. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/IPPrefixesAgents.md b/api_docs/v1/IPPrefixesAgents.md index 70aeda162bf..bcd444408e7 100644 --- a/api_docs/v1/IPPrefixesAgents.md +++ b/api_docs/v1/IPPrefixesAgents.md @@ -3,6 +3,7 @@ # IPPrefixesAgents Available prefix information for the Agent endpoints. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/IPPrefixesLogs.md b/api_docs/v1/IPPrefixesLogs.md index c2ad0402f6b..d6f9da973c8 100644 --- a/api_docs/v1/IPPrefixesLogs.md +++ b/api_docs/v1/IPPrefixesLogs.md @@ -3,6 +3,7 @@ # IPPrefixesLogs Available prefix information for the Logs endpoints. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/IPPrefixesProcess.md b/api_docs/v1/IPPrefixesProcess.md index 63ffd712e3d..d027390e601 100644 --- a/api_docs/v1/IPPrefixesProcess.md +++ b/api_docs/v1/IPPrefixesProcess.md @@ -3,6 +3,7 @@ # IPPrefixesProcess Available prefix information for the Process endpoints. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/IPPrefixesSynthetics.md b/api_docs/v1/IPPrefixesSynthetics.md index 5fd570a8f5a..8e6f69390d0 100644 --- a/api_docs/v1/IPPrefixesSynthetics.md +++ b/api_docs/v1/IPPrefixesSynthetics.md @@ -3,6 +3,7 @@ # IPPrefixesSynthetics Available prefix information for the Synthetics endpoints. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/IPPrefixesWebhooks.md b/api_docs/v1/IPPrefixesWebhooks.md index 239b5b85a3a..f670bc6fb35 100644 --- a/api_docs/v1/IPPrefixesWebhooks.md +++ b/api_docs/v1/IPPrefixesWebhooks.md @@ -3,6 +3,7 @@ # IPPrefixesWebhooks Available prefix information for the Webhook endpoints. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/IPRanges.md b/api_docs/v1/IPRanges.md index 26ed8e10eb5..5c5603cee85 100644 --- a/api_docs/v1/IPRanges.md +++ b/api_docs/v1/IPRanges.md @@ -3,6 +3,7 @@ # IPRanges IP ranges. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/IdpFormData.md b/api_docs/v1/IdpFormData.md index f3709b29cd4..e05407bbf92 100644 --- a/api_docs/v1/IdpFormData.md +++ b/api_docs/v1/IdpFormData.md @@ -3,6 +3,7 @@ # IdpFormData Object describing the IdP configuration. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/IdpResponse.md b/api_docs/v1/IdpResponse.md index d83b3e9d2fd..c6408fcae71 100644 --- a/api_docs/v1/IdpResponse.md +++ b/api_docs/v1/IdpResponse.md @@ -3,6 +3,7 @@ # IdpResponse The IdP response object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ImageWidgetDefinition.md b/api_docs/v1/ImageWidgetDefinition.md index f05493fa8cd..696548a0732 100644 --- a/api_docs/v1/ImageWidgetDefinition.md +++ b/api_docs/v1/ImageWidgetDefinition.md @@ -3,6 +3,7 @@ # ImageWidgetDefinition The image widget allows you to embed an image on your dashboard. An image can be a PNG, JPG, or animated GIF. Only available on FREE layout dashboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/Log.md b/api_docs/v1/Log.md index 631497cb1e1..a57e44e3aa4 100644 --- a/api_docs/v1/Log.md +++ b/api_docs/v1/Log.md @@ -3,6 +3,7 @@ # Log Object describing a log after being processed and stored by Datadog. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogContent.md b/api_docs/v1/LogContent.md index 2b2ab7f5537..3dde2a06f7f 100644 --- a/api_docs/v1/LogContent.md +++ b/api_docs/v1/LogContent.md @@ -3,6 +3,7 @@ # LogContent JSON object containing all log attributes and their associated values. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogQueryDefinition.md b/api_docs/v1/LogQueryDefinition.md index 4125a51b32f..1a1095dc071 100644 --- a/api_docs/v1/LogQueryDefinition.md +++ b/api_docs/v1/LogQueryDefinition.md @@ -3,6 +3,7 @@ # LogQueryDefinition The log query. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogQueryDefinitionGroupBy.md b/api_docs/v1/LogQueryDefinitionGroupBy.md index 7aaf757a612..803ac50f181 100644 --- a/api_docs/v1/LogQueryDefinitionGroupBy.md +++ b/api_docs/v1/LogQueryDefinitionGroupBy.md @@ -3,6 +3,7 @@ # LogQueryDefinitionGroupBy Defined items in the group. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogQueryDefinitionGroupBySort.md b/api_docs/v1/LogQueryDefinitionGroupBySort.md index 5bdfc63238e..f89f49693e2 100644 --- a/api_docs/v1/LogQueryDefinitionGroupBySort.md +++ b/api_docs/v1/LogQueryDefinitionGroupBySort.md @@ -3,6 +3,7 @@ # LogQueryDefinitionGroupBySort Define a sorting method. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogQueryDefinitionSearch.md b/api_docs/v1/LogQueryDefinitionSearch.md index ffbaf40fe29..3769bf054b1 100644 --- a/api_docs/v1/LogQueryDefinitionSearch.md +++ b/api_docs/v1/LogQueryDefinitionSearch.md @@ -3,6 +3,7 @@ # LogQueryDefinitionSearch The query being made on the logs. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogStreamWidgetDefinition.md b/api_docs/v1/LogStreamWidgetDefinition.md index bbaab18adfb..a17c785e2a5 100644 --- a/api_docs/v1/LogStreamWidgetDefinition.md +++ b/api_docs/v1/LogStreamWidgetDefinition.md @@ -3,6 +3,7 @@ # LogStreamWidgetDefinition The Log Stream displays a log flow matching the defined query. Only available on FREE layout dashboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsAPIError.md b/api_docs/v1/LogsAPIError.md index 1dd3c2c1d00..f63e14e9b52 100644 --- a/api_docs/v1/LogsAPIError.md +++ b/api_docs/v1/LogsAPIError.md @@ -3,6 +3,7 @@ # LogsAPIError Error returned by the Logs API + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsAPIErrorResponse.md b/api_docs/v1/LogsAPIErrorResponse.md index e78676f1222..7082a252133 100644 --- a/api_docs/v1/LogsAPIErrorResponse.md +++ b/api_docs/v1/LogsAPIErrorResponse.md @@ -3,6 +3,7 @@ # LogsAPIErrorResponse Response returned by the Logs API when errors occur. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsArithmeticProcessor.md b/api_docs/v1/LogsArithmeticProcessor.md index d9c8a229c6b..107d23388a5 100644 --- a/api_docs/v1/LogsArithmeticProcessor.md +++ b/api_docs/v1/LogsArithmeticProcessor.md @@ -3,6 +3,7 @@ # LogsArithmeticProcessor Use the Arithmetic Processor to add a new attribute (without spaces or special characters in the new attribute name) to a log with the result of the provided formula. This enables you to remap different time attributes with different units into a single attribute, or to compute operations on attributes within the same log. The formula can use parentheses and the basic arithmetic operators `-`, `+`, `*`, `/`. By default, the calculation is skipped if an attribute is missing. Select “Replace missing attribute by 0” to automatically populate missing attribute values with 0 to ensure that the calculation is done. An attribute is missing if it is not found in the log attributes, or if it cannot be converted to a number. *Notes*: - The operator `-` needs to be space split in the formula as it can also be contained in attribute names. - If the target attribute already exists, it is overwritten by the result of the formula. - Results are rounded up to the 9th decimal. For example, if the result of the formula is `0.1234567891`, the actual value stored for the attribute is `0.123456789`. - If you need to scale a unit of measure, see [Scale Filter](https://docs.datadoghq.com/logs/processing/parsing/?tab=filter#matcher-and-filter). + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsAttributeRemapper.md b/api_docs/v1/LogsAttributeRemapper.md index cc5c151e341..fb1b96433db 100644 --- a/api_docs/v1/LogsAttributeRemapper.md +++ b/api_docs/v1/LogsAttributeRemapper.md @@ -3,6 +3,7 @@ # LogsAttributeRemapper The remapper processor remaps any source attribute(s) or tag to another target attribute or tag. Constraints on the tag/attribute name are explained in the [Tag Best Practice documentation](https://docs.datadoghq.com/logs/guide/log-parsing-best-practice). Some additional constraints are applied as `:` or `,` are not allowed in the target tag/attribute name. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsCategoryProcessor.md b/api_docs/v1/LogsCategoryProcessor.md index 0a16c2f6c04..d0e7b37730a 100644 --- a/api_docs/v1/LogsCategoryProcessor.md +++ b/api_docs/v1/LogsCategoryProcessor.md @@ -3,6 +3,7 @@ # LogsCategoryProcessor Use the Category Processor to add a new attribute (without spaces or special characters in the new attribute name) to a log matching a provided search query. Use categories to create groups for an analytical view. For example, URL groups, machine groups, environments, and response time buckets. **Notes**: - The syntax of the query is the one of Logs Explorer search bar. The query can be done on any log attribute or tag, whether it is a facet or not. Wildcards can also be used inside your query. - Once the log has matched one of the Processor queries, it stops. Make sure they are properly ordered in case a log could match several queries. - The names of the categories must be unique. - Once defined in the Category Processor, you can map categories to log status using the Log Status Remapper. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsCategoryProcessorCategory.md b/api_docs/v1/LogsCategoryProcessorCategory.md index 978d8acb3a3..fb1483ff036 100644 --- a/api_docs/v1/LogsCategoryProcessorCategory.md +++ b/api_docs/v1/LogsCategoryProcessorCategory.md @@ -3,6 +3,7 @@ # LogsCategoryProcessorCategory Object describing the logs filter. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsDateRemapper.md b/api_docs/v1/LogsDateRemapper.md index 04611a3aea0..ff18263471c 100644 --- a/api_docs/v1/LogsDateRemapper.md +++ b/api_docs/v1/LogsDateRemapper.md @@ -3,6 +3,7 @@ # LogsDateRemapper As Datadog receives logs, it timestamps them using the value(s) from any of these default attributes. - `timestamp` - `date` - `_timestamp` - `Timestamp` - `eventTime` - `published_date` If your logs put their dates in an attribute not in this list, use the log date Remapper Processor to define their date attribute as the official log timestamp. The recognized date formats are ISO8601, UNIX (the milliseconds EPOCH format), and RFC3164. **Note:** If your logs don’t contain any of the default attributes and you haven’t defined your own date attribute, Datadog timestamps the logs with the date it received them. If multiple log date remapper processors can be applied to a given log, only the first one (according to the pipelines order) is taken into account. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsExclusion.md b/api_docs/v1/LogsExclusion.md index b58abbd939a..6a6c5bb8aae 100644 --- a/api_docs/v1/LogsExclusion.md +++ b/api_docs/v1/LogsExclusion.md @@ -3,6 +3,7 @@ # LogsExclusion Represents the index exclusion filter object from configuration API. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsExclusionFilter.md b/api_docs/v1/LogsExclusionFilter.md index 5d17d667335..0a2b7c52e27 100644 --- a/api_docs/v1/LogsExclusionFilter.md +++ b/api_docs/v1/LogsExclusionFilter.md @@ -3,6 +3,7 @@ # LogsExclusionFilter Exclusion filter is defined by a query, a sampling rule, and a active/inactive toggle. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsFilter.md b/api_docs/v1/LogsFilter.md index ca733d73e09..3c384c93e4b 100644 --- a/api_docs/v1/LogsFilter.md +++ b/api_docs/v1/LogsFilter.md @@ -3,6 +3,7 @@ # LogsFilter Filter for logs. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsGeoIPParser.md b/api_docs/v1/LogsGeoIPParser.md index c673ca57070..baf55997720 100644 --- a/api_docs/v1/LogsGeoIPParser.md +++ b/api_docs/v1/LogsGeoIPParser.md @@ -3,6 +3,7 @@ # LogsGeoIPParser The GeoIP parser takes an IP address attribute and extracts if available the Continent, Country, Subdivision, and City information in the target attribute path. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsGrokParser.md b/api_docs/v1/LogsGrokParser.md index 329de061676..9916ed946c5 100644 --- a/api_docs/v1/LogsGrokParser.md +++ b/api_docs/v1/LogsGrokParser.md @@ -3,6 +3,7 @@ # LogsGrokParser Create custom grok rules to parse the full message or [a specific attribute of your raw event](https://docs.datadoghq.com/logs/processing/parsing/#advanced-settings). For more information, see the [parsing section](https://docs.datadoghq.com/logs/processing/parsing). + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsGrokParserRules.md b/api_docs/v1/LogsGrokParserRules.md index 1a5eb6ea76d..f0d06046be4 100644 --- a/api_docs/v1/LogsGrokParserRules.md +++ b/api_docs/v1/LogsGrokParserRules.md @@ -3,6 +3,7 @@ # LogsGrokParserRules Set of rules for the grok parser. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsIndex.md b/api_docs/v1/LogsIndex.md index 390c69a7ae3..a71f38c9022 100644 --- a/api_docs/v1/LogsIndex.md +++ b/api_docs/v1/LogsIndex.md @@ -3,6 +3,7 @@ # LogsIndex Object describing a Datadog Log index. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsIndexListResponse.md b/api_docs/v1/LogsIndexListResponse.md index 3175263df99..3f1041e7a71 100644 --- a/api_docs/v1/LogsIndexListResponse.md +++ b/api_docs/v1/LogsIndexListResponse.md @@ -3,6 +3,7 @@ # LogsIndexListResponse Object with all Index configurations for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsIndexUpdateRequest.md b/api_docs/v1/LogsIndexUpdateRequest.md index 09074fa4962..4ed902da0e9 100644 --- a/api_docs/v1/LogsIndexUpdateRequest.md +++ b/api_docs/v1/LogsIndexUpdateRequest.md @@ -3,6 +3,7 @@ # LogsIndexUpdateRequest Object for updating a Datadog Log index. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsIndexesOrder.md b/api_docs/v1/LogsIndexesOrder.md index 95d23cf0f53..f53770f3198 100644 --- a/api_docs/v1/LogsIndexesOrder.md +++ b/api_docs/v1/LogsIndexesOrder.md @@ -3,6 +3,7 @@ # LogsIndexesOrder Object containing the ordered list of log index names. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsListRequest.md b/api_docs/v1/LogsListRequest.md index 2af5c8a46e8..8c791354a17 100644 --- a/api_docs/v1/LogsListRequest.md +++ b/api_docs/v1/LogsListRequest.md @@ -3,6 +3,7 @@ # LogsListRequest Object to send with the request to retrieve a list of logs from your Organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsListRequestTime.md b/api_docs/v1/LogsListRequestTime.md index 8012844b9fb..b8a0a266b0b 100644 --- a/api_docs/v1/LogsListRequestTime.md +++ b/api_docs/v1/LogsListRequestTime.md @@ -3,6 +3,7 @@ # LogsListRequestTime Timeframe to retrieve the log from. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsListResponse.md b/api_docs/v1/LogsListResponse.md index b17542d6d14..a76a5aee6a7 100644 --- a/api_docs/v1/LogsListResponse.md +++ b/api_docs/v1/LogsListResponse.md @@ -3,6 +3,7 @@ # LogsListResponse Response object with all logs matching the request and pagination information. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsLookupProcessor.md b/api_docs/v1/LogsLookupProcessor.md index cd8faadee3a..c42cf4493a1 100644 --- a/api_docs/v1/LogsLookupProcessor.md +++ b/api_docs/v1/LogsLookupProcessor.md @@ -3,6 +3,7 @@ # LogsLookupProcessor Use the Lookup Processor to define a mapping between a log attribute and a human readable value saved in the processors mapping table. For example, you can use the Lookup Processor to map an internal service ID into a human readable service name. Alternatively, you could also use it to check if the MAC address that just attempted to connect to the production environment belongs to your list of stolen machines. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsMessageRemapper.md b/api_docs/v1/LogsMessageRemapper.md index a8aefff6f63..ad6ef93a6d6 100644 --- a/api_docs/v1/LogsMessageRemapper.md +++ b/api_docs/v1/LogsMessageRemapper.md @@ -3,6 +3,7 @@ # LogsMessageRemapper The message is a key attribute in Datadog. It is displayed in the message column of the Log Explorer and you can do full string search on it. Use this Processor to define one or more attributes as the official log message. **Note:** If multiple log message remapper processors can be applied to a given log, only the first one (according to the pipeline order) is taken into account. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsPipeline.md b/api_docs/v1/LogsPipeline.md index 07322c20618..0b3b9a42d95 100644 --- a/api_docs/v1/LogsPipeline.md +++ b/api_docs/v1/LogsPipeline.md @@ -3,6 +3,7 @@ # LogsPipeline Pipelines and processors operate on incoming logs, parsing and transforming them into structured attributes for easier querying. **Note**: These endpoints are only available for admin users. Make sure to use an application key created by an admin. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsPipelineProcessor.md b/api_docs/v1/LogsPipelineProcessor.md index 998522dd570..0295e7e662c 100644 --- a/api_docs/v1/LogsPipelineProcessor.md +++ b/api_docs/v1/LogsPipelineProcessor.md @@ -3,6 +3,7 @@ # LogsPipelineProcessor Nested Pipelines are pipelines within a pipeline. Use Nested Pipelines to split the processing into two steps. For example, first use a high-level filtering such as team and then a second level of filtering based on the integration, service, or any other tag or attribute. A pipeline can contain Nested Pipelines and Processors whereas a Nested Pipeline can only contain Processors. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsPipelinesOrder.md b/api_docs/v1/LogsPipelinesOrder.md index 94e4576b069..54b49edb273 100644 --- a/api_docs/v1/LogsPipelinesOrder.md +++ b/api_docs/v1/LogsPipelinesOrder.md @@ -3,6 +3,7 @@ # LogsPipelinesOrder Object containing the ordered list of pipeline IDs. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsQueryCompute.md b/api_docs/v1/LogsQueryCompute.md index 53157828c3d..aa2e310c942 100644 --- a/api_docs/v1/LogsQueryCompute.md +++ b/api_docs/v1/LogsQueryCompute.md @@ -3,6 +3,7 @@ # LogsQueryCompute Define computation for a log query. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsServiceRemapper.md b/api_docs/v1/LogsServiceRemapper.md index 82f6b2221d5..4e41f3888de 100644 --- a/api_docs/v1/LogsServiceRemapper.md +++ b/api_docs/v1/LogsServiceRemapper.md @@ -3,6 +3,7 @@ # LogsServiceRemapper Use this processor if you want to assign one or more attributes as the official service. **Note:** If multiple service remapper processors can be applied to a given log, only the first one (according to the pipeline order) is taken into account. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsStatusRemapper.md b/api_docs/v1/LogsStatusRemapper.md index e84d4fee9c9..2633c5ff996 100644 --- a/api_docs/v1/LogsStatusRemapper.md +++ b/api_docs/v1/LogsStatusRemapper.md @@ -3,6 +3,7 @@ # LogsStatusRemapper Use this Processor if you want to assign some attributes as the official status. Each incoming status value is mapped as follows. - Integers from 0 to 7 map to the Syslog severity standards - Strings beginning with `emerg` or f (case-insensitive) map to `emerg` (0) - Strings beginning with `a` (case-insensitive) map to `alert` (1) - Strings beginning with `c` (case-insensitive) map to `critical` (2) - Strings beginning with `err` (case-insensitive) map to `error` (3) - Strings beginning with `w` (case-insensitive) map to `warning` (4) - Strings beginning with `n` (case-insensitive) map to `notice` (5) - Strings beginning with `i` (case-insensitive) map to `info` (6) - Strings beginning with `d`, `trace` or `verbose` (case-insensitive) map to `debug` (7) - Strings beginning with `o` or matching `OK` or `Success` (case-insensitive) map to OK - All others map to `info` (6) **Note:** If multiple log status remapper processors can be applied to a given log, only the first one (according to the pipelines order) is taken into account. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsStringBuilderProcessor.md b/api_docs/v1/LogsStringBuilderProcessor.md index e2d95bc3145..18884d95ad6 100644 --- a/api_docs/v1/LogsStringBuilderProcessor.md +++ b/api_docs/v1/LogsStringBuilderProcessor.md @@ -3,6 +3,7 @@ # LogsStringBuilderProcessor Use the string builder processor to add a new attribute (without spaces or special characters) to a log with the result of the provided template. This enables aggregation of different attributes or raw strings into a single attribute. The template is defined by both raw text and blocks with the syntax `%{attribute_path}`. **Notes**: - The processor only accepts attributes with values or an array of values in the blocks. - If an attribute cannot be used (object or array of object), it is replaced by an empty string or the entire operation is skipped depending on your selection. - If the target attribute already exists, it is overwritten by the result of the template. - Results of the template cannot exceed 256 characters. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsTraceRemapper.md b/api_docs/v1/LogsTraceRemapper.md index efb6beb37c8..1ac427f9205 100644 --- a/api_docs/v1/LogsTraceRemapper.md +++ b/api_docs/v1/LogsTraceRemapper.md @@ -3,6 +3,7 @@ # LogsTraceRemapper There are two ways to improve correlation between application traces and logs. 1. Follow the documentation on [how to inject a trace ID in the application logs](https://docs.datadoghq.com/tracing/connect_logs_and_traces) and by default log integrations take care of all the rest of the setup. 2. Use the Trace remapper processor to define a log attribute as its associated trace ID. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsURLParser.md b/api_docs/v1/LogsURLParser.md index 2008799fe6f..0ead37c9d39 100644 --- a/api_docs/v1/LogsURLParser.md +++ b/api_docs/v1/LogsURLParser.md @@ -3,6 +3,7 @@ # LogsURLParser This processor extracts query parameters and other important parameters from a URL. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/LogsUserAgentParser.md b/api_docs/v1/LogsUserAgentParser.md index 207e7723bb9..3159dd39c07 100644 --- a/api_docs/v1/LogsUserAgentParser.md +++ b/api_docs/v1/LogsUserAgentParser.md @@ -3,6 +3,7 @@ # LogsUserAgentParser The User-Agent parser takes a User-Agent attribute and extracts the OS, browser, device, and other user data. It recognizes major bots like the Google Bot, Yahoo Slurp, and Bing. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MetricMetadata.md b/api_docs/v1/MetricMetadata.md index 10ccc8911e0..61a6b8080f8 100644 --- a/api_docs/v1/MetricMetadata.md +++ b/api_docs/v1/MetricMetadata.md @@ -3,6 +3,7 @@ # MetricMetadata Object with all metric related metadata. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MetricSearchResponse.md b/api_docs/v1/MetricSearchResponse.md index ccde4dc52e4..b7680dce742 100644 --- a/api_docs/v1/MetricSearchResponse.md +++ b/api_docs/v1/MetricSearchResponse.md @@ -3,6 +3,7 @@ # MetricSearchResponse Object containing the list of metrics matching the search query. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MetricSearchResponseResults.md b/api_docs/v1/MetricSearchResponseResults.md index 9cdd82dbd8e..09e138f2e07 100644 --- a/api_docs/v1/MetricSearchResponseResults.md +++ b/api_docs/v1/MetricSearchResponseResults.md @@ -3,6 +3,7 @@ # MetricSearchResponseResults Search result. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MetricsListResponse.md b/api_docs/v1/MetricsListResponse.md index b9acb80ea32..47b63b9e7e8 100644 --- a/api_docs/v1/MetricsListResponse.md +++ b/api_docs/v1/MetricsListResponse.md @@ -3,6 +3,7 @@ # MetricsListResponse Object listing all metric names stored by Datadog since a given time. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MetricsQueryMetadata.md b/api_docs/v1/MetricsQueryMetadata.md index e1bfd9edc28..bed355e0589 100644 --- a/api_docs/v1/MetricsQueryMetadata.md +++ b/api_docs/v1/MetricsQueryMetadata.md @@ -3,6 +3,7 @@ # MetricsQueryMetadata Object containing all metric names returned and their associated metadata. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MetricsQueryResponse.md b/api_docs/v1/MetricsQueryResponse.md index 964e90d37af..fa6d0874f5a 100644 --- a/api_docs/v1/MetricsQueryResponse.md +++ b/api_docs/v1/MetricsQueryResponse.md @@ -3,6 +3,7 @@ # MetricsQueryResponse Response Object that includes your query and the list of metrics retrieved. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MetricsQueryUnit.md b/api_docs/v1/MetricsQueryUnit.md index c5b21d1abcb..c60898cbc51 100644 --- a/api_docs/v1/MetricsQueryUnit.md +++ b/api_docs/v1/MetricsQueryUnit.md @@ -3,6 +3,7 @@ # MetricsQueryUnit Object containing the metric unit family, scale factor, name, and short name. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/Monitor.md b/api_docs/v1/Monitor.md index d873154a5b2..4c5571fcdb1 100644 --- a/api_docs/v1/Monitor.md +++ b/api_docs/v1/Monitor.md @@ -3,6 +3,7 @@ # Monitor Object describing a monitor. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MonitorOptions.md b/api_docs/v1/MonitorOptions.md index 30f162fcdba..59172d50874 100644 --- a/api_docs/v1/MonitorOptions.md +++ b/api_docs/v1/MonitorOptions.md @@ -3,6 +3,7 @@ # MonitorOptions List of options associated with your monitor. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MonitorOptionsAggregation.md b/api_docs/v1/MonitorOptionsAggregation.md index 85c8926c69d..c7a08b487c3 100644 --- a/api_docs/v1/MonitorOptionsAggregation.md +++ b/api_docs/v1/MonitorOptionsAggregation.md @@ -3,6 +3,7 @@ # MonitorOptionsAggregation Type of aggregation performed in the monitor query. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MonitorState.md b/api_docs/v1/MonitorState.md index af18728b96b..1f494bddb78 100644 --- a/api_docs/v1/MonitorState.md +++ b/api_docs/v1/MonitorState.md @@ -3,6 +3,7 @@ # MonitorState Wrapper object with the different monitor states. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MonitorStateGroup.md b/api_docs/v1/MonitorStateGroup.md index b167f9dffdc..0ef8c1cfa11 100644 --- a/api_docs/v1/MonitorStateGroup.md +++ b/api_docs/v1/MonitorStateGroup.md @@ -3,6 +3,7 @@ # MonitorStateGroup Monitor state for a single group. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MonitorSummaryWidgetDefinition.md b/api_docs/v1/MonitorSummaryWidgetDefinition.md index 528cda09bbc..f066959ccf9 100644 --- a/api_docs/v1/MonitorSummaryWidgetDefinition.md +++ b/api_docs/v1/MonitorSummaryWidgetDefinition.md @@ -3,6 +3,7 @@ # MonitorSummaryWidgetDefinition The monitor summary widget displays a summary view of all your Datadog monitors, or a subset based on a query. Only available on FREE layout dashboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MonitorThresholdWindowOptions.md b/api_docs/v1/MonitorThresholdWindowOptions.md index f283ea7a9c8..e88a6d52ea6 100644 --- a/api_docs/v1/MonitorThresholdWindowOptions.md +++ b/api_docs/v1/MonitorThresholdWindowOptions.md @@ -3,6 +3,7 @@ # MonitorThresholdWindowOptions Alerting time window options. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MonitorThresholds.md b/api_docs/v1/MonitorThresholds.md index de71e034a3e..5d6d9820a39 100644 --- a/api_docs/v1/MonitorThresholds.md +++ b/api_docs/v1/MonitorThresholds.md @@ -3,6 +3,7 @@ # MonitorThresholds List of the different monitor threshold available. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/MonitorUpdateRequest.md b/api_docs/v1/MonitorUpdateRequest.md index 6f1362524f8..1e57e0487bc 100644 --- a/api_docs/v1/MonitorUpdateRequest.md +++ b/api_docs/v1/MonitorUpdateRequest.md @@ -3,6 +3,7 @@ # MonitorUpdateRequest Object describing a monitor update request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/NoteWidgetDefinition.md b/api_docs/v1/NoteWidgetDefinition.md index 14e2f0bd9d6..7aa3eb44a7f 100644 --- a/api_docs/v1/NoteWidgetDefinition.md +++ b/api_docs/v1/NoteWidgetDefinition.md @@ -3,6 +3,7 @@ # NoteWidgetDefinition The notes and links widget is similar to free text widget, but allows for more formatting options. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/Organization.md b/api_docs/v1/Organization.md index a200dbbc679..81c22b0a2e4 100644 --- a/api_docs/v1/Organization.md +++ b/api_docs/v1/Organization.md @@ -3,6 +3,7 @@ # Organization Create, edit, and manage organizations. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/OrganizationBilling.md b/api_docs/v1/OrganizationBilling.md index 21d9ba05593..d31317a59f0 100644 --- a/api_docs/v1/OrganizationBilling.md +++ b/api_docs/v1/OrganizationBilling.md @@ -3,6 +3,7 @@ # OrganizationBilling A JSON array of billing type. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/OrganizationCreateBody.md b/api_docs/v1/OrganizationCreateBody.md index bcfb477ba77..2fd5f374881 100644 --- a/api_docs/v1/OrganizationCreateBody.md +++ b/api_docs/v1/OrganizationCreateBody.md @@ -3,6 +3,7 @@ # OrganizationCreateBody Object describing an organization to create. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/OrganizationCreateResponse.md b/api_docs/v1/OrganizationCreateResponse.md index 53e20cf675a..4314b2f6c2a 100644 --- a/api_docs/v1/OrganizationCreateResponse.md +++ b/api_docs/v1/OrganizationCreateResponse.md @@ -3,6 +3,7 @@ # OrganizationCreateResponse Response object for an organization creation. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/OrganizationListResponse.md b/api_docs/v1/OrganizationListResponse.md index eba51c07bab..fc246b9187e 100644 --- a/api_docs/v1/OrganizationListResponse.md +++ b/api_docs/v1/OrganizationListResponse.md @@ -3,6 +3,7 @@ # OrganizationListResponse Response with the list of organizations. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/OrganizationResponse.md b/api_docs/v1/OrganizationResponse.md index e1236141cff..8d63bab5e7b 100644 --- a/api_docs/v1/OrganizationResponse.md +++ b/api_docs/v1/OrganizationResponse.md @@ -3,6 +3,7 @@ # OrganizationResponse Response with an organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/OrganizationSettings.md b/api_docs/v1/OrganizationSettings.md index fd5a6e0195a..8ef701f3339 100644 --- a/api_docs/v1/OrganizationSettings.md +++ b/api_docs/v1/OrganizationSettings.md @@ -3,6 +3,7 @@ # OrganizationSettings A JSON array of settings. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/OrganizationSettingsSaml.md b/api_docs/v1/OrganizationSettingsSaml.md index 73da4e87384..5520545a4c7 100644 --- a/api_docs/v1/OrganizationSettingsSaml.md +++ b/api_docs/v1/OrganizationSettingsSaml.md @@ -3,6 +3,7 @@ # OrganizationSettingsSaml Set the boolean property enabled to enable or disable single sign on with SAML. See the SAML documentation for more information about all SAML settings. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/OrganizationSettingsSamlAutocreateUsersDomains.md b/api_docs/v1/OrganizationSettingsSamlAutocreateUsersDomains.md index 47cf9235883..ae55953b67f 100644 --- a/api_docs/v1/OrganizationSettingsSamlAutocreateUsersDomains.md +++ b/api_docs/v1/OrganizationSettingsSamlAutocreateUsersDomains.md @@ -3,6 +3,7 @@ # OrganizationSettingsSamlAutocreateUsersDomains Has two properties, `enabled` (boolean) and `domains`, which is a list of domains without the @ symbol. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/OrganizationSettingsSamlIdpInitiatedLogin.md b/api_docs/v1/OrganizationSettingsSamlIdpInitiatedLogin.md index 4c40af16f1f..684ca33893b 100644 --- a/api_docs/v1/OrganizationSettingsSamlIdpInitiatedLogin.md +++ b/api_docs/v1/OrganizationSettingsSamlIdpInitiatedLogin.md @@ -3,6 +3,7 @@ # OrganizationSettingsSamlIdpInitiatedLogin Has one property enabled (boolean). + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/OrganizationSettingsSamlStrictMode.md b/api_docs/v1/OrganizationSettingsSamlStrictMode.md index 9cf9a1d3998..561f05d039e 100644 --- a/api_docs/v1/OrganizationSettingsSamlStrictMode.md +++ b/api_docs/v1/OrganizationSettingsSamlStrictMode.md @@ -3,6 +3,7 @@ # OrganizationSettingsSamlStrictMode Has one property enabled (boolean). + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/OrganizationSubscription.md b/api_docs/v1/OrganizationSubscription.md index 832b4a83515..e30264edf26 100644 --- a/api_docs/v1/OrganizationSubscription.md +++ b/api_docs/v1/OrganizationSubscription.md @@ -3,6 +3,7 @@ # OrganizationSubscription Subscription definition. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/PagerDutyService.md b/api_docs/v1/PagerDutyService.md index 01aa59f64a3..fed8aec255e 100644 --- a/api_docs/v1/PagerDutyService.md +++ b/api_docs/v1/PagerDutyService.md @@ -3,6 +3,7 @@ # PagerDutyService The PagerDuty service that is available for integration with Datadog. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/PagerDutyServiceKey.md b/api_docs/v1/PagerDutyServiceKey.md index fa82c8033b5..b10c8fe2d4c 100644 --- a/api_docs/v1/PagerDutyServiceKey.md +++ b/api_docs/v1/PagerDutyServiceKey.md @@ -3,6 +3,7 @@ # PagerDutyServiceKey PagerDuty service object key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/PagerDutyServiceName.md b/api_docs/v1/PagerDutyServiceName.md index f1dd19ad999..a01f00e05ef 100644 --- a/api_docs/v1/PagerDutyServiceName.md +++ b/api_docs/v1/PagerDutyServiceName.md @@ -3,6 +3,7 @@ # PagerDutyServiceName PagerDuty service object name. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ProcessQueryDefinition.md b/api_docs/v1/ProcessQueryDefinition.md index 2824e3a6b3e..2e395b0df93 100644 --- a/api_docs/v1/ProcessQueryDefinition.md +++ b/api_docs/v1/ProcessQueryDefinition.md @@ -3,6 +3,7 @@ # ProcessQueryDefinition The process query to use in the widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/QueryValueWidgetDefinition.md b/api_docs/v1/QueryValueWidgetDefinition.md index 5b2371fba5f..8cdcd9c7bba 100644 --- a/api_docs/v1/QueryValueWidgetDefinition.md +++ b/api_docs/v1/QueryValueWidgetDefinition.md @@ -3,6 +3,7 @@ # QueryValueWidgetDefinition Query values display the current value of a given metric, APM, or log query. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/QueryValueWidgetRequest.md b/api_docs/v1/QueryValueWidgetRequest.md index e7118a47697..802533dbca7 100644 --- a/api_docs/v1/QueryValueWidgetRequest.md +++ b/api_docs/v1/QueryValueWidgetRequest.md @@ -3,6 +3,7 @@ # QueryValueWidgetRequest Updated query value widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOBulkDeleteError.md b/api_docs/v1/SLOBulkDeleteError.md index 363eb4cf79d..23696818d22 100644 --- a/api_docs/v1/SLOBulkDeleteError.md +++ b/api_docs/v1/SLOBulkDeleteError.md @@ -3,6 +3,7 @@ # SLOBulkDeleteError Object describing the error. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOBulkDeleteResponse.md b/api_docs/v1/SLOBulkDeleteResponse.md index 827e82d82df..7545b98b81f 100644 --- a/api_docs/v1/SLOBulkDeleteResponse.md +++ b/api_docs/v1/SLOBulkDeleteResponse.md @@ -3,6 +3,7 @@ # SLOBulkDeleteResponse The bulk partial delete service level objective object endpoint response. This endpoint operates on multiple service level objective objects, so it may be partially successful. In such cases, the \"data\" and \"error\" fields in this response indicate which deletions succeeded and failed. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOBulkDeleteResponseData.md b/api_docs/v1/SLOBulkDeleteResponseData.md index c57e162e3d7..e37c2247508 100644 --- a/api_docs/v1/SLOBulkDeleteResponseData.md +++ b/api_docs/v1/SLOBulkDeleteResponseData.md @@ -3,6 +3,7 @@ # SLOBulkDeleteResponseData An array of service level objective objects. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOCorrection.md b/api_docs/v1/SLOCorrection.md index cdf89600851..af4289ee98b 100644 --- a/api_docs/v1/SLOCorrection.md +++ b/api_docs/v1/SLOCorrection.md @@ -3,6 +3,7 @@ # SLOCorrection The response object of a list of SLO corrections + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOCorrectionCreateData.md b/api_docs/v1/SLOCorrectionCreateData.md index deaa00cfdc7..3f6a93db9eb 100644 --- a/api_docs/v1/SLOCorrectionCreateData.md +++ b/api_docs/v1/SLOCorrectionCreateData.md @@ -3,6 +3,7 @@ # SLOCorrectionCreateData The data object associated with the SLO correction to be created + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOCorrectionCreateRequest.md b/api_docs/v1/SLOCorrectionCreateRequest.md index 5f15c1ae61e..4cab40a629b 100644 --- a/api_docs/v1/SLOCorrectionCreateRequest.md +++ b/api_docs/v1/SLOCorrectionCreateRequest.md @@ -3,6 +3,7 @@ # SLOCorrectionCreateRequest An object that defines a correction to be applied to an SLO + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOCorrectionCreateRequestAttributes.md b/api_docs/v1/SLOCorrectionCreateRequestAttributes.md index 9adaabba9c4..435584cf174 100644 --- a/api_docs/v1/SLOCorrectionCreateRequestAttributes.md +++ b/api_docs/v1/SLOCorrectionCreateRequestAttributes.md @@ -3,6 +3,7 @@ # SLOCorrectionCreateRequestAttributes The attribute object associated with the SLO correction to be created + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOCorrectionListResponse.md b/api_docs/v1/SLOCorrectionListResponse.md index 0a88d1837eb..804db15fdc0 100644 --- a/api_docs/v1/SLOCorrectionListResponse.md +++ b/api_docs/v1/SLOCorrectionListResponse.md @@ -3,6 +3,7 @@ # SLOCorrectionListResponse A list of SLO correction objects + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOCorrectionResponse.md b/api_docs/v1/SLOCorrectionResponse.md index 74c929cd317..48c3824e720 100644 --- a/api_docs/v1/SLOCorrectionResponse.md +++ b/api_docs/v1/SLOCorrectionResponse.md @@ -3,6 +3,7 @@ # SLOCorrectionResponse The response object of an SLO correction + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOCorrectionResponseAttributes.md b/api_docs/v1/SLOCorrectionResponseAttributes.md index e5aabfc797c..24a711e6eb8 100644 --- a/api_docs/v1/SLOCorrectionResponseAttributes.md +++ b/api_docs/v1/SLOCorrectionResponseAttributes.md @@ -3,6 +3,7 @@ # SLOCorrectionResponseAttributes The attribute object associated with the SLO correction + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOCorrectionUpdateData.md b/api_docs/v1/SLOCorrectionUpdateData.md index a2b3d8e445e..0a182b9837e 100644 --- a/api_docs/v1/SLOCorrectionUpdateData.md +++ b/api_docs/v1/SLOCorrectionUpdateData.md @@ -3,6 +3,7 @@ # SLOCorrectionUpdateData The data object associated with the SLO correction to be updated + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOCorrectionUpdateRequest.md b/api_docs/v1/SLOCorrectionUpdateRequest.md index 4391f2c7600..144112eede9 100644 --- a/api_docs/v1/SLOCorrectionUpdateRequest.md +++ b/api_docs/v1/SLOCorrectionUpdateRequest.md @@ -3,6 +3,7 @@ # SLOCorrectionUpdateRequest An object that defines a correction to be applied to an SLO + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOCorrectionUpdateRequestAttributes.md b/api_docs/v1/SLOCorrectionUpdateRequestAttributes.md index 591551dc46a..d52afc4f611 100644 --- a/api_docs/v1/SLOCorrectionUpdateRequestAttributes.md +++ b/api_docs/v1/SLOCorrectionUpdateRequestAttributes.md @@ -3,6 +3,7 @@ # SLOCorrectionUpdateRequestAttributes The attribute object associated with the SLO correction to be updated + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLODeleteResponse.md b/api_docs/v1/SLODeleteResponse.md index f80323b16d4..61d2936f9f0 100644 --- a/api_docs/v1/SLODeleteResponse.md +++ b/api_docs/v1/SLODeleteResponse.md @@ -3,6 +3,7 @@ # SLODeleteResponse A response list of all service level objective deleted. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOHistoryMetrics.md b/api_docs/v1/SLOHistoryMetrics.md index 7dd373a2819..6ce4db8f207 100644 --- a/api_docs/v1/SLOHistoryMetrics.md +++ b/api_docs/v1/SLOHistoryMetrics.md @@ -3,6 +3,7 @@ # SLOHistoryMetrics A `metric` based SLO history response. This is not included in responses for `monitor` based SLOs. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOHistoryMetricsSeries.md b/api_docs/v1/SLOHistoryMetricsSeries.md index d0035dfa0de..67ad0daa1f0 100644 --- a/api_docs/v1/SLOHistoryMetricsSeries.md +++ b/api_docs/v1/SLOHistoryMetricsSeries.md @@ -3,6 +3,7 @@ # SLOHistoryMetricsSeries A representation of `metric` based SLO time series for the provided queries. This is the same response type from `batch_query` endpoint. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOHistoryMetricsSeriesMetadata.md b/api_docs/v1/SLOHistoryMetricsSeriesMetadata.md index 4c99cec9294..8e3eddb1a38 100644 --- a/api_docs/v1/SLOHistoryMetricsSeriesMetadata.md +++ b/api_docs/v1/SLOHistoryMetricsSeriesMetadata.md @@ -3,6 +3,7 @@ # SLOHistoryMetricsSeriesMetadata Query metadata. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOHistoryMetricsSeriesMetadataUnit.md b/api_docs/v1/SLOHistoryMetricsSeriesMetadataUnit.md index d11744b5813..eb9bcc2bd38 100644 --- a/api_docs/v1/SLOHistoryMetricsSeriesMetadataUnit.md +++ b/api_docs/v1/SLOHistoryMetricsSeriesMetadataUnit.md @@ -3,6 +3,7 @@ # SLOHistoryMetricsSeriesMetadataUnit An Object of metric units. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOHistoryResponse.md b/api_docs/v1/SLOHistoryResponse.md index 7b8da4cf522..aeef34101e7 100644 --- a/api_docs/v1/SLOHistoryResponse.md +++ b/api_docs/v1/SLOHistoryResponse.md @@ -3,6 +3,7 @@ # SLOHistoryResponse A service level objective history response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOHistoryResponseData.md b/api_docs/v1/SLOHistoryResponseData.md index b934fa0b0f8..9da6dbb24ad 100644 --- a/api_docs/v1/SLOHistoryResponseData.md +++ b/api_docs/v1/SLOHistoryResponseData.md @@ -3,6 +3,7 @@ # SLOHistoryResponseData An array of service level objective objects. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOHistoryResponseError.md b/api_docs/v1/SLOHistoryResponseError.md index c5e4184b21f..1b797dc0eb0 100644 --- a/api_docs/v1/SLOHistoryResponseError.md +++ b/api_docs/v1/SLOHistoryResponseError.md @@ -3,6 +3,7 @@ # SLOHistoryResponseError A service level objective response containing the requested history. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOHistorySLIData.md b/api_docs/v1/SLOHistorySLIData.md index da0851e0111..abd092acc37 100644 --- a/api_docs/v1/SLOHistorySLIData.md +++ b/api_docs/v1/SLOHistorySLIData.md @@ -3,6 +3,7 @@ # SLOHistorySLIData An object that holds an SLI value and its associated data. It can represent an SLO's overall SLI value. This can also represent the SLI value for a specific monitor in multi-monitor SLOs, or a group in grouped SLOs. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOListResponse.md b/api_docs/v1/SLOListResponse.md index 9bc8900c295..cd9a89de7b0 100644 --- a/api_docs/v1/SLOListResponse.md +++ b/api_docs/v1/SLOListResponse.md @@ -3,6 +3,7 @@ # SLOListResponse A response with one or more service level objective. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOResponse.md b/api_docs/v1/SLOResponse.md index 979b611e8bb..489bf084f6b 100644 --- a/api_docs/v1/SLOResponse.md +++ b/api_docs/v1/SLOResponse.md @@ -3,6 +3,7 @@ # SLOResponse A service level objective response containing a single service level objective. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOThreshold.md b/api_docs/v1/SLOThreshold.md index 12c7f9e0027..71c0e9db0cb 100644 --- a/api_docs/v1/SLOThreshold.md +++ b/api_docs/v1/SLOThreshold.md @@ -3,6 +3,7 @@ # SLOThreshold SLO thresholds (target and optionally warning) for a single time window. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SLOWidgetDefinition.md b/api_docs/v1/SLOWidgetDefinition.md index 050d9e32686..a3ab74178a2 100644 --- a/api_docs/v1/SLOWidgetDefinition.md +++ b/api_docs/v1/SLOWidgetDefinition.md @@ -3,6 +3,7 @@ # SLOWidgetDefinition Use the SLO and uptime widget to track your SLOs (Service Level Objectives) and uptime on screenboards and timeboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ScatterPlotRequest.md b/api_docs/v1/ScatterPlotRequest.md index e7daf79761f..c01a22c58aa 100644 --- a/api_docs/v1/ScatterPlotRequest.md +++ b/api_docs/v1/ScatterPlotRequest.md @@ -3,6 +3,7 @@ # ScatterPlotRequest Updated scatter plot. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ScatterPlotWidgetDefinition.md b/api_docs/v1/ScatterPlotWidgetDefinition.md index 72434a3c6e5..b2a6ddbf2c0 100644 --- a/api_docs/v1/ScatterPlotWidgetDefinition.md +++ b/api_docs/v1/ScatterPlotWidgetDefinition.md @@ -3,6 +3,7 @@ # ScatterPlotWidgetDefinition The scatter plot visualization allows you to graph a chosen scope over two different metrics with their respective aggregation. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ScatterPlotWidgetDefinitionRequests.md b/api_docs/v1/ScatterPlotWidgetDefinitionRequests.md index 895c0742ac3..1d7c205122c 100644 --- a/api_docs/v1/ScatterPlotWidgetDefinitionRequests.md +++ b/api_docs/v1/ScatterPlotWidgetDefinitionRequests.md @@ -3,6 +3,7 @@ # ScatterPlotWidgetDefinitionRequests Widget definition. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ServiceLevelObjective.md b/api_docs/v1/ServiceLevelObjective.md index f5ac024ef28..3a12c8e1634 100644 --- a/api_docs/v1/ServiceLevelObjective.md +++ b/api_docs/v1/ServiceLevelObjective.md @@ -3,6 +3,7 @@ # ServiceLevelObjective A service level objective object includes a service level indicator, thresholds for one or more timeframes, and metadata (`name`, `description`, `tags`, etc.). + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ServiceLevelObjectiveQuery.md b/api_docs/v1/ServiceLevelObjectiveQuery.md index 0b646128382..aa51a87db4d 100644 --- a/api_docs/v1/ServiceLevelObjectiveQuery.md +++ b/api_docs/v1/ServiceLevelObjectiveQuery.md @@ -3,6 +3,7 @@ # ServiceLevelObjectiveQuery A metric SLI query. **Required if type is `metric`**. Note that Datadog only allows the sum by aggregator to be used because this will sum up all request counts instead of averaging them, or taking the max or min of all of those requests. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ServiceLevelObjectiveRequest.md b/api_docs/v1/ServiceLevelObjectiveRequest.md index c5f2e460f1d..64dc3324100 100644 --- a/api_docs/v1/ServiceLevelObjectiveRequest.md +++ b/api_docs/v1/ServiceLevelObjectiveRequest.md @@ -3,6 +3,7 @@ # ServiceLevelObjectiveRequest A service level objective object includes a service level indicator, thresholds for one or more timeframes, and metadata (`name`, `description`, `tags`, etc.). + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ServiceMapWidgetDefinition.md b/api_docs/v1/ServiceMapWidgetDefinition.md index 7a3d45ea65d..d87917f72ef 100644 --- a/api_docs/v1/ServiceMapWidgetDefinition.md +++ b/api_docs/v1/ServiceMapWidgetDefinition.md @@ -3,6 +3,7 @@ # ServiceMapWidgetDefinition This widget displays a map of a service to all of the services that call it, and all of the services that it calls. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ServiceSummaryWidgetDefinition.md b/api_docs/v1/ServiceSummaryWidgetDefinition.md index 26dfe9d0d8b..9eeab40acd8 100644 --- a/api_docs/v1/ServiceSummaryWidgetDefinition.md +++ b/api_docs/v1/ServiceSummaryWidgetDefinition.md @@ -3,6 +3,7 @@ # ServiceSummaryWidgetDefinition The service summary displays the graphs of a chosen service in your screenboard. Only available on FREE layout dashboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SlackIntegrationChannel.md b/api_docs/v1/SlackIntegrationChannel.md index f1346f90db0..94fb1d59129 100644 --- a/api_docs/v1/SlackIntegrationChannel.md +++ b/api_docs/v1/SlackIntegrationChannel.md @@ -3,6 +3,7 @@ # SlackIntegrationChannel The Slack channel configuration. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SlackIntegrationChannelDisplay.md b/api_docs/v1/SlackIntegrationChannelDisplay.md index 1fb153f5425..8e2c12b1ba8 100644 --- a/api_docs/v1/SlackIntegrationChannelDisplay.md +++ b/api_docs/v1/SlackIntegrationChannelDisplay.md @@ -3,6 +3,7 @@ # SlackIntegrationChannelDisplay Configuration options for what is shown in an alert event message. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsAPIStep.md b/api_docs/v1/SyntheticsAPIStep.md index bb5878ff1f7..c7ecf766900 100644 --- a/api_docs/v1/SyntheticsAPIStep.md +++ b/api_docs/v1/SyntheticsAPIStep.md @@ -3,6 +3,7 @@ # SyntheticsAPIStep The steps used in a Synthetics multistep API test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsAPITest.md b/api_docs/v1/SyntheticsAPITest.md index a6eaed2461d..3aca4ef9837 100644 --- a/api_docs/v1/SyntheticsAPITest.md +++ b/api_docs/v1/SyntheticsAPITest.md @@ -3,6 +3,7 @@ # SyntheticsAPITest Object containing details about a Synthetic API test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsAPITestConfig.md b/api_docs/v1/SyntheticsAPITestConfig.md index 959fbcef660..4873319b49a 100644 --- a/api_docs/v1/SyntheticsAPITestConfig.md +++ b/api_docs/v1/SyntheticsAPITestConfig.md @@ -3,6 +3,7 @@ # SyntheticsAPITestConfig Configuration object for a Synthetic API test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsAPITestResultData.md b/api_docs/v1/SyntheticsAPITestResultData.md index 2f3c6a485c1..2c235a381e0 100644 --- a/api_docs/v1/SyntheticsAPITestResultData.md +++ b/api_docs/v1/SyntheticsAPITestResultData.md @@ -3,6 +3,7 @@ # SyntheticsAPITestResultData Object containing results for your Synthetic API test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsAPITestResultFull.md b/api_docs/v1/SyntheticsAPITestResultFull.md index 438536b0d5d..5de8778b897 100644 --- a/api_docs/v1/SyntheticsAPITestResultFull.md +++ b/api_docs/v1/SyntheticsAPITestResultFull.md @@ -3,6 +3,7 @@ # SyntheticsAPITestResultFull Object returned describing a API test result. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsAPITestResultFullCheck.md b/api_docs/v1/SyntheticsAPITestResultFullCheck.md index 3579b129662..a8a5341db68 100644 --- a/api_docs/v1/SyntheticsAPITestResultFullCheck.md +++ b/api_docs/v1/SyntheticsAPITestResultFullCheck.md @@ -3,6 +3,7 @@ # SyntheticsAPITestResultFullCheck Object describing the API test configuration. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsAPITestResultShort.md b/api_docs/v1/SyntheticsAPITestResultShort.md index fda828b3d2d..077047a920d 100644 --- a/api_docs/v1/SyntheticsAPITestResultShort.md +++ b/api_docs/v1/SyntheticsAPITestResultShort.md @@ -3,6 +3,7 @@ # SyntheticsAPITestResultShort Object with the results of a single Synthetic API test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsAPITestResultShortResult.md b/api_docs/v1/SyntheticsAPITestResultShortResult.md index bd1b6ffd030..f2e359f1af8 100644 --- a/api_docs/v1/SyntheticsAPITestResultShortResult.md +++ b/api_docs/v1/SyntheticsAPITestResultShortResult.md @@ -3,6 +3,7 @@ # SyntheticsAPITestResultShortResult Result of the last API test run. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsAssertionJSONPathTarget.md b/api_docs/v1/SyntheticsAssertionJSONPathTarget.md index 904abaebf59..919cc85e6f0 100644 --- a/api_docs/v1/SyntheticsAssertionJSONPathTarget.md +++ b/api_docs/v1/SyntheticsAssertionJSONPathTarget.md @@ -3,6 +3,7 @@ # SyntheticsAssertionJSONPathTarget An assertion for the `validatesJSONPath` operator. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsAssertionJSONPathTargetTarget.md b/api_docs/v1/SyntheticsAssertionJSONPathTargetTarget.md index 73831d88dce..8cd1eaab5d8 100644 --- a/api_docs/v1/SyntheticsAssertionJSONPathTargetTarget.md +++ b/api_docs/v1/SyntheticsAssertionJSONPathTargetTarget.md @@ -3,6 +3,7 @@ # SyntheticsAssertionJSONPathTargetTarget Composed target for `validatesJSONPath` operator. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsAssertionTarget.md b/api_docs/v1/SyntheticsAssertionTarget.md index f80d75ac39e..0cb7fc61a8b 100644 --- a/api_docs/v1/SyntheticsAssertionTarget.md +++ b/api_docs/v1/SyntheticsAssertionTarget.md @@ -3,6 +3,7 @@ # SyntheticsAssertionTarget An assertion which uses a simple target. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsBasicAuth.md b/api_docs/v1/SyntheticsBasicAuth.md index e50c39457f2..1a7c3fec19c 100644 --- a/api_docs/v1/SyntheticsBasicAuth.md +++ b/api_docs/v1/SyntheticsBasicAuth.md @@ -3,6 +3,7 @@ # SyntheticsBasicAuth Object to handle basic authentication when performing the test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsBrowserError.md b/api_docs/v1/SyntheticsBrowserError.md index 51d0db687ad..ff92b42e9f6 100644 --- a/api_docs/v1/SyntheticsBrowserError.md +++ b/api_docs/v1/SyntheticsBrowserError.md @@ -3,6 +3,7 @@ # SyntheticsBrowserError Error response object for a browser test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsBrowserTest.md b/api_docs/v1/SyntheticsBrowserTest.md index 7357163f188..899418b37e2 100644 --- a/api_docs/v1/SyntheticsBrowserTest.md +++ b/api_docs/v1/SyntheticsBrowserTest.md @@ -3,6 +3,7 @@ # SyntheticsBrowserTest Object containing details about a Synthetic browser test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsBrowserTestConfig.md b/api_docs/v1/SyntheticsBrowserTestConfig.md index 08627481b9b..d3c1cc4f5cb 100644 --- a/api_docs/v1/SyntheticsBrowserTestConfig.md +++ b/api_docs/v1/SyntheticsBrowserTestConfig.md @@ -3,6 +3,7 @@ # SyntheticsBrowserTestConfig Configuration object for a Synthetic browser test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsBrowserTestResultData.md b/api_docs/v1/SyntheticsBrowserTestResultData.md index 86274388bc5..1afd3610cb4 100644 --- a/api_docs/v1/SyntheticsBrowserTestResultData.md +++ b/api_docs/v1/SyntheticsBrowserTestResultData.md @@ -3,6 +3,7 @@ # SyntheticsBrowserTestResultData Object containing results for your Synthetic browser test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsBrowserTestResultFull.md b/api_docs/v1/SyntheticsBrowserTestResultFull.md index 6fbc6044db9..138fb325a27 100644 --- a/api_docs/v1/SyntheticsBrowserTestResultFull.md +++ b/api_docs/v1/SyntheticsBrowserTestResultFull.md @@ -3,6 +3,7 @@ # SyntheticsBrowserTestResultFull Object returned describing a browser test result. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsBrowserTestResultFullCheck.md b/api_docs/v1/SyntheticsBrowserTestResultFullCheck.md index 13bf1aaebe7..7fe39a913f4 100644 --- a/api_docs/v1/SyntheticsBrowserTestResultFullCheck.md +++ b/api_docs/v1/SyntheticsBrowserTestResultFullCheck.md @@ -3,6 +3,7 @@ # SyntheticsBrowserTestResultFullCheck Object describing the browser test configuration. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsBrowserTestResultShort.md b/api_docs/v1/SyntheticsBrowserTestResultShort.md index 7a0d6dff4d7..da0c9c2fc16 100644 --- a/api_docs/v1/SyntheticsBrowserTestResultShort.md +++ b/api_docs/v1/SyntheticsBrowserTestResultShort.md @@ -3,6 +3,7 @@ # SyntheticsBrowserTestResultShort Object with the results of a single Synthetic browser test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsBrowserTestResultShortResult.md b/api_docs/v1/SyntheticsBrowserTestResultShortResult.md index 8d13bd2d425..2a3542ff24c 100644 --- a/api_docs/v1/SyntheticsBrowserTestResultShortResult.md +++ b/api_docs/v1/SyntheticsBrowserTestResultShortResult.md @@ -3,6 +3,7 @@ # SyntheticsBrowserTestResultShortResult Object with the result of the last browser test run. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsBrowserVariable.md b/api_docs/v1/SyntheticsBrowserVariable.md index e667af65c3f..75d84d6f6df 100644 --- a/api_docs/v1/SyntheticsBrowserVariable.md +++ b/api_docs/v1/SyntheticsBrowserVariable.md @@ -3,6 +3,7 @@ # SyntheticsBrowserVariable Object defining a variable that can be used in your browser test. Learn more in the [Browser test Actions documentation](https://docs.datadoghq.com/synthetics/browser_tests/actions#variable). + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsCITest.md b/api_docs/v1/SyntheticsCITest.md index 9a75f3fd123..af1b78f3962 100644 --- a/api_docs/v1/SyntheticsCITest.md +++ b/api_docs/v1/SyntheticsCITest.md @@ -3,6 +3,7 @@ # SyntheticsCITest Test configuration for Synthetics CI + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsCITestBody.md b/api_docs/v1/SyntheticsCITestBody.md index dc81475542c..c371032b979 100644 --- a/api_docs/v1/SyntheticsCITestBody.md +++ b/api_docs/v1/SyntheticsCITestBody.md @@ -3,6 +3,7 @@ # SyntheticsCITestBody Object describing the synthetics tests to trigger. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsCITestMetadata.md b/api_docs/v1/SyntheticsCITestMetadata.md index e2410027aba..a74411be638 100644 --- a/api_docs/v1/SyntheticsCITestMetadata.md +++ b/api_docs/v1/SyntheticsCITestMetadata.md @@ -3,6 +3,7 @@ # SyntheticsCITestMetadata Metadata for the Synthetics tests run + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsCITestMetadataCi.md b/api_docs/v1/SyntheticsCITestMetadataCi.md index 92a6d2fd91d..8b357fdea2f 100644 --- a/api_docs/v1/SyntheticsCITestMetadataCi.md +++ b/api_docs/v1/SyntheticsCITestMetadataCi.md @@ -3,6 +3,7 @@ # SyntheticsCITestMetadataCi Describe CI provider. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsCITestMetadataGit.md b/api_docs/v1/SyntheticsCITestMetadataGit.md index c000d21275a..e3e22712284 100644 --- a/api_docs/v1/SyntheticsCITestMetadataGit.md +++ b/api_docs/v1/SyntheticsCITestMetadataGit.md @@ -3,6 +3,7 @@ # SyntheticsCITestMetadataGit Git information. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsConfigVariable.md b/api_docs/v1/SyntheticsConfigVariable.md index c2269508270..816d2d8e2d5 100644 --- a/api_docs/v1/SyntheticsConfigVariable.md +++ b/api_docs/v1/SyntheticsConfigVariable.md @@ -3,6 +3,7 @@ # SyntheticsConfigVariable Object defining a variable that can be used in your test configuration. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsCoreWebVitals.md b/api_docs/v1/SyntheticsCoreWebVitals.md index 90953a84c98..ab11bace7c3 100644 --- a/api_docs/v1/SyntheticsCoreWebVitals.md +++ b/api_docs/v1/SyntheticsCoreWebVitals.md @@ -3,6 +3,7 @@ # SyntheticsCoreWebVitals Core Web Vitals attached to a browser test step. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsDeleteTestsPayload.md b/api_docs/v1/SyntheticsDeleteTestsPayload.md index f155b428457..88edbefe049 100644 --- a/api_docs/v1/SyntheticsDeleteTestsPayload.md +++ b/api_docs/v1/SyntheticsDeleteTestsPayload.md @@ -3,6 +3,7 @@ # SyntheticsDeleteTestsPayload A JSON list of the ID or IDs of the Synthetic tests that you want to delete. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsDeleteTestsResponse.md b/api_docs/v1/SyntheticsDeleteTestsResponse.md index 9f19b82d694..a92b80383af 100644 --- a/api_docs/v1/SyntheticsDeleteTestsResponse.md +++ b/api_docs/v1/SyntheticsDeleteTestsResponse.md @@ -3,6 +3,7 @@ # SyntheticsDeleteTestsResponse Response object for deleting Synthetic tests. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsDeletedTest.md b/api_docs/v1/SyntheticsDeletedTest.md index 6b9c48b216c..31271765b3a 100644 --- a/api_docs/v1/SyntheticsDeletedTest.md +++ b/api_docs/v1/SyntheticsDeletedTest.md @@ -3,6 +3,7 @@ # SyntheticsDeletedTest Object containing a deleted Synthetic test ID with the associated deletion timestamp. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsDevice.md b/api_docs/v1/SyntheticsDevice.md index aec5d6ba47e..4c76c6df7c2 100644 --- a/api_docs/v1/SyntheticsDevice.md +++ b/api_docs/v1/SyntheticsDevice.md @@ -3,6 +3,7 @@ # SyntheticsDevice Object describing the device used to perform the Synthetic test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsGetAPITestLatestResultsResponse.md b/api_docs/v1/SyntheticsGetAPITestLatestResultsResponse.md index c9c062d1f76..03660876ba7 100644 --- a/api_docs/v1/SyntheticsGetAPITestLatestResultsResponse.md +++ b/api_docs/v1/SyntheticsGetAPITestLatestResultsResponse.md @@ -3,6 +3,7 @@ # SyntheticsGetAPITestLatestResultsResponse Object with the latest Synthetic API test run. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsGetBrowserTestLatestResultsResponse.md b/api_docs/v1/SyntheticsGetBrowserTestLatestResultsResponse.md index 02d0b9c7d53..391a9b9cc7f 100644 --- a/api_docs/v1/SyntheticsGetBrowserTestLatestResultsResponse.md +++ b/api_docs/v1/SyntheticsGetBrowserTestLatestResultsResponse.md @@ -3,6 +3,7 @@ # SyntheticsGetBrowserTestLatestResultsResponse Object with the latest Synthetic browser test run. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsGlobalVariable.md b/api_docs/v1/SyntheticsGlobalVariable.md index a41bbdf63e8..ce714fc3c9b 100644 --- a/api_docs/v1/SyntheticsGlobalVariable.md +++ b/api_docs/v1/SyntheticsGlobalVariable.md @@ -3,6 +3,7 @@ # SyntheticsGlobalVariable Synthetics global variable. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsGlobalVariableParseTestOptions.md b/api_docs/v1/SyntheticsGlobalVariableParseTestOptions.md index a8d0e62086b..fe7e410b497 100644 --- a/api_docs/v1/SyntheticsGlobalVariableParseTestOptions.md +++ b/api_docs/v1/SyntheticsGlobalVariableParseTestOptions.md @@ -3,6 +3,7 @@ # SyntheticsGlobalVariableParseTestOptions Parser options to use for retrieving a Synthetics global variable from a Synthetics Test. Used in conjunction with `parse_test_public_id`. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsGlobalVariableValue.md b/api_docs/v1/SyntheticsGlobalVariableValue.md index ad669ef9f94..c2a98a80bc9 100644 --- a/api_docs/v1/SyntheticsGlobalVariableValue.md +++ b/api_docs/v1/SyntheticsGlobalVariableValue.md @@ -3,6 +3,7 @@ # SyntheticsGlobalVariableValue Value of the global variable. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsListTestsResponse.md b/api_docs/v1/SyntheticsListTestsResponse.md index 2fb4cd82cc3..b53d87aa6f3 100644 --- a/api_docs/v1/SyntheticsListTestsResponse.md +++ b/api_docs/v1/SyntheticsListTestsResponse.md @@ -3,6 +3,7 @@ # SyntheticsListTestsResponse Object containing an array of Synthetic tests configuration. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsLocation.md b/api_docs/v1/SyntheticsLocation.md index edfcbcd213e..75ab591bdc2 100644 --- a/api_docs/v1/SyntheticsLocation.md +++ b/api_docs/v1/SyntheticsLocation.md @@ -3,6 +3,7 @@ # SyntheticsLocation Synthetic location that can be used when creating or editing a test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsLocations.md b/api_docs/v1/SyntheticsLocations.md index 323313deb3d..75af006469e 100644 --- a/api_docs/v1/SyntheticsLocations.md +++ b/api_docs/v1/SyntheticsLocations.md @@ -3,6 +3,7 @@ # SyntheticsLocations List of Synthetics locations. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsParsingOptions.md b/api_docs/v1/SyntheticsParsingOptions.md index 9246d3af04f..c94711a3fbb 100644 --- a/api_docs/v1/SyntheticsParsingOptions.md +++ b/api_docs/v1/SyntheticsParsingOptions.md @@ -3,6 +3,7 @@ # SyntheticsParsingOptions Parsing options for variables to extract. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsPrivateLocation.md b/api_docs/v1/SyntheticsPrivateLocation.md index 682b4b2e764..44b66705ef5 100644 --- a/api_docs/v1/SyntheticsPrivateLocation.md +++ b/api_docs/v1/SyntheticsPrivateLocation.md @@ -3,6 +3,7 @@ # SyntheticsPrivateLocation Object containing information about the private location to create. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsPrivateLocationCreationResponse.md b/api_docs/v1/SyntheticsPrivateLocationCreationResponse.md index e9892ab7682..52a4a1a6786 100644 --- a/api_docs/v1/SyntheticsPrivateLocationCreationResponse.md +++ b/api_docs/v1/SyntheticsPrivateLocationCreationResponse.md @@ -3,6 +3,7 @@ # SyntheticsPrivateLocationCreationResponse Object that contains the new private location, the public key for result encryption, and the configuration skeleton. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsPrivateLocationCreationResponseResultEncryption.md b/api_docs/v1/SyntheticsPrivateLocationCreationResponseResultEncryption.md index 2e2bd73a5b6..51532a06873 100644 --- a/api_docs/v1/SyntheticsPrivateLocationCreationResponseResultEncryption.md +++ b/api_docs/v1/SyntheticsPrivateLocationCreationResponseResultEncryption.md @@ -3,6 +3,7 @@ # SyntheticsPrivateLocationCreationResponseResultEncryption Public key for the result encryption. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsPrivateLocationSecrets.md b/api_docs/v1/SyntheticsPrivateLocationSecrets.md index a914611ebda..1a4cdf78751 100644 --- a/api_docs/v1/SyntheticsPrivateLocationSecrets.md +++ b/api_docs/v1/SyntheticsPrivateLocationSecrets.md @@ -3,6 +3,7 @@ # SyntheticsPrivateLocationSecrets Secrets for the private location. Only present in the response when creating the private location. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsPrivateLocationSecretsAuthentication.md b/api_docs/v1/SyntheticsPrivateLocationSecretsAuthentication.md index f7b0729ca20..a3e9f6776c5 100644 --- a/api_docs/v1/SyntheticsPrivateLocationSecretsAuthentication.md +++ b/api_docs/v1/SyntheticsPrivateLocationSecretsAuthentication.md @@ -3,6 +3,7 @@ # SyntheticsPrivateLocationSecretsAuthentication Authentication part of the secrets. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsPrivateLocationSecretsConfigDecryption.md b/api_docs/v1/SyntheticsPrivateLocationSecretsConfigDecryption.md index 1f44c0e28e9..aa5bf5dcd38 100644 --- a/api_docs/v1/SyntheticsPrivateLocationSecretsConfigDecryption.md +++ b/api_docs/v1/SyntheticsPrivateLocationSecretsConfigDecryption.md @@ -3,6 +3,7 @@ # SyntheticsPrivateLocationSecretsConfigDecryption Private key for the private location. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsSSLCertificate.md b/api_docs/v1/SyntheticsSSLCertificate.md index e9db98fa34a..4c13f8e1440 100644 --- a/api_docs/v1/SyntheticsSSLCertificate.md +++ b/api_docs/v1/SyntheticsSSLCertificate.md @@ -3,6 +3,7 @@ # SyntheticsSSLCertificate Object describing the SSL certificate used for a Synthetic test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsSSLCertificateIssuer.md b/api_docs/v1/SyntheticsSSLCertificateIssuer.md index 2e244e20e5b..9eeaba8f8cd 100644 --- a/api_docs/v1/SyntheticsSSLCertificateIssuer.md +++ b/api_docs/v1/SyntheticsSSLCertificateIssuer.md @@ -3,6 +3,7 @@ # SyntheticsSSLCertificateIssuer Object describing the issuer of a SSL certificate. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsSSLCertificateSubject.md b/api_docs/v1/SyntheticsSSLCertificateSubject.md index 28fedde25ee..4f6baca119b 100644 --- a/api_docs/v1/SyntheticsSSLCertificateSubject.md +++ b/api_docs/v1/SyntheticsSSLCertificateSubject.md @@ -3,6 +3,7 @@ # SyntheticsSSLCertificateSubject Object describing the SSL certificate used for the test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsStep.md b/api_docs/v1/SyntheticsStep.md index eecd9a629e8..9b286138df7 100644 --- a/api_docs/v1/SyntheticsStep.md +++ b/api_docs/v1/SyntheticsStep.md @@ -3,6 +3,7 @@ # SyntheticsStep The steps used in a Synthetics browser test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsStepDetail.md b/api_docs/v1/SyntheticsStepDetail.md index 46fdc79d81c..ce795adf3b4 100644 --- a/api_docs/v1/SyntheticsStepDetail.md +++ b/api_docs/v1/SyntheticsStepDetail.md @@ -3,6 +3,7 @@ # SyntheticsStepDetail Object describing a step for a Synthetic test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsStepDetailWarning.md b/api_docs/v1/SyntheticsStepDetailWarning.md index 35f2647213a..3f164f8956d 100644 --- a/api_docs/v1/SyntheticsStepDetailWarning.md +++ b/api_docs/v1/SyntheticsStepDetailWarning.md @@ -3,6 +3,7 @@ # SyntheticsStepDetailWarning Object collecting warnings for a given step. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsTestConfig.md b/api_docs/v1/SyntheticsTestConfig.md index cbdda1d3b86..e39debb89be 100644 --- a/api_docs/v1/SyntheticsTestConfig.md +++ b/api_docs/v1/SyntheticsTestConfig.md @@ -3,6 +3,7 @@ # SyntheticsTestConfig Configuration object for a Synthetic test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsTestDetails.md b/api_docs/v1/SyntheticsTestDetails.md index a0e4a83504e..0a7db15672a 100644 --- a/api_docs/v1/SyntheticsTestDetails.md +++ b/api_docs/v1/SyntheticsTestDetails.md @@ -3,6 +3,7 @@ # SyntheticsTestDetails Object containing details about your Synthetic test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsTestOptions.md b/api_docs/v1/SyntheticsTestOptions.md index b8d73a0b06b..46ed71b7de7 100644 --- a/api_docs/v1/SyntheticsTestOptions.md +++ b/api_docs/v1/SyntheticsTestOptions.md @@ -3,6 +3,7 @@ # SyntheticsTestOptions Object describing the extra options for a Synthetic test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsTestOptionsMonitorOptions.md b/api_docs/v1/SyntheticsTestOptionsMonitorOptions.md index 4f585abe60d..93efa5e876a 100644 --- a/api_docs/v1/SyntheticsTestOptionsMonitorOptions.md +++ b/api_docs/v1/SyntheticsTestOptionsMonitorOptions.md @@ -3,6 +3,7 @@ # SyntheticsTestOptionsMonitorOptions Object containing the options for a Synthetic test as a monitor (for example, renotification). + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsTestOptionsRetry.md b/api_docs/v1/SyntheticsTestOptionsRetry.md index f2090f49b20..1cf43a19304 100644 --- a/api_docs/v1/SyntheticsTestOptionsRetry.md +++ b/api_docs/v1/SyntheticsTestOptionsRetry.md @@ -3,6 +3,7 @@ # SyntheticsTestOptionsRetry Object describing the retry strategy to apply to a Synthetic test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsTestRequest.md b/api_docs/v1/SyntheticsTestRequest.md index 99554e769f3..85f8c0fa899 100644 --- a/api_docs/v1/SyntheticsTestRequest.md +++ b/api_docs/v1/SyntheticsTestRequest.md @@ -3,6 +3,7 @@ # SyntheticsTestRequest Object describing the Synthetic test request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsTestRequestCertificate.md b/api_docs/v1/SyntheticsTestRequestCertificate.md index b2c2febea6c..fb0368e00be 100644 --- a/api_docs/v1/SyntheticsTestRequestCertificate.md +++ b/api_docs/v1/SyntheticsTestRequestCertificate.md @@ -3,6 +3,7 @@ # SyntheticsTestRequestCertificate Client certificate to use when performing the test request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsTestRequestCertificateItem.md b/api_docs/v1/SyntheticsTestRequestCertificateItem.md index f9a31912b2e..16902ca627f 100644 --- a/api_docs/v1/SyntheticsTestRequestCertificateItem.md +++ b/api_docs/v1/SyntheticsTestRequestCertificateItem.md @@ -3,6 +3,7 @@ # SyntheticsTestRequestCertificateItem Define a request certificate. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsTiming.md b/api_docs/v1/SyntheticsTiming.md index f3f134b5bdf..6532a297e2c 100644 --- a/api_docs/v1/SyntheticsTiming.md +++ b/api_docs/v1/SyntheticsTiming.md @@ -3,6 +3,7 @@ # SyntheticsTiming Object containing all metrics and their values collected for a Synthetic API test. Learn more about those metrics in [Synthetics documentation](https://docs.datadoghq.com/synthetics/#metrics). + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsTriggerCITestLocation.md b/api_docs/v1/SyntheticsTriggerCITestLocation.md index 6700f8cfe9b..af63f86f565 100644 --- a/api_docs/v1/SyntheticsTriggerCITestLocation.md +++ b/api_docs/v1/SyntheticsTriggerCITestLocation.md @@ -3,6 +3,7 @@ # SyntheticsTriggerCITestLocation Synthetics location. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsTriggerCITestRunResult.md b/api_docs/v1/SyntheticsTriggerCITestRunResult.md index a05c4c9f94a..f8ccc27ffe0 100644 --- a/api_docs/v1/SyntheticsTriggerCITestRunResult.md +++ b/api_docs/v1/SyntheticsTriggerCITestRunResult.md @@ -3,6 +3,7 @@ # SyntheticsTriggerCITestRunResult Information about a single test run. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsTriggerCITestsResponse.md b/api_docs/v1/SyntheticsTriggerCITestsResponse.md index ea6bf24aecf..d4362a382bd 100644 --- a/api_docs/v1/SyntheticsTriggerCITestsResponse.md +++ b/api_docs/v1/SyntheticsTriggerCITestsResponse.md @@ -3,6 +3,7 @@ # SyntheticsTriggerCITestsResponse Object containing information about the tests triggered. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsUpdateTestPauseStatusPayload.md b/api_docs/v1/SyntheticsUpdateTestPauseStatusPayload.md index b434dcdf13b..ad24ffc491a 100644 --- a/api_docs/v1/SyntheticsUpdateTestPauseStatusPayload.md +++ b/api_docs/v1/SyntheticsUpdateTestPauseStatusPayload.md @@ -3,6 +3,7 @@ # SyntheticsUpdateTestPauseStatusPayload Object to start or pause an existing Synthetic test. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/SyntheticsVariableParser.md b/api_docs/v1/SyntheticsVariableParser.md index dca0cb12d50..56b930e871b 100644 --- a/api_docs/v1/SyntheticsVariableParser.md +++ b/api_docs/v1/SyntheticsVariableParser.md @@ -3,6 +3,7 @@ # SyntheticsVariableParser Details of the parser to use for the global variable. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/TableWidgetDefinition.md b/api_docs/v1/TableWidgetDefinition.md index 4da9ada5400..333a89dd743 100644 --- a/api_docs/v1/TableWidgetDefinition.md +++ b/api_docs/v1/TableWidgetDefinition.md @@ -3,6 +3,7 @@ # TableWidgetDefinition The table visualization is available on timeboards and screenboards. It displays columns of metrics grouped by tag key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/TableWidgetRequest.md b/api_docs/v1/TableWidgetRequest.md index b5f2486b5e0..3e14c1312e9 100644 --- a/api_docs/v1/TableWidgetRequest.md +++ b/api_docs/v1/TableWidgetRequest.md @@ -3,6 +3,7 @@ # TableWidgetRequest Updated table widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/TagToHosts.md b/api_docs/v1/TagToHosts.md index 7aa1c3b7e78..e1d8d05bf16 100644 --- a/api_docs/v1/TagToHosts.md +++ b/api_docs/v1/TagToHosts.md @@ -3,6 +3,7 @@ # TagToHosts In this object, the key is the tag, the value is a list of host names that are reporting that tag. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/TimeseriesWidgetDefinition.md b/api_docs/v1/TimeseriesWidgetDefinition.md index 5ff5fa3894f..41ffeb2159c 100644 --- a/api_docs/v1/TimeseriesWidgetDefinition.md +++ b/api_docs/v1/TimeseriesWidgetDefinition.md @@ -3,6 +3,7 @@ # TimeseriesWidgetDefinition The timeseries visualization allows you to display the evolution of one or more metrics, log events, or Indexed Spans over time. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/TimeseriesWidgetExpressionAlias.md b/api_docs/v1/TimeseriesWidgetExpressionAlias.md index c0096d41546..2fae9287a13 100644 --- a/api_docs/v1/TimeseriesWidgetExpressionAlias.md +++ b/api_docs/v1/TimeseriesWidgetExpressionAlias.md @@ -3,6 +3,7 @@ # TimeseriesWidgetExpressionAlias Define an expression alias. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/TimeseriesWidgetRequest.md b/api_docs/v1/TimeseriesWidgetRequest.md index 60bd4ab8c9f..440a34a8835 100644 --- a/api_docs/v1/TimeseriesWidgetRequest.md +++ b/api_docs/v1/TimeseriesWidgetRequest.md @@ -3,6 +3,7 @@ # TimeseriesWidgetRequest Updated timeseries widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ToplistWidgetDefinition.md b/api_docs/v1/ToplistWidgetDefinition.md index d85aecc38d7..0d97a95cd83 100644 --- a/api_docs/v1/ToplistWidgetDefinition.md +++ b/api_docs/v1/ToplistWidgetDefinition.md @@ -3,6 +3,7 @@ # ToplistWidgetDefinition The top list visualization enables you to display a list of Tag value like hostname or service with the most or least of any metric value, such as highest consumers of CPU, hosts with the least disk space, etc. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/ToplistWidgetRequest.md b/api_docs/v1/ToplistWidgetRequest.md index 99acc3c938b..89b7ae742be 100644 --- a/api_docs/v1/ToplistWidgetRequest.md +++ b/api_docs/v1/ToplistWidgetRequest.md @@ -3,6 +3,7 @@ # ToplistWidgetRequest Updated top list widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageAnalyzedLogsHour.md b/api_docs/v1/UsageAnalyzedLogsHour.md index a0bbdb7dc5b..1f8bfd30d04 100644 --- a/api_docs/v1/UsageAnalyzedLogsHour.md +++ b/api_docs/v1/UsageAnalyzedLogsHour.md @@ -3,6 +3,7 @@ # UsageAnalyzedLogsHour The number of analyzed logs for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageAnalyzedLogsResponse.md b/api_docs/v1/UsageAnalyzedLogsResponse.md index a03a887f9c7..bd7e69b2f05 100644 --- a/api_docs/v1/UsageAnalyzedLogsResponse.md +++ b/api_docs/v1/UsageAnalyzedLogsResponse.md @@ -3,6 +3,7 @@ # UsageAnalyzedLogsResponse A response containing the number of analyzed logs for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageAttributionAggregatesBody.md b/api_docs/v1/UsageAttributionAggregatesBody.md index 05fecbbf736..7a42139066e 100644 --- a/api_docs/v1/UsageAttributionAggregatesBody.md +++ b/api_docs/v1/UsageAttributionAggregatesBody.md @@ -3,6 +3,7 @@ # UsageAttributionAggregatesBody The object containing the aggregates. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageAttributionBody.md b/api_docs/v1/UsageAttributionBody.md index 746157094ba..f6c54482dc6 100644 --- a/api_docs/v1/UsageAttributionBody.md +++ b/api_docs/v1/UsageAttributionBody.md @@ -3,6 +3,7 @@ # UsageAttributionBody Usage Summary by tag for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageAttributionMetadata.md b/api_docs/v1/UsageAttributionMetadata.md index 925cbf0da72..1a5cb631273 100644 --- a/api_docs/v1/UsageAttributionMetadata.md +++ b/api_docs/v1/UsageAttributionMetadata.md @@ -3,6 +3,7 @@ # UsageAttributionMetadata The object containing document metadata. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageAttributionPagination.md b/api_docs/v1/UsageAttributionPagination.md index 79bb5c650ef..2668289f55c 100644 --- a/api_docs/v1/UsageAttributionPagination.md +++ b/api_docs/v1/UsageAttributionPagination.md @@ -3,6 +3,7 @@ # UsageAttributionPagination The page count for the current pagination. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageAttributionResponse.md b/api_docs/v1/UsageAttributionResponse.md index 1cb056e11c5..9d21b07bc0a 100644 --- a/api_docs/v1/UsageAttributionResponse.md +++ b/api_docs/v1/UsageAttributionResponse.md @@ -3,6 +3,7 @@ # UsageAttributionResponse Response containing the Usage Summary by tag(s). + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageAttributionValues.md b/api_docs/v1/UsageAttributionValues.md index 970ddf8b1de..56de19d5973 100644 --- a/api_docs/v1/UsageAttributionValues.md +++ b/api_docs/v1/UsageAttributionValues.md @@ -3,6 +3,7 @@ # UsageAttributionValues Fields in Usage Summary by tag(s). + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageBillableSummaryBody.md b/api_docs/v1/UsageBillableSummaryBody.md index fda1685216c..cd6f73b9bfa 100644 --- a/api_docs/v1/UsageBillableSummaryBody.md +++ b/api_docs/v1/UsageBillableSummaryBody.md @@ -3,6 +3,7 @@ # UsageBillableSummaryBody Response with properties for each aggregated usage type. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageBillableSummaryHour.md b/api_docs/v1/UsageBillableSummaryHour.md index 03db8eccf0a..bbf6948c5f4 100644 --- a/api_docs/v1/UsageBillableSummaryHour.md +++ b/api_docs/v1/UsageBillableSummaryHour.md @@ -3,6 +3,7 @@ # UsageBillableSummaryHour Response with monthly summary of data billed by Datadog. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageBillableSummaryKeys.md b/api_docs/v1/UsageBillableSummaryKeys.md index 54d33d2269e..9a666b74a4f 100644 --- a/api_docs/v1/UsageBillableSummaryKeys.md +++ b/api_docs/v1/UsageBillableSummaryKeys.md @@ -3,6 +3,7 @@ # UsageBillableSummaryKeys Response with aggregated usage types. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageBillableSummaryResponse.md b/api_docs/v1/UsageBillableSummaryResponse.md index f6f3fc2291b..6b2affcca07 100644 --- a/api_docs/v1/UsageBillableSummaryResponse.md +++ b/api_docs/v1/UsageBillableSummaryResponse.md @@ -3,6 +3,7 @@ # UsageBillableSummaryResponse Response with monthly summary of data billed by Datadog. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageCustomReportsAttributes.md b/api_docs/v1/UsageCustomReportsAttributes.md index 3e87dd852ec..5b57b032739 100644 --- a/api_docs/v1/UsageCustomReportsAttributes.md +++ b/api_docs/v1/UsageCustomReportsAttributes.md @@ -3,6 +3,7 @@ # UsageCustomReportsAttributes The response containing attributes for custom reports. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageCustomReportsData.md b/api_docs/v1/UsageCustomReportsData.md index d3d8717b885..ef48a24451e 100644 --- a/api_docs/v1/UsageCustomReportsData.md +++ b/api_docs/v1/UsageCustomReportsData.md @@ -3,6 +3,7 @@ # UsageCustomReportsData The response containing the date and type for custom reports. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageCustomReportsMeta.md b/api_docs/v1/UsageCustomReportsMeta.md index 6a8dec0f624..f3303369c0a 100644 --- a/api_docs/v1/UsageCustomReportsMeta.md +++ b/api_docs/v1/UsageCustomReportsMeta.md @@ -3,6 +3,7 @@ # UsageCustomReportsMeta The object containing document metadata. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageCustomReportsPage.md b/api_docs/v1/UsageCustomReportsPage.md index 656589011f6..6f30a15c5ac 100644 --- a/api_docs/v1/UsageCustomReportsPage.md +++ b/api_docs/v1/UsageCustomReportsPage.md @@ -3,6 +3,7 @@ # UsageCustomReportsPage The object containing page total count. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageCustomReportsResponse.md b/api_docs/v1/UsageCustomReportsResponse.md index e63aafc0124..7626a3304d5 100644 --- a/api_docs/v1/UsageCustomReportsResponse.md +++ b/api_docs/v1/UsageCustomReportsResponse.md @@ -3,6 +3,7 @@ # UsageCustomReportsResponse Response containing available custom reports. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageFargateHour.md b/api_docs/v1/UsageFargateHour.md index 8d54b7f82cd..21a6a7eb508 100644 --- a/api_docs/v1/UsageFargateHour.md +++ b/api_docs/v1/UsageFargateHour.md @@ -3,6 +3,7 @@ # UsageFargateHour Number of Fargate tasks run and hourly usage. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageFargateResponse.md b/api_docs/v1/UsageFargateResponse.md index ca5e5c13d15..b24d347247f 100644 --- a/api_docs/v1/UsageFargateResponse.md +++ b/api_docs/v1/UsageFargateResponse.md @@ -3,6 +3,7 @@ # UsageFargateResponse Response containing the number of Fargate tasks run and hourly usage. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageHostHour.md b/api_docs/v1/UsageHostHour.md index 4002df1219e..35279f0c32c 100644 --- a/api_docs/v1/UsageHostHour.md +++ b/api_docs/v1/UsageHostHour.md @@ -3,6 +3,7 @@ # UsageHostHour Number of hosts/containers recorded for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageHostsResponse.md b/api_docs/v1/UsageHostsResponse.md index 1e6e16ffaa9..7d188a97927 100644 --- a/api_docs/v1/UsageHostsResponse.md +++ b/api_docs/v1/UsageHostsResponse.md @@ -3,6 +3,7 @@ # UsageHostsResponse Host usage response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageIncidentManagementHour.md b/api_docs/v1/UsageIncidentManagementHour.md index 14fba7ddc9e..3bfec1e1989 100644 --- a/api_docs/v1/UsageIncidentManagementHour.md +++ b/api_docs/v1/UsageIncidentManagementHour.md @@ -3,6 +3,7 @@ # UsageIncidentManagementHour Incident management usage for a given organization for a given hour. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageIncidentManagementResponse.md b/api_docs/v1/UsageIncidentManagementResponse.md index 8c58504c7eb..842eaf73c36 100644 --- a/api_docs/v1/UsageIncidentManagementResponse.md +++ b/api_docs/v1/UsageIncidentManagementResponse.md @@ -3,6 +3,7 @@ # UsageIncidentManagementResponse Response containing the incident management usage for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageIndexedSpansHour.md b/api_docs/v1/UsageIndexedSpansHour.md index 9407594b256..9e1ea20ac2b 100644 --- a/api_docs/v1/UsageIndexedSpansHour.md +++ b/api_docs/v1/UsageIndexedSpansHour.md @@ -3,6 +3,7 @@ # UsageIndexedSpansHour The hours of indexed spans usage. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageIndexedSpansResponse.md b/api_docs/v1/UsageIndexedSpansResponse.md index 0a34c38ebe1..e54f3a81f13 100644 --- a/api_docs/v1/UsageIndexedSpansResponse.md +++ b/api_docs/v1/UsageIndexedSpansResponse.md @@ -3,6 +3,7 @@ # UsageIndexedSpansResponse A response containing indexed spans usage. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageIngestedSpansHour.md b/api_docs/v1/UsageIngestedSpansHour.md index 5a0cbf81875..8b81b52ac9b 100644 --- a/api_docs/v1/UsageIngestedSpansHour.md +++ b/api_docs/v1/UsageIngestedSpansHour.md @@ -3,6 +3,7 @@ # UsageIngestedSpansHour Ingested spans usage for a given organization for a given hour. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageIngestedSpansResponse.md b/api_docs/v1/UsageIngestedSpansResponse.md index 14e274c7926..103f8aeee5d 100644 --- a/api_docs/v1/UsageIngestedSpansResponse.md +++ b/api_docs/v1/UsageIngestedSpansResponse.md @@ -3,6 +3,7 @@ # UsageIngestedSpansResponse Response containing the ingested spans usage for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageIoTHour.md b/api_docs/v1/UsageIoTHour.md index d8fedfda577..a4d8534986f 100644 --- a/api_docs/v1/UsageIoTHour.md +++ b/api_docs/v1/UsageIoTHour.md @@ -3,6 +3,7 @@ # UsageIoTHour IoT usage for a given organization for a given hour. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageIoTResponse.md b/api_docs/v1/UsageIoTResponse.md index 0d8db181568..9120ec9400d 100644 --- a/api_docs/v1/UsageIoTResponse.md +++ b/api_docs/v1/UsageIoTResponse.md @@ -3,6 +3,7 @@ # UsageIoTResponse Response containing the IoT usage for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageLambdaHour.md b/api_docs/v1/UsageLambdaHour.md index 11cbc126d8b..06cb8e7aa32 100644 --- a/api_docs/v1/UsageLambdaHour.md +++ b/api_docs/v1/UsageLambdaHour.md @@ -3,6 +3,7 @@ # UsageLambdaHour Number of lambda functions and sum of the invocations of all lambda functions for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageLambdaResponse.md b/api_docs/v1/UsageLambdaResponse.md index 4b452e6d1d1..7f32918440e 100644 --- a/api_docs/v1/UsageLambdaResponse.md +++ b/api_docs/v1/UsageLambdaResponse.md @@ -3,6 +3,7 @@ # UsageLambdaResponse Response containing the number of lambda functions and sum of the invocations of all lambda functions for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageLogsByIndexHour.md b/api_docs/v1/UsageLogsByIndexHour.md index e7978449201..7c0b33e862d 100644 --- a/api_docs/v1/UsageLogsByIndexHour.md +++ b/api_docs/v1/UsageLogsByIndexHour.md @@ -3,6 +3,7 @@ # UsageLogsByIndexHour Number of indexed logs for each hour and index for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageLogsByIndexResponse.md b/api_docs/v1/UsageLogsByIndexResponse.md index 785a91c5748..4890c74a61f 100644 --- a/api_docs/v1/UsageLogsByIndexResponse.md +++ b/api_docs/v1/UsageLogsByIndexResponse.md @@ -3,6 +3,7 @@ # UsageLogsByIndexResponse Response containing the number of indexed logs for each hour and index for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageLogsHour.md b/api_docs/v1/UsageLogsHour.md index eb788cbcb6b..82171a5aa16 100644 --- a/api_docs/v1/UsageLogsHour.md +++ b/api_docs/v1/UsageLogsHour.md @@ -3,6 +3,7 @@ # UsageLogsHour Hour usage for logs. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageLogsResponse.md b/api_docs/v1/UsageLogsResponse.md index 83e78ed1f39..137bff33a7e 100644 --- a/api_docs/v1/UsageLogsResponse.md +++ b/api_docs/v1/UsageLogsResponse.md @@ -3,6 +3,7 @@ # UsageLogsResponse Response containing the number of logs for each hour. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageNetworkFlowsHour.md b/api_docs/v1/UsageNetworkFlowsHour.md index 00dea5c19b2..c0446764df8 100644 --- a/api_docs/v1/UsageNetworkFlowsHour.md +++ b/api_docs/v1/UsageNetworkFlowsHour.md @@ -3,6 +3,7 @@ # UsageNetworkFlowsHour Number of netflow events indexed for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageNetworkFlowsResponse.md b/api_docs/v1/UsageNetworkFlowsResponse.md index 05a9f25306b..4352ebb4b1b 100644 --- a/api_docs/v1/UsageNetworkFlowsResponse.md +++ b/api_docs/v1/UsageNetworkFlowsResponse.md @@ -3,6 +3,7 @@ # UsageNetworkFlowsResponse Response containing the number of netflow events indexed for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageNetworkHostsHour.md b/api_docs/v1/UsageNetworkHostsHour.md index cc05f524502..154d6d2fbe6 100644 --- a/api_docs/v1/UsageNetworkHostsHour.md +++ b/api_docs/v1/UsageNetworkHostsHour.md @@ -3,6 +3,7 @@ # UsageNetworkHostsHour Number of active NPM hosts for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageNetworkHostsResponse.md b/api_docs/v1/UsageNetworkHostsResponse.md index 5c3e8309a8e..1ee36b21e57 100644 --- a/api_docs/v1/UsageNetworkHostsResponse.md +++ b/api_docs/v1/UsageNetworkHostsResponse.md @@ -3,6 +3,7 @@ # UsageNetworkHostsResponse Response containing the number of active NPM hosts for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageProfilingHour.md b/api_docs/v1/UsageProfilingHour.md index 9cce8f50250..9b1680ae697 100644 --- a/api_docs/v1/UsageProfilingHour.md +++ b/api_docs/v1/UsageProfilingHour.md @@ -3,6 +3,7 @@ # UsageProfilingHour The number of profiled hosts for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageProfilingResponse.md b/api_docs/v1/UsageProfilingResponse.md index f161e8a379c..fe4d090d087 100644 --- a/api_docs/v1/UsageProfilingResponse.md +++ b/api_docs/v1/UsageProfilingResponse.md @@ -3,6 +3,7 @@ # UsageProfilingResponse Response containing the number of profiled hosts for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageRumSessionsHour.md b/api_docs/v1/UsageRumSessionsHour.md index aabd279d762..ddc0742adfa 100644 --- a/api_docs/v1/UsageRumSessionsHour.md +++ b/api_docs/v1/UsageRumSessionsHour.md @@ -3,6 +3,7 @@ # UsageRumSessionsHour Number of RUM Sessions recorded for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageRumSessionsResponse.md b/api_docs/v1/UsageRumSessionsResponse.md index 0fe5a90ce25..7b46400babc 100644 --- a/api_docs/v1/UsageRumSessionsResponse.md +++ b/api_docs/v1/UsageRumSessionsResponse.md @@ -3,6 +3,7 @@ # UsageRumSessionsResponse Response containing the number of RUM Sessions for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSNMPHour.md b/api_docs/v1/UsageSNMPHour.md index 2a7fada862e..a6225f4f741 100644 --- a/api_docs/v1/UsageSNMPHour.md +++ b/api_docs/v1/UsageSNMPHour.md @@ -3,6 +3,7 @@ # UsageSNMPHour The number of SNMP devices for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSNMPResponse.md b/api_docs/v1/UsageSNMPResponse.md index bf3adeed414..761bf2ac7c1 100644 --- a/api_docs/v1/UsageSNMPResponse.md +++ b/api_docs/v1/UsageSNMPResponse.md @@ -3,6 +3,7 @@ # UsageSNMPResponse Response containing the number of SNMP devices for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSpecifiedCustomReportsAttributes.md b/api_docs/v1/UsageSpecifiedCustomReportsAttributes.md index 2ac1ff10005..e0e828562fb 100644 --- a/api_docs/v1/UsageSpecifiedCustomReportsAttributes.md +++ b/api_docs/v1/UsageSpecifiedCustomReportsAttributes.md @@ -3,6 +3,7 @@ # UsageSpecifiedCustomReportsAttributes The response containing attributes for specified custom reports. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSpecifiedCustomReportsData.md b/api_docs/v1/UsageSpecifiedCustomReportsData.md index 2905e5c945f..f4d4a7b416f 100644 --- a/api_docs/v1/UsageSpecifiedCustomReportsData.md +++ b/api_docs/v1/UsageSpecifiedCustomReportsData.md @@ -3,6 +3,7 @@ # UsageSpecifiedCustomReportsData Response containing date and type for specified custom reports. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSpecifiedCustomReportsMeta.md b/api_docs/v1/UsageSpecifiedCustomReportsMeta.md index 89717525dc4..d9fbfd8931b 100644 --- a/api_docs/v1/UsageSpecifiedCustomReportsMeta.md +++ b/api_docs/v1/UsageSpecifiedCustomReportsMeta.md @@ -3,6 +3,7 @@ # UsageSpecifiedCustomReportsMeta The object containing document metadata. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSpecifiedCustomReportsPage.md b/api_docs/v1/UsageSpecifiedCustomReportsPage.md index eaac0d17f2f..611d1d7fea9 100644 --- a/api_docs/v1/UsageSpecifiedCustomReportsPage.md +++ b/api_docs/v1/UsageSpecifiedCustomReportsPage.md @@ -3,6 +3,7 @@ # UsageSpecifiedCustomReportsPage The object containing page total count for specified ID. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSpecifiedCustomReportsResponse.md b/api_docs/v1/UsageSpecifiedCustomReportsResponse.md index 47d06766577..88ff88b789c 100644 --- a/api_docs/v1/UsageSpecifiedCustomReportsResponse.md +++ b/api_docs/v1/UsageSpecifiedCustomReportsResponse.md @@ -3,6 +3,7 @@ # UsageSpecifiedCustomReportsResponse Returns available specified custom reports. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSummaryDate.md b/api_docs/v1/UsageSummaryDate.md index 99a15a39960..79bd7198208 100644 --- a/api_docs/v1/UsageSummaryDate.md +++ b/api_docs/v1/UsageSummaryDate.md @@ -3,6 +3,7 @@ # UsageSummaryDate Response with hourly report of all data billed by Datadog all organizations. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSummaryDateOrg.md b/api_docs/v1/UsageSummaryDateOrg.md index af45df51712..7f415225e00 100644 --- a/api_docs/v1/UsageSummaryDateOrg.md +++ b/api_docs/v1/UsageSummaryDateOrg.md @@ -3,6 +3,7 @@ # UsageSummaryDateOrg Global hourly report of all data billed by Datadog for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSummaryResponse.md b/api_docs/v1/UsageSummaryResponse.md index 0437d80fc02..c82f0ff4c08 100644 --- a/api_docs/v1/UsageSummaryResponse.md +++ b/api_docs/v1/UsageSummaryResponse.md @@ -3,6 +3,7 @@ # UsageSummaryResponse Response with hourly report of all data billed by Datadog all organizations. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSyntheticsAPIHour.md b/api_docs/v1/UsageSyntheticsAPIHour.md index c25fccbf867..fb7519e376d 100644 --- a/api_docs/v1/UsageSyntheticsAPIHour.md +++ b/api_docs/v1/UsageSyntheticsAPIHour.md @@ -3,6 +3,7 @@ # UsageSyntheticsAPIHour Number of Synthetics API tests run for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSyntheticsAPIResponse.md b/api_docs/v1/UsageSyntheticsAPIResponse.md index 7cb7eed378d..5084f431366 100644 --- a/api_docs/v1/UsageSyntheticsAPIResponse.md +++ b/api_docs/v1/UsageSyntheticsAPIResponse.md @@ -3,6 +3,7 @@ # UsageSyntheticsAPIResponse Response containing the number of Synthetics API tests run for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSyntheticsBrowserHour.md b/api_docs/v1/UsageSyntheticsBrowserHour.md index e19c2611257..87cea0abd1e 100644 --- a/api_docs/v1/UsageSyntheticsBrowserHour.md +++ b/api_docs/v1/UsageSyntheticsBrowserHour.md @@ -3,6 +3,7 @@ # UsageSyntheticsBrowserHour Number of Synthetics Browser tests run for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSyntheticsBrowserResponse.md b/api_docs/v1/UsageSyntheticsBrowserResponse.md index 70ae460b7e5..241f297f729 100644 --- a/api_docs/v1/UsageSyntheticsBrowserResponse.md +++ b/api_docs/v1/UsageSyntheticsBrowserResponse.md @@ -3,6 +3,7 @@ # UsageSyntheticsBrowserResponse Response containing the number of Synthetics Browser tests run for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSyntheticsHour.md b/api_docs/v1/UsageSyntheticsHour.md index 39a0cb27fa1..efddfe2b174 100644 --- a/api_docs/v1/UsageSyntheticsHour.md +++ b/api_docs/v1/UsageSyntheticsHour.md @@ -3,6 +3,7 @@ # UsageSyntheticsHour The number of synthetics tests run for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageSyntheticsResponse.md b/api_docs/v1/UsageSyntheticsResponse.md index d6a4e7cb144..2112096d826 100644 --- a/api_docs/v1/UsageSyntheticsResponse.md +++ b/api_docs/v1/UsageSyntheticsResponse.md @@ -3,6 +3,7 @@ # UsageSyntheticsResponse Response containing the number of Synthetics API tests run for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageTimeseriesHour.md b/api_docs/v1/UsageTimeseriesHour.md index 2dca8e2f6fd..ff57b2e01fe 100644 --- a/api_docs/v1/UsageTimeseriesHour.md +++ b/api_docs/v1/UsageTimeseriesHour.md @@ -3,6 +3,7 @@ # UsageTimeseriesHour The hourly usage of timeseries. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageTimeseriesResponse.md b/api_docs/v1/UsageTimeseriesResponse.md index 5a9827d54b3..4cb393e1190 100644 --- a/api_docs/v1/UsageTimeseriesResponse.md +++ b/api_docs/v1/UsageTimeseriesResponse.md @@ -3,6 +3,7 @@ # UsageTimeseriesResponse Response containing hourly usage of timeseries. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageTopAvgMetricsHour.md b/api_docs/v1/UsageTopAvgMetricsHour.md index ec094b6736f..56f37c7554b 100644 --- a/api_docs/v1/UsageTopAvgMetricsHour.md +++ b/api_docs/v1/UsageTopAvgMetricsHour.md @@ -3,6 +3,7 @@ # UsageTopAvgMetricsHour Number of hourly recorded custom metrics for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageTopAvgMetricsResponse.md b/api_docs/v1/UsageTopAvgMetricsResponse.md index 3800798a28f..b6e9815f4c8 100644 --- a/api_docs/v1/UsageTopAvgMetricsResponse.md +++ b/api_docs/v1/UsageTopAvgMetricsResponse.md @@ -3,6 +3,7 @@ # UsageTopAvgMetricsResponse Response containing the number of hourly recorded custom metrics for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageTraceHour.md b/api_docs/v1/UsageTraceHour.md index 313e2d39af2..4512d96df49 100644 --- a/api_docs/v1/UsageTraceHour.md +++ b/api_docs/v1/UsageTraceHour.md @@ -3,6 +3,7 @@ # UsageTraceHour The hours of trace usage. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageTraceResponse.md b/api_docs/v1/UsageTraceResponse.md index f43ed2bf9c9..c490032fd73 100644 --- a/api_docs/v1/UsageTraceResponse.md +++ b/api_docs/v1/UsageTraceResponse.md @@ -3,6 +3,7 @@ # UsageTraceResponse A response containing trace usage. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageTracingWithoutLimitsHour.md b/api_docs/v1/UsageTracingWithoutLimitsHour.md index 0b5bb939da9..b049c924358 100644 --- a/api_docs/v1/UsageTracingWithoutLimitsHour.md +++ b/api_docs/v1/UsageTracingWithoutLimitsHour.md @@ -3,6 +3,7 @@ # UsageTracingWithoutLimitsHour Tracing without limits usage for a given organization for a given hour. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UsageTracingWithoutLimitsResponse.md b/api_docs/v1/UsageTracingWithoutLimitsResponse.md index 0785a04fa69..4a94b379af0 100644 --- a/api_docs/v1/UsageTracingWithoutLimitsResponse.md +++ b/api_docs/v1/UsageTracingWithoutLimitsResponse.md @@ -3,6 +3,7 @@ # UsageTracingWithoutLimitsResponse Response containing the tracing without limits usage for each hour for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/User.md b/api_docs/v1/User.md index 725aa78e99c..a37022b880c 100644 --- a/api_docs/v1/User.md +++ b/api_docs/v1/User.md @@ -3,6 +3,7 @@ # User Create, edit, and disable users. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UserDisableResponse.md b/api_docs/v1/UserDisableResponse.md index a116a8f5dd3..c38668fe7be 100644 --- a/api_docs/v1/UserDisableResponse.md +++ b/api_docs/v1/UserDisableResponse.md @@ -3,6 +3,7 @@ # UserDisableResponse Array of user disabled for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UserListResponse.md b/api_docs/v1/UserListResponse.md index 84359198a31..b8802cfc09d 100644 --- a/api_docs/v1/UserListResponse.md +++ b/api_docs/v1/UserListResponse.md @@ -3,6 +3,7 @@ # UserListResponse Array of Datadog users for a given organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/UserResponse.md b/api_docs/v1/UserResponse.md index eb0105a8091..081d46cdeb8 100644 --- a/api_docs/v1/UserResponse.md +++ b/api_docs/v1/UserResponse.md @@ -3,6 +3,7 @@ # UserResponse A Datadog User. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/Widget.md b/api_docs/v1/Widget.md index a14b8c5e965..dbafcc2daba 100644 --- a/api_docs/v1/Widget.md +++ b/api_docs/v1/Widget.md @@ -3,6 +3,7 @@ # Widget Information about widget. Note: The `layout` property is required for widgets in dashboards with `free` `layout_type` only. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/WidgetAxis.md b/api_docs/v1/WidgetAxis.md index c38bcfab0c6..e1a00bcc76c 100644 --- a/api_docs/v1/WidgetAxis.md +++ b/api_docs/v1/WidgetAxis.md @@ -3,6 +3,7 @@ # WidgetAxis Axis controls for the widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/WidgetConditionalFormat.md b/api_docs/v1/WidgetConditionalFormat.md index 17c465c0b2a..49a72d877b2 100644 --- a/api_docs/v1/WidgetConditionalFormat.md +++ b/api_docs/v1/WidgetConditionalFormat.md @@ -3,6 +3,7 @@ # WidgetConditionalFormat Define a conditional format for the widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/WidgetCustomLink.md b/api_docs/v1/WidgetCustomLink.md index fac5876ffd6..0471667581e 100644 --- a/api_docs/v1/WidgetCustomLink.md +++ b/api_docs/v1/WidgetCustomLink.md @@ -3,6 +3,7 @@ # WidgetCustomLink Custom links help you connect a data value to a URL, like a Datadog page or your AWS console. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/WidgetEvent.md b/api_docs/v1/WidgetEvent.md index f199451c4d1..0710e879674 100644 --- a/api_docs/v1/WidgetEvent.md +++ b/api_docs/v1/WidgetEvent.md @@ -3,6 +3,7 @@ # WidgetEvent Event overlay control options. See the dedicated [Events JSON schema documentation](https://docs.datadoghq.com/dashboards/graphing_json/widget_json/#events-schema) to learn how to build the ``. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/WidgetFieldSort.md b/api_docs/v1/WidgetFieldSort.md index 7e9150aac38..f5666b5579e 100644 --- a/api_docs/v1/WidgetFieldSort.md +++ b/api_docs/v1/WidgetFieldSort.md @@ -3,6 +3,7 @@ # WidgetFieldSort Which column and order to sort by + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/WidgetFormula.md b/api_docs/v1/WidgetFormula.md index bc0d8a24d09..f56e5d64cb8 100644 --- a/api_docs/v1/WidgetFormula.md +++ b/api_docs/v1/WidgetFormula.md @@ -3,6 +3,7 @@ # WidgetFormula Formula to be used in a widget query. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/WidgetFormulaLimit.md b/api_docs/v1/WidgetFormulaLimit.md index 64b248eb9bb..1dc94501c91 100644 --- a/api_docs/v1/WidgetFormulaLimit.md +++ b/api_docs/v1/WidgetFormulaLimit.md @@ -3,6 +3,7 @@ # WidgetFormulaLimit Options for limiting results returned. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/WidgetLayout.md b/api_docs/v1/WidgetLayout.md index 288624aefec..53b733a5822 100644 --- a/api_docs/v1/WidgetLayout.md +++ b/api_docs/v1/WidgetLayout.md @@ -3,6 +3,7 @@ # WidgetLayout The layout for a widget on a free dashboard. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/WidgetMarker.md b/api_docs/v1/WidgetMarker.md index 0d140a0aea5..12c9be5dea4 100644 --- a/api_docs/v1/WidgetMarker.md +++ b/api_docs/v1/WidgetMarker.md @@ -3,6 +3,7 @@ # WidgetMarker Markers allow you to add visual conditional formatting for your graphs. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/WidgetRequestStyle.md b/api_docs/v1/WidgetRequestStyle.md index 6079d01bd08..c08d865cf64 100644 --- a/api_docs/v1/WidgetRequestStyle.md +++ b/api_docs/v1/WidgetRequestStyle.md @@ -3,6 +3,7 @@ # WidgetRequestStyle Define request widget style. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/WidgetStyle.md b/api_docs/v1/WidgetStyle.md index efbdc836281..3dea9a57847 100644 --- a/api_docs/v1/WidgetStyle.md +++ b/api_docs/v1/WidgetStyle.md @@ -3,6 +3,7 @@ # WidgetStyle Widget style definition. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v1/WidgetTime.md b/api_docs/v1/WidgetTime.md index d7450524203..4f5c2b143c0 100644 --- a/api_docs/v1/WidgetTime.md +++ b/api_docs/v1/WidgetTime.md @@ -3,6 +3,7 @@ # WidgetTime Time setting for the widget. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/APIErrorResponse.md b/api_docs/v2/APIErrorResponse.md index 762d5496c67..9b3ff1beee4 100644 --- a/api_docs/v2/APIErrorResponse.md +++ b/api_docs/v2/APIErrorResponse.md @@ -3,6 +3,7 @@ # APIErrorResponse API error response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/APIKeyCreateAttributes.md b/api_docs/v2/APIKeyCreateAttributes.md index efcbfe3d29e..7c7bbbd73b2 100644 --- a/api_docs/v2/APIKeyCreateAttributes.md +++ b/api_docs/v2/APIKeyCreateAttributes.md @@ -3,6 +3,7 @@ # APIKeyCreateAttributes Attributes used to create an API Key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/APIKeyCreateData.md b/api_docs/v2/APIKeyCreateData.md index 563eff6daf8..bcd32c2e542 100644 --- a/api_docs/v2/APIKeyCreateData.md +++ b/api_docs/v2/APIKeyCreateData.md @@ -3,6 +3,7 @@ # APIKeyCreateData Object used to create an API key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/APIKeyCreateRequest.md b/api_docs/v2/APIKeyCreateRequest.md index aee4437861f..dca0f144001 100644 --- a/api_docs/v2/APIKeyCreateRequest.md +++ b/api_docs/v2/APIKeyCreateRequest.md @@ -3,6 +3,7 @@ # APIKeyCreateRequest Request used to create an API key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/APIKeyRelationships.md b/api_docs/v2/APIKeyRelationships.md index 4f197721408..8d4bf21f0aa 100644 --- a/api_docs/v2/APIKeyRelationships.md +++ b/api_docs/v2/APIKeyRelationships.md @@ -3,6 +3,7 @@ # APIKeyRelationships Resources related to the API key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/APIKeyResponse.md b/api_docs/v2/APIKeyResponse.md index f73e0cb2c26..4d62d72bfd7 100644 --- a/api_docs/v2/APIKeyResponse.md +++ b/api_docs/v2/APIKeyResponse.md @@ -3,6 +3,7 @@ # APIKeyResponse Response for retrieving an API key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/APIKeyUpdateAttributes.md b/api_docs/v2/APIKeyUpdateAttributes.md index 9543fe5c215..d4867bf68e5 100644 --- a/api_docs/v2/APIKeyUpdateAttributes.md +++ b/api_docs/v2/APIKeyUpdateAttributes.md @@ -3,6 +3,7 @@ # APIKeyUpdateAttributes Attributes used to update an API Key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/APIKeyUpdateData.md b/api_docs/v2/APIKeyUpdateData.md index 7f9fe375969..0b36ad99fa9 100644 --- a/api_docs/v2/APIKeyUpdateData.md +++ b/api_docs/v2/APIKeyUpdateData.md @@ -3,6 +3,7 @@ # APIKeyUpdateData Object used to update an API key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/APIKeyUpdateRequest.md b/api_docs/v2/APIKeyUpdateRequest.md index 0423daf88e1..35bb4d5138c 100644 --- a/api_docs/v2/APIKeyUpdateRequest.md +++ b/api_docs/v2/APIKeyUpdateRequest.md @@ -3,6 +3,7 @@ # APIKeyUpdateRequest Request used to update an API key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/APIKeysResponse.md b/api_docs/v2/APIKeysResponse.md index c05c8c2ef20..9dbc86a16d2 100644 --- a/api_docs/v2/APIKeysResponse.md +++ b/api_docs/v2/APIKeysResponse.md @@ -3,6 +3,7 @@ # APIKeysResponse Response for a list of API keys. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ApplicationKeyCreateAttributes.md b/api_docs/v2/ApplicationKeyCreateAttributes.md index b13b17ffd01..b8a284c21a9 100644 --- a/api_docs/v2/ApplicationKeyCreateAttributes.md +++ b/api_docs/v2/ApplicationKeyCreateAttributes.md @@ -3,6 +3,7 @@ # ApplicationKeyCreateAttributes Attributes used to create an application Key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ApplicationKeyCreateData.md b/api_docs/v2/ApplicationKeyCreateData.md index 9c6ffe1ad58..890ffefefea 100644 --- a/api_docs/v2/ApplicationKeyCreateData.md +++ b/api_docs/v2/ApplicationKeyCreateData.md @@ -3,6 +3,7 @@ # ApplicationKeyCreateData Object used to create an application key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ApplicationKeyCreateRequest.md b/api_docs/v2/ApplicationKeyCreateRequest.md index fdc458321c4..4fbca11e7bc 100644 --- a/api_docs/v2/ApplicationKeyCreateRequest.md +++ b/api_docs/v2/ApplicationKeyCreateRequest.md @@ -3,6 +3,7 @@ # ApplicationKeyCreateRequest Request used to create an application key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ApplicationKeyRelationships.md b/api_docs/v2/ApplicationKeyRelationships.md index 1c5ad131334..9336fe74769 100644 --- a/api_docs/v2/ApplicationKeyRelationships.md +++ b/api_docs/v2/ApplicationKeyRelationships.md @@ -3,6 +3,7 @@ # ApplicationKeyRelationships Resources related to the application key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ApplicationKeyResponse.md b/api_docs/v2/ApplicationKeyResponse.md index 1712ffb8684..9a5dfedaca8 100644 --- a/api_docs/v2/ApplicationKeyResponse.md +++ b/api_docs/v2/ApplicationKeyResponse.md @@ -3,6 +3,7 @@ # ApplicationKeyResponse Response for retrieving an application key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ApplicationKeyUpdateAttributes.md b/api_docs/v2/ApplicationKeyUpdateAttributes.md index fe28f6845ec..0f0879a4943 100644 --- a/api_docs/v2/ApplicationKeyUpdateAttributes.md +++ b/api_docs/v2/ApplicationKeyUpdateAttributes.md @@ -3,6 +3,7 @@ # ApplicationKeyUpdateAttributes Attributes used to update an application Key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ApplicationKeyUpdateData.md b/api_docs/v2/ApplicationKeyUpdateData.md index d64f3656c84..d00d9ed4a21 100644 --- a/api_docs/v2/ApplicationKeyUpdateData.md +++ b/api_docs/v2/ApplicationKeyUpdateData.md @@ -3,6 +3,7 @@ # ApplicationKeyUpdateData Object used to update an application key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ApplicationKeyUpdateRequest.md b/api_docs/v2/ApplicationKeyUpdateRequest.md index 170a8d1e694..c249ed71b17 100644 --- a/api_docs/v2/ApplicationKeyUpdateRequest.md +++ b/api_docs/v2/ApplicationKeyUpdateRequest.md @@ -3,6 +3,7 @@ # ApplicationKeyUpdateRequest Request used to update an application key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/Creator.md b/api_docs/v2/Creator.md index c2e7cf2fcb0..7a606571319 100644 --- a/api_docs/v2/Creator.md +++ b/api_docs/v2/Creator.md @@ -3,6 +3,7 @@ # Creator Creator of the object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/DashboardListAddItemsRequest.md b/api_docs/v2/DashboardListAddItemsRequest.md index 772bd4cafc1..47214dc008a 100644 --- a/api_docs/v2/DashboardListAddItemsRequest.md +++ b/api_docs/v2/DashboardListAddItemsRequest.md @@ -3,6 +3,7 @@ # DashboardListAddItemsRequest Request containing a list of dashboards to add. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/DashboardListAddItemsResponse.md b/api_docs/v2/DashboardListAddItemsResponse.md index a592abd6432..6060be28cd5 100644 --- a/api_docs/v2/DashboardListAddItemsResponse.md +++ b/api_docs/v2/DashboardListAddItemsResponse.md @@ -3,6 +3,7 @@ # DashboardListAddItemsResponse Response containing a list of added dashboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/DashboardListDeleteItemsRequest.md b/api_docs/v2/DashboardListDeleteItemsRequest.md index 0bfe26ca5f7..2f65457eaec 100644 --- a/api_docs/v2/DashboardListDeleteItemsRequest.md +++ b/api_docs/v2/DashboardListDeleteItemsRequest.md @@ -3,6 +3,7 @@ # DashboardListDeleteItemsRequest Request containing a list of dashboards to delete. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/DashboardListDeleteItemsResponse.md b/api_docs/v2/DashboardListDeleteItemsResponse.md index 3dcf9238a72..8db2b289237 100644 --- a/api_docs/v2/DashboardListDeleteItemsResponse.md +++ b/api_docs/v2/DashboardListDeleteItemsResponse.md @@ -3,6 +3,7 @@ # DashboardListDeleteItemsResponse Response containing a list of deleted dashboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/DashboardListItem.md b/api_docs/v2/DashboardListItem.md index bb3a8a6082f..dcb89acd083 100644 --- a/api_docs/v2/DashboardListItem.md +++ b/api_docs/v2/DashboardListItem.md @@ -3,6 +3,7 @@ # DashboardListItem A dashboard within a list. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/DashboardListItemRequest.md b/api_docs/v2/DashboardListItemRequest.md index f5d6978bd92..c1c78542f9e 100644 --- a/api_docs/v2/DashboardListItemRequest.md +++ b/api_docs/v2/DashboardListItemRequest.md @@ -3,6 +3,7 @@ # DashboardListItemRequest A dashboard within a list. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/DashboardListItemResponse.md b/api_docs/v2/DashboardListItemResponse.md index d54ecd16431..df9af44cf92 100644 --- a/api_docs/v2/DashboardListItemResponse.md +++ b/api_docs/v2/DashboardListItemResponse.md @@ -3,6 +3,7 @@ # DashboardListItemResponse A dashboard within a list. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/DashboardListItems.md b/api_docs/v2/DashboardListItems.md index a4bd827c04c..a2406e81d3d 100644 --- a/api_docs/v2/DashboardListItems.md +++ b/api_docs/v2/DashboardListItems.md @@ -3,6 +3,7 @@ # DashboardListItems Dashboards within a list. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/DashboardListUpdateItemsRequest.md b/api_docs/v2/DashboardListUpdateItemsRequest.md index 4c772c319e0..a4213aedd3a 100644 --- a/api_docs/v2/DashboardListUpdateItemsRequest.md +++ b/api_docs/v2/DashboardListUpdateItemsRequest.md @@ -3,6 +3,7 @@ # DashboardListUpdateItemsRequest Request containing the list of dashboards to update to. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/DashboardListUpdateItemsResponse.md b/api_docs/v2/DashboardListUpdateItemsResponse.md index d1778080763..41a5cfc6196 100644 --- a/api_docs/v2/DashboardListUpdateItemsResponse.md +++ b/api_docs/v2/DashboardListUpdateItemsResponse.md @@ -3,6 +3,7 @@ # DashboardListUpdateItemsResponse Response containing a list of updated dashboards. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/FullAPIKey.md b/api_docs/v2/FullAPIKey.md index e43e5b7aa96..7383fe32f3b 100644 --- a/api_docs/v2/FullAPIKey.md +++ b/api_docs/v2/FullAPIKey.md @@ -3,6 +3,7 @@ # FullAPIKey Datadog API key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/FullAPIKeyAttributes.md b/api_docs/v2/FullAPIKeyAttributes.md index e7b2d16eac3..beca5fe229c 100644 --- a/api_docs/v2/FullAPIKeyAttributes.md +++ b/api_docs/v2/FullAPIKeyAttributes.md @@ -3,6 +3,7 @@ # FullAPIKeyAttributes Attributes of a full API key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/FullApplicationKey.md b/api_docs/v2/FullApplicationKey.md index 9ac8d597e4c..5f12243f900 100644 --- a/api_docs/v2/FullApplicationKey.md +++ b/api_docs/v2/FullApplicationKey.md @@ -3,6 +3,7 @@ # FullApplicationKey Datadog application key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/FullApplicationKeyAttributes.md b/api_docs/v2/FullApplicationKeyAttributes.md index 6ef0bbc1c29..3c8ef4c59f6 100644 --- a/api_docs/v2/FullApplicationKeyAttributes.md +++ b/api_docs/v2/FullApplicationKeyAttributes.md @@ -3,6 +3,7 @@ # FullApplicationKeyAttributes Attributes of a full application key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentCreateAttributes.md b/api_docs/v2/IncidentCreateAttributes.md index 7b3e09cce9b..0086d7b8b44 100644 --- a/api_docs/v2/IncidentCreateAttributes.md +++ b/api_docs/v2/IncidentCreateAttributes.md @@ -3,6 +3,7 @@ # IncidentCreateAttributes The incident's attributes for a create request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentCreateData.md b/api_docs/v2/IncidentCreateData.md index d942a9f8cad..81605977f66 100644 --- a/api_docs/v2/IncidentCreateData.md +++ b/api_docs/v2/IncidentCreateData.md @@ -3,6 +3,7 @@ # IncidentCreateData Incident data for a create request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentCreateRelationships.md b/api_docs/v2/IncidentCreateRelationships.md index 28960a6fef6..41959d0bc23 100644 --- a/api_docs/v2/IncidentCreateRelationships.md +++ b/api_docs/v2/IncidentCreateRelationships.md @@ -3,6 +3,7 @@ # IncidentCreateRelationships The relationships the incident will have with other resources once created. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentCreateRequest.md b/api_docs/v2/IncidentCreateRequest.md index e72d1871e06..e0ae0063489 100644 --- a/api_docs/v2/IncidentCreateRequest.md +++ b/api_docs/v2/IncidentCreateRequest.md @@ -3,6 +3,7 @@ # IncidentCreateRequest Create request for an incident. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentFieldAttributesMultipleValue.md b/api_docs/v2/IncidentFieldAttributesMultipleValue.md index f3d110e043c..3a89efaa264 100644 --- a/api_docs/v2/IncidentFieldAttributesMultipleValue.md +++ b/api_docs/v2/IncidentFieldAttributesMultipleValue.md @@ -3,6 +3,7 @@ # IncidentFieldAttributesMultipleValue A field with potentially multiple values selected. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentFieldAttributesSingleValue.md b/api_docs/v2/IncidentFieldAttributesSingleValue.md index c43841ea61c..78189011575 100644 --- a/api_docs/v2/IncidentFieldAttributesSingleValue.md +++ b/api_docs/v2/IncidentFieldAttributesSingleValue.md @@ -3,6 +3,7 @@ # IncidentFieldAttributesSingleValue A field with a single value selected. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentResponse.md b/api_docs/v2/IncidentResponse.md index 8ff0428ef34..daa611b211c 100644 --- a/api_docs/v2/IncidentResponse.md +++ b/api_docs/v2/IncidentResponse.md @@ -3,6 +3,7 @@ # IncidentResponse Response with an incident. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentResponseAttributes.md b/api_docs/v2/IncidentResponseAttributes.md index 092d6d462a7..982a62b38b5 100644 --- a/api_docs/v2/IncidentResponseAttributes.md +++ b/api_docs/v2/IncidentResponseAttributes.md @@ -3,6 +3,7 @@ # IncidentResponseAttributes The incident's attributes from a response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentResponseData.md b/api_docs/v2/IncidentResponseData.md index d1539f2d818..dd32515cd1c 100644 --- a/api_docs/v2/IncidentResponseData.md +++ b/api_docs/v2/IncidentResponseData.md @@ -3,6 +3,7 @@ # IncidentResponseData Incident data from a response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentResponseRelationships.md b/api_docs/v2/IncidentResponseRelationships.md index 0a4e081b801..fd7ef87bbc0 100644 --- a/api_docs/v2/IncidentResponseRelationships.md +++ b/api_docs/v2/IncidentResponseRelationships.md @@ -3,6 +3,7 @@ # IncidentResponseRelationships The incident's relationships from a response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServiceCreateAttributes.md b/api_docs/v2/IncidentServiceCreateAttributes.md index ae9b8197d29..dcc6be7e1b5 100644 --- a/api_docs/v2/IncidentServiceCreateAttributes.md +++ b/api_docs/v2/IncidentServiceCreateAttributes.md @@ -3,6 +3,7 @@ # IncidentServiceCreateAttributes The incident service's attributes for a create request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServiceCreateData.md b/api_docs/v2/IncidentServiceCreateData.md index 375bf6b1026..f61e9dea5b4 100644 --- a/api_docs/v2/IncidentServiceCreateData.md +++ b/api_docs/v2/IncidentServiceCreateData.md @@ -3,6 +3,7 @@ # IncidentServiceCreateData Incident Service payload for create requests. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServiceCreateRequest.md b/api_docs/v2/IncidentServiceCreateRequest.md index 62438fdcf38..f7126fec045 100644 --- a/api_docs/v2/IncidentServiceCreateRequest.md +++ b/api_docs/v2/IncidentServiceCreateRequest.md @@ -3,6 +3,7 @@ # IncidentServiceCreateRequest Create request with an incident service payload. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServiceRelationships.md b/api_docs/v2/IncidentServiceRelationships.md index 29c274ea8bb..4647065cf72 100644 --- a/api_docs/v2/IncidentServiceRelationships.md +++ b/api_docs/v2/IncidentServiceRelationships.md @@ -3,6 +3,7 @@ # IncidentServiceRelationships The incident service's relationships. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServiceResponse.md b/api_docs/v2/IncidentServiceResponse.md index e5667482bc4..bcabf57fa8b 100644 --- a/api_docs/v2/IncidentServiceResponse.md +++ b/api_docs/v2/IncidentServiceResponse.md @@ -3,6 +3,7 @@ # IncidentServiceResponse Response with an incident service payload. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServiceResponseAttributes.md b/api_docs/v2/IncidentServiceResponseAttributes.md index eabc1497c81..c45aed0bf3e 100644 --- a/api_docs/v2/IncidentServiceResponseAttributes.md +++ b/api_docs/v2/IncidentServiceResponseAttributes.md @@ -3,6 +3,7 @@ # IncidentServiceResponseAttributes The incident service's attributes from a response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServiceResponseData.md b/api_docs/v2/IncidentServiceResponseData.md index b65381456d5..f9a58c52bde 100644 --- a/api_docs/v2/IncidentServiceResponseData.md +++ b/api_docs/v2/IncidentServiceResponseData.md @@ -3,6 +3,7 @@ # IncidentServiceResponseData Incident Service data from responses. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServiceUpdateAttributes.md b/api_docs/v2/IncidentServiceUpdateAttributes.md index d5859ed5a56..9f1f260fc57 100644 --- a/api_docs/v2/IncidentServiceUpdateAttributes.md +++ b/api_docs/v2/IncidentServiceUpdateAttributes.md @@ -3,6 +3,7 @@ # IncidentServiceUpdateAttributes The incident service's attributes for an update request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServiceUpdateData.md b/api_docs/v2/IncidentServiceUpdateData.md index 1128c2e2baf..58af2016f50 100644 --- a/api_docs/v2/IncidentServiceUpdateData.md +++ b/api_docs/v2/IncidentServiceUpdateData.md @@ -3,6 +3,7 @@ # IncidentServiceUpdateData Incident Service payload for update requests. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServiceUpdateRequest.md b/api_docs/v2/IncidentServiceUpdateRequest.md index aede8001c1a..797c67650bc 100644 --- a/api_docs/v2/IncidentServiceUpdateRequest.md +++ b/api_docs/v2/IncidentServiceUpdateRequest.md @@ -3,6 +3,7 @@ # IncidentServiceUpdateRequest Update request with an incident service payload. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServicesResponse.md b/api_docs/v2/IncidentServicesResponse.md index 514c36810f6..c0f6db251b0 100644 --- a/api_docs/v2/IncidentServicesResponse.md +++ b/api_docs/v2/IncidentServicesResponse.md @@ -3,6 +3,7 @@ # IncidentServicesResponse Response with a list of incident service payloads. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServicesResponseMeta.md b/api_docs/v2/IncidentServicesResponseMeta.md index 6f3ddddcfac..b58f00ca87c 100644 --- a/api_docs/v2/IncidentServicesResponseMeta.md +++ b/api_docs/v2/IncidentServicesResponseMeta.md @@ -3,6 +3,7 @@ # IncidentServicesResponseMeta The metadata object containing pagination metadata. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentServicesResponseMetaPagination.md b/api_docs/v2/IncidentServicesResponseMetaPagination.md index 6a5740f2c3a..b4e07ae1c1a 100644 --- a/api_docs/v2/IncidentServicesResponseMetaPagination.md +++ b/api_docs/v2/IncidentServicesResponseMetaPagination.md @@ -3,6 +3,7 @@ # IncidentServicesResponseMetaPagination Pagination properties. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTeamCreateAttributes.md b/api_docs/v2/IncidentTeamCreateAttributes.md index 2c668e6017b..a00a0617eeb 100644 --- a/api_docs/v2/IncidentTeamCreateAttributes.md +++ b/api_docs/v2/IncidentTeamCreateAttributes.md @@ -3,6 +3,7 @@ # IncidentTeamCreateAttributes The incident team's attributes for a create request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTeamCreateData.md b/api_docs/v2/IncidentTeamCreateData.md index a1e47eae4bf..13963d7b494 100644 --- a/api_docs/v2/IncidentTeamCreateData.md +++ b/api_docs/v2/IncidentTeamCreateData.md @@ -3,6 +3,7 @@ # IncidentTeamCreateData Incident Team data for a create request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTeamCreateRequest.md b/api_docs/v2/IncidentTeamCreateRequest.md index 058638720ab..6d50a68034f 100644 --- a/api_docs/v2/IncidentTeamCreateRequest.md +++ b/api_docs/v2/IncidentTeamCreateRequest.md @@ -3,6 +3,7 @@ # IncidentTeamCreateRequest Create request with an incident team payload. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTeamRelationships.md b/api_docs/v2/IncidentTeamRelationships.md index e9721640ea7..5db344cc26b 100644 --- a/api_docs/v2/IncidentTeamRelationships.md +++ b/api_docs/v2/IncidentTeamRelationships.md @@ -3,6 +3,7 @@ # IncidentTeamRelationships The incident team's relationships. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTeamResponse.md b/api_docs/v2/IncidentTeamResponse.md index 05332b3f682..3ebdee8228f 100644 --- a/api_docs/v2/IncidentTeamResponse.md +++ b/api_docs/v2/IncidentTeamResponse.md @@ -3,6 +3,7 @@ # IncidentTeamResponse Response with an incident team payload. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTeamResponseAttributes.md b/api_docs/v2/IncidentTeamResponseAttributes.md index efcebe91772..5549a7fc8fd 100644 --- a/api_docs/v2/IncidentTeamResponseAttributes.md +++ b/api_docs/v2/IncidentTeamResponseAttributes.md @@ -3,6 +3,7 @@ # IncidentTeamResponseAttributes The incident team's attributes from a response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTeamResponseData.md b/api_docs/v2/IncidentTeamResponseData.md index f2a604821b5..c0a57846dc1 100644 --- a/api_docs/v2/IncidentTeamResponseData.md +++ b/api_docs/v2/IncidentTeamResponseData.md @@ -3,6 +3,7 @@ # IncidentTeamResponseData Incident Team data from a response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTeamUpdateAttributes.md b/api_docs/v2/IncidentTeamUpdateAttributes.md index debd79341e8..0f26facf7fd 100644 --- a/api_docs/v2/IncidentTeamUpdateAttributes.md +++ b/api_docs/v2/IncidentTeamUpdateAttributes.md @@ -3,6 +3,7 @@ # IncidentTeamUpdateAttributes The incident team's attributes for an update request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTeamUpdateData.md b/api_docs/v2/IncidentTeamUpdateData.md index 42e51147d80..108c569bb77 100644 --- a/api_docs/v2/IncidentTeamUpdateData.md +++ b/api_docs/v2/IncidentTeamUpdateData.md @@ -3,6 +3,7 @@ # IncidentTeamUpdateData Incident Team data for an update request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTeamUpdateRequest.md b/api_docs/v2/IncidentTeamUpdateRequest.md index 3af168c8743..01c79f32478 100644 --- a/api_docs/v2/IncidentTeamUpdateRequest.md +++ b/api_docs/v2/IncidentTeamUpdateRequest.md @@ -3,6 +3,7 @@ # IncidentTeamUpdateRequest Update request with an incident team payload. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTeamsResponse.md b/api_docs/v2/IncidentTeamsResponse.md index 7a0f296760b..41486806e66 100644 --- a/api_docs/v2/IncidentTeamsResponse.md +++ b/api_docs/v2/IncidentTeamsResponse.md @@ -3,6 +3,7 @@ # IncidentTeamsResponse Response with a list of incident team payloads. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTimelineCellMarkdownCreateAttributes.md b/api_docs/v2/IncidentTimelineCellMarkdownCreateAttributes.md index 629499f2ba1..4c91f2329ae 100644 --- a/api_docs/v2/IncidentTimelineCellMarkdownCreateAttributes.md +++ b/api_docs/v2/IncidentTimelineCellMarkdownCreateAttributes.md @@ -3,6 +3,7 @@ # IncidentTimelineCellMarkdownCreateAttributes Timeline cell data for Markdown timeline cells for a create request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentTimelineCellMarkdownCreateAttributesContent.md b/api_docs/v2/IncidentTimelineCellMarkdownCreateAttributesContent.md index 4b40695f993..d4d63f9ad07 100644 --- a/api_docs/v2/IncidentTimelineCellMarkdownCreateAttributesContent.md +++ b/api_docs/v2/IncidentTimelineCellMarkdownCreateAttributesContent.md @@ -3,6 +3,7 @@ # IncidentTimelineCellMarkdownCreateAttributesContent The Markdown timeline cell contents. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentUpdateAttributes.md b/api_docs/v2/IncidentUpdateAttributes.md index 142f424153a..3833d185536 100644 --- a/api_docs/v2/IncidentUpdateAttributes.md +++ b/api_docs/v2/IncidentUpdateAttributes.md @@ -3,6 +3,7 @@ # IncidentUpdateAttributes The incident's attributes for an update request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentUpdateData.md b/api_docs/v2/IncidentUpdateData.md index e2d83a3d366..4073f1cb626 100644 --- a/api_docs/v2/IncidentUpdateData.md +++ b/api_docs/v2/IncidentUpdateData.md @@ -3,6 +3,7 @@ # IncidentUpdateData Incident data for an update request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentUpdateRelationships.md b/api_docs/v2/IncidentUpdateRelationships.md index 3409ed9d7e0..27b06a260b0 100644 --- a/api_docs/v2/IncidentUpdateRelationships.md +++ b/api_docs/v2/IncidentUpdateRelationships.md @@ -3,6 +3,7 @@ # IncidentUpdateRelationships The incident's relationships for an update request. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentUpdateRequest.md b/api_docs/v2/IncidentUpdateRequest.md index 72d9add0f47..25be3c636c6 100644 --- a/api_docs/v2/IncidentUpdateRequest.md +++ b/api_docs/v2/IncidentUpdateRequest.md @@ -3,6 +3,7 @@ # IncidentUpdateRequest Update request for an incident. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/IncidentsResponse.md b/api_docs/v2/IncidentsResponse.md index 089ce2b5c28..c1ca10dd4ff 100644 --- a/api_docs/v2/IncidentsResponse.md +++ b/api_docs/v2/IncidentsResponse.md @@ -3,6 +3,7 @@ # IncidentsResponse Response with a list of incidents. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ListApplicationKeysResponse.md b/api_docs/v2/ListApplicationKeysResponse.md index 26ae8071cea..c246e031076 100644 --- a/api_docs/v2/ListApplicationKeysResponse.md +++ b/api_docs/v2/ListApplicationKeysResponse.md @@ -3,6 +3,7 @@ # ListApplicationKeysResponse Response for a list of application keys. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/Log.md b/api_docs/v2/Log.md index 287ca8e0c82..119e330218c 100644 --- a/api_docs/v2/Log.md +++ b/api_docs/v2/Log.md @@ -3,6 +3,7 @@ # Log Object description of a log after being processed and stored by Datadog. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogAttributes.md b/api_docs/v2/LogAttributes.md index ab93516b172..f4f88d76798 100644 --- a/api_docs/v2/LogAttributes.md +++ b/api_docs/v2/LogAttributes.md @@ -3,6 +3,7 @@ # LogAttributes JSON object containing all log attributes and their associated values. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsAggregateBucket.md b/api_docs/v2/LogsAggregateBucket.md index cd1dc5ab66c..31407e7b595 100644 --- a/api_docs/v2/LogsAggregateBucket.md +++ b/api_docs/v2/LogsAggregateBucket.md @@ -3,6 +3,7 @@ # LogsAggregateBucket A bucket values + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsAggregateBucketValueTimeseries.md b/api_docs/v2/LogsAggregateBucketValueTimeseries.md index ad8547063e6..6eae4fd6e96 100644 --- a/api_docs/v2/LogsAggregateBucketValueTimeseries.md +++ b/api_docs/v2/LogsAggregateBucketValueTimeseries.md @@ -3,6 +3,7 @@ # LogsAggregateBucketValueTimeseries A timeseries array + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsAggregateBucketValueTimeseriesPoint.md b/api_docs/v2/LogsAggregateBucketValueTimeseriesPoint.md index f927b3c35d3..48bd076a99d 100644 --- a/api_docs/v2/LogsAggregateBucketValueTimeseriesPoint.md +++ b/api_docs/v2/LogsAggregateBucketValueTimeseriesPoint.md @@ -3,6 +3,7 @@ # LogsAggregateBucketValueTimeseriesPoint A timeseries point + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsAggregateRequest.md b/api_docs/v2/LogsAggregateRequest.md index f3a61d816d1..9f1c68765d6 100644 --- a/api_docs/v2/LogsAggregateRequest.md +++ b/api_docs/v2/LogsAggregateRequest.md @@ -3,6 +3,7 @@ # LogsAggregateRequest The object sent with the request to retrieve a list of logs from your organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsAggregateRequestPage.md b/api_docs/v2/LogsAggregateRequestPage.md index 49fc449a4e8..1f7339b2730 100644 --- a/api_docs/v2/LogsAggregateRequestPage.md +++ b/api_docs/v2/LogsAggregateRequestPage.md @@ -3,6 +3,7 @@ # LogsAggregateRequestPage Paging settings + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsAggregateResponse.md b/api_docs/v2/LogsAggregateResponse.md index 2df078d50b5..250556db1e9 100644 --- a/api_docs/v2/LogsAggregateResponse.md +++ b/api_docs/v2/LogsAggregateResponse.md @@ -3,6 +3,7 @@ # LogsAggregateResponse The response object for the logs aggregate API endpoint + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsAggregateResponseData.md b/api_docs/v2/LogsAggregateResponseData.md index b58cab7b71f..65494dd2f6a 100644 --- a/api_docs/v2/LogsAggregateResponseData.md +++ b/api_docs/v2/LogsAggregateResponseData.md @@ -3,6 +3,7 @@ # LogsAggregateResponseData The query results + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsAggregateSort.md b/api_docs/v2/LogsAggregateSort.md index ae39ff63de3..91319ee88da 100644 --- a/api_docs/v2/LogsAggregateSort.md +++ b/api_docs/v2/LogsAggregateSort.md @@ -3,6 +3,7 @@ # LogsAggregateSort A sort rule + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchive.md b/api_docs/v2/LogsArchive.md index 2f1a4cb5e34..78ef488f771 100644 --- a/api_docs/v2/LogsArchive.md +++ b/api_docs/v2/LogsArchive.md @@ -3,6 +3,7 @@ # LogsArchive The logs archive. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveAttributes.md b/api_docs/v2/LogsArchiveAttributes.md index 27fab1d0bd6..aef7b6f027f 100644 --- a/api_docs/v2/LogsArchiveAttributes.md +++ b/api_docs/v2/LogsArchiveAttributes.md @@ -3,6 +3,7 @@ # LogsArchiveAttributes The attributes associated with the archive. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveCreateRequest.md b/api_docs/v2/LogsArchiveCreateRequest.md index c337229c76d..93930bddaff 100644 --- a/api_docs/v2/LogsArchiveCreateRequest.md +++ b/api_docs/v2/LogsArchiveCreateRequest.md @@ -3,6 +3,7 @@ # LogsArchiveCreateRequest The logs archive. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveCreateRequestAttributes.md b/api_docs/v2/LogsArchiveCreateRequestAttributes.md index 0e8a13eaa4d..fc88bfc7676 100644 --- a/api_docs/v2/LogsArchiveCreateRequestAttributes.md +++ b/api_docs/v2/LogsArchiveCreateRequestAttributes.md @@ -3,6 +3,7 @@ # LogsArchiveCreateRequestAttributes The attributes associated with the archive. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveCreateRequestDefinition.md b/api_docs/v2/LogsArchiveCreateRequestDefinition.md index 1e8816ebdb6..129ab6f4c61 100644 --- a/api_docs/v2/LogsArchiveCreateRequestDefinition.md +++ b/api_docs/v2/LogsArchiveCreateRequestDefinition.md @@ -3,6 +3,7 @@ # LogsArchiveCreateRequestDefinition The definition of an archive. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveDefinition.md b/api_docs/v2/LogsArchiveDefinition.md index d9f3d2ec45e..85fc8b0ddd1 100644 --- a/api_docs/v2/LogsArchiveDefinition.md +++ b/api_docs/v2/LogsArchiveDefinition.md @@ -3,6 +3,7 @@ # LogsArchiveDefinition The definition of an archive. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveDestinationAzure.md b/api_docs/v2/LogsArchiveDestinationAzure.md index cd4a2bdc9cc..7f8adbe38bb 100644 --- a/api_docs/v2/LogsArchiveDestinationAzure.md +++ b/api_docs/v2/LogsArchiveDestinationAzure.md @@ -3,6 +3,7 @@ # LogsArchiveDestinationAzure The Azure archive destination. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveDestinationGCS.md b/api_docs/v2/LogsArchiveDestinationGCS.md index 12c637a8494..40fc552bea4 100644 --- a/api_docs/v2/LogsArchiveDestinationGCS.md +++ b/api_docs/v2/LogsArchiveDestinationGCS.md @@ -3,6 +3,7 @@ # LogsArchiveDestinationGCS The GCS archive destination. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveDestinationS3.md b/api_docs/v2/LogsArchiveDestinationS3.md index 1f1fa613447..4139308924f 100644 --- a/api_docs/v2/LogsArchiveDestinationS3.md +++ b/api_docs/v2/LogsArchiveDestinationS3.md @@ -3,6 +3,7 @@ # LogsArchiveDestinationS3 The S3 archive destination. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveIntegrationAzure.md b/api_docs/v2/LogsArchiveIntegrationAzure.md index e98ec2e9414..6d82de2dd87 100644 --- a/api_docs/v2/LogsArchiveIntegrationAzure.md +++ b/api_docs/v2/LogsArchiveIntegrationAzure.md @@ -3,6 +3,7 @@ # LogsArchiveIntegrationAzure The Azure archive's integration destination. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveIntegrationGCS.md b/api_docs/v2/LogsArchiveIntegrationGCS.md index 595beba7d4c..9dadc8c252f 100644 --- a/api_docs/v2/LogsArchiveIntegrationGCS.md +++ b/api_docs/v2/LogsArchiveIntegrationGCS.md @@ -3,6 +3,7 @@ # LogsArchiveIntegrationGCS The GCS archive's integration destination. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveIntegrationS3.md b/api_docs/v2/LogsArchiveIntegrationS3.md index b9c34655ba1..703bcd0450e 100644 --- a/api_docs/v2/LogsArchiveIntegrationS3.md +++ b/api_docs/v2/LogsArchiveIntegrationS3.md @@ -3,6 +3,7 @@ # LogsArchiveIntegrationS3 The S3 Archive's integration destination. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveOrder.md b/api_docs/v2/LogsArchiveOrder.md index f773cd12ece..ee1f21a948d 100644 --- a/api_docs/v2/LogsArchiveOrder.md +++ b/api_docs/v2/LogsArchiveOrder.md @@ -3,6 +3,7 @@ # LogsArchiveOrder A ordered list of archive IDs. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveOrderAttributes.md b/api_docs/v2/LogsArchiveOrderAttributes.md index d36a2939430..e52daf02870 100644 --- a/api_docs/v2/LogsArchiveOrderAttributes.md +++ b/api_docs/v2/LogsArchiveOrderAttributes.md @@ -3,6 +3,7 @@ # LogsArchiveOrderAttributes The attributes associated with the archive order. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchiveOrderDefinition.md b/api_docs/v2/LogsArchiveOrderDefinition.md index a50c0f3c74e..be52667a6b5 100644 --- a/api_docs/v2/LogsArchiveOrderDefinition.md +++ b/api_docs/v2/LogsArchiveOrderDefinition.md @@ -3,6 +3,7 @@ # LogsArchiveOrderDefinition The definition of an archive order. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsArchives.md b/api_docs/v2/LogsArchives.md index c8baa13c627..96d1735995b 100644 --- a/api_docs/v2/LogsArchives.md +++ b/api_docs/v2/LogsArchives.md @@ -3,6 +3,7 @@ # LogsArchives The available archives. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsCompute.md b/api_docs/v2/LogsCompute.md index 1a9475093a5..9e6f5fec84a 100644 --- a/api_docs/v2/LogsCompute.md +++ b/api_docs/v2/LogsCompute.md @@ -3,6 +3,7 @@ # LogsCompute A compute rule to compute metrics or timeseries + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsGroupBy.md b/api_docs/v2/LogsGroupBy.md index a398aad6f56..02897ce83aa 100644 --- a/api_docs/v2/LogsGroupBy.md +++ b/api_docs/v2/LogsGroupBy.md @@ -3,6 +3,7 @@ # LogsGroupBy A group by rule + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsGroupByHistogram.md b/api_docs/v2/LogsGroupByHistogram.md index a72ec16ad69..f18374e983a 100644 --- a/api_docs/v2/LogsGroupByHistogram.md +++ b/api_docs/v2/LogsGroupByHistogram.md @@ -3,6 +3,7 @@ # LogsGroupByHistogram Used to perform a histogram computation (only for measure facets). Note: At most 100 buckets are allowed, the number of buckets is (max - min)/interval. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsListRequest.md b/api_docs/v2/LogsListRequest.md index af231d71ac8..0723a848e6e 100644 --- a/api_docs/v2/LogsListRequest.md +++ b/api_docs/v2/LogsListRequest.md @@ -3,6 +3,7 @@ # LogsListRequest The request for a logs list. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsListRequestPage.md b/api_docs/v2/LogsListRequestPage.md index ed030a14dc9..e01f781c804 100644 --- a/api_docs/v2/LogsListRequestPage.md +++ b/api_docs/v2/LogsListRequestPage.md @@ -3,6 +3,7 @@ # LogsListRequestPage Paging attributes for listing logs. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsListResponse.md b/api_docs/v2/LogsListResponse.md index 93b02989bf1..f24c3eec548 100644 --- a/api_docs/v2/LogsListResponse.md +++ b/api_docs/v2/LogsListResponse.md @@ -3,6 +3,7 @@ # LogsListResponse Response object with all logs matching the request and pagination information. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsListResponseLinks.md b/api_docs/v2/LogsListResponseLinks.md index f04caa6f705..736282cea6b 100644 --- a/api_docs/v2/LogsListResponseLinks.md +++ b/api_docs/v2/LogsListResponseLinks.md @@ -3,6 +3,7 @@ # LogsListResponseLinks Links attributes. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricCompute.md b/api_docs/v2/LogsMetricCompute.md index 58eff948a9e..9c4698affc0 100644 --- a/api_docs/v2/LogsMetricCompute.md +++ b/api_docs/v2/LogsMetricCompute.md @@ -3,6 +3,7 @@ # LogsMetricCompute The compute rule to compute the log-based metric. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricCreateAttributes.md b/api_docs/v2/LogsMetricCreateAttributes.md index 952129034aa..4e5a5e3062a 100644 --- a/api_docs/v2/LogsMetricCreateAttributes.md +++ b/api_docs/v2/LogsMetricCreateAttributes.md @@ -3,6 +3,7 @@ # LogsMetricCreateAttributes The object describing the Datadog log-based metric to create. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricCreateData.md b/api_docs/v2/LogsMetricCreateData.md index 9c61f774b22..b0e09a0dfc9 100644 --- a/api_docs/v2/LogsMetricCreateData.md +++ b/api_docs/v2/LogsMetricCreateData.md @@ -3,6 +3,7 @@ # LogsMetricCreateData The new log-based metric properties. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricCreateRequest.md b/api_docs/v2/LogsMetricCreateRequest.md index 8a4db445e1f..d1253a0ba99 100644 --- a/api_docs/v2/LogsMetricCreateRequest.md +++ b/api_docs/v2/LogsMetricCreateRequest.md @@ -3,6 +3,7 @@ # LogsMetricCreateRequest The new log-based metric body. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricFilter.md b/api_docs/v2/LogsMetricFilter.md index f384f3350c9..ccd3ed9ad84 100644 --- a/api_docs/v2/LogsMetricFilter.md +++ b/api_docs/v2/LogsMetricFilter.md @@ -3,6 +3,7 @@ # LogsMetricFilter The log-based metric filter. Logs matching this filter will be aggregated in this metric. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricGroupBy.md b/api_docs/v2/LogsMetricGroupBy.md index 906ff144d19..ea4240802ce 100644 --- a/api_docs/v2/LogsMetricGroupBy.md +++ b/api_docs/v2/LogsMetricGroupBy.md @@ -3,6 +3,7 @@ # LogsMetricGroupBy A group by rule. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricResponse.md b/api_docs/v2/LogsMetricResponse.md index 13fe6393e36..8bd16279386 100644 --- a/api_docs/v2/LogsMetricResponse.md +++ b/api_docs/v2/LogsMetricResponse.md @@ -3,6 +3,7 @@ # LogsMetricResponse The log-based metric object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricResponseAttributes.md b/api_docs/v2/LogsMetricResponseAttributes.md index c944d2dd310..07edee98851 100644 --- a/api_docs/v2/LogsMetricResponseAttributes.md +++ b/api_docs/v2/LogsMetricResponseAttributes.md @@ -3,6 +3,7 @@ # LogsMetricResponseAttributes The object describing a Datadog log-based metric. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricResponseCompute.md b/api_docs/v2/LogsMetricResponseCompute.md index b7f3d6c5d7c..c638e600cce 100644 --- a/api_docs/v2/LogsMetricResponseCompute.md +++ b/api_docs/v2/LogsMetricResponseCompute.md @@ -3,6 +3,7 @@ # LogsMetricResponseCompute The compute rule to compute the log-based metric. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricResponseData.md b/api_docs/v2/LogsMetricResponseData.md index 4e7455ccac7..bacd80f89a7 100644 --- a/api_docs/v2/LogsMetricResponseData.md +++ b/api_docs/v2/LogsMetricResponseData.md @@ -3,6 +3,7 @@ # LogsMetricResponseData The log-based metric properties. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricResponseFilter.md b/api_docs/v2/LogsMetricResponseFilter.md index 024d6173974..b4e797b0898 100644 --- a/api_docs/v2/LogsMetricResponseFilter.md +++ b/api_docs/v2/LogsMetricResponseFilter.md @@ -3,6 +3,7 @@ # LogsMetricResponseFilter The log-based metric filter. Logs matching this filter will be aggregated in this metric. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricResponseGroupBy.md b/api_docs/v2/LogsMetricResponseGroupBy.md index 78ec6afede1..35e7512b450 100644 --- a/api_docs/v2/LogsMetricResponseGroupBy.md +++ b/api_docs/v2/LogsMetricResponseGroupBy.md @@ -3,6 +3,7 @@ # LogsMetricResponseGroupBy A group by rule. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricUpdateAttributes.md b/api_docs/v2/LogsMetricUpdateAttributes.md index f16f5576490..7e756cfe92f 100644 --- a/api_docs/v2/LogsMetricUpdateAttributes.md +++ b/api_docs/v2/LogsMetricUpdateAttributes.md @@ -3,6 +3,7 @@ # LogsMetricUpdateAttributes The log-based metric properties that will be updated. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricUpdateData.md b/api_docs/v2/LogsMetricUpdateData.md index e6470d0c878..d8961d73409 100644 --- a/api_docs/v2/LogsMetricUpdateData.md +++ b/api_docs/v2/LogsMetricUpdateData.md @@ -3,6 +3,7 @@ # LogsMetricUpdateData The new log-based metric properties. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricUpdateRequest.md b/api_docs/v2/LogsMetricUpdateRequest.md index 88197b54c0e..6e3731167c6 100644 --- a/api_docs/v2/LogsMetricUpdateRequest.md +++ b/api_docs/v2/LogsMetricUpdateRequest.md @@ -3,6 +3,7 @@ # LogsMetricUpdateRequest The new log-based metric body. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsMetricsResponse.md b/api_docs/v2/LogsMetricsResponse.md index 85b0fc6ff99..316926cabe1 100644 --- a/api_docs/v2/LogsMetricsResponse.md +++ b/api_docs/v2/LogsMetricsResponse.md @@ -3,6 +3,7 @@ # LogsMetricsResponse All the available log-based metric objects. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsQueryFilter.md b/api_docs/v2/LogsQueryFilter.md index 79f342de444..1b25d7397e2 100644 --- a/api_docs/v2/LogsQueryFilter.md +++ b/api_docs/v2/LogsQueryFilter.md @@ -3,6 +3,7 @@ # LogsQueryFilter The search and filter query settings + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsQueryOptions.md b/api_docs/v2/LogsQueryOptions.md index 112e903ed33..0f85cae1ff2 100644 --- a/api_docs/v2/LogsQueryOptions.md +++ b/api_docs/v2/LogsQueryOptions.md @@ -3,6 +3,7 @@ # LogsQueryOptions Global query options that are used during the query. Note: You should only supply timezone or time offset but not both otherwise the query will fail. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsResponseMetadata.md b/api_docs/v2/LogsResponseMetadata.md index ca30e3e6e20..37b8e2ffdc1 100644 --- a/api_docs/v2/LogsResponseMetadata.md +++ b/api_docs/v2/LogsResponseMetadata.md @@ -3,6 +3,7 @@ # LogsResponseMetadata The metadata associated with a request + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsResponseMetadataPage.md b/api_docs/v2/LogsResponseMetadataPage.md index 1758099fdb9..ee5cbfe9bb3 100644 --- a/api_docs/v2/LogsResponseMetadataPage.md +++ b/api_docs/v2/LogsResponseMetadataPage.md @@ -3,6 +3,7 @@ # LogsResponseMetadataPage Paging attributes. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/LogsWarning.md b/api_docs/v2/LogsWarning.md index dbd9fdf503b..1c4c965a18a 100644 --- a/api_docs/v2/LogsWarning.md +++ b/api_docs/v2/LogsWarning.md @@ -3,6 +3,7 @@ # LogsWarning A warning message indicating something that went wrong with the query + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/Metric.md b/api_docs/v2/Metric.md index ed27801821e..31098c445bf 100644 --- a/api_docs/v2/Metric.md +++ b/api_docs/v2/Metric.md @@ -3,6 +3,7 @@ # Metric Object for a single metric tag configuration. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricAllTags.md b/api_docs/v2/MetricAllTags.md index 8f127b51327..f0d1ea130dc 100644 --- a/api_docs/v2/MetricAllTags.md +++ b/api_docs/v2/MetricAllTags.md @@ -3,6 +3,7 @@ # MetricAllTags Object for a single metric's indexed tags. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricAllTagsAttributes.md b/api_docs/v2/MetricAllTagsAttributes.md index 44e8e8d5cd1..4d0e76954f0 100644 --- a/api_docs/v2/MetricAllTagsAttributes.md +++ b/api_docs/v2/MetricAllTagsAttributes.md @@ -3,6 +3,7 @@ # MetricAllTagsAttributes Object containing the definition of a metric's tags. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricAllTagsResponse.md b/api_docs/v2/MetricAllTagsResponse.md index 9adaa810c7a..7457f2f0b03 100644 --- a/api_docs/v2/MetricAllTagsResponse.md +++ b/api_docs/v2/MetricAllTagsResponse.md @@ -3,6 +3,7 @@ # MetricAllTagsResponse Response object that includes a single metric's indexed tags. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricDistinctVolume.md b/api_docs/v2/MetricDistinctVolume.md index f2b0fa94125..051dae55533 100644 --- a/api_docs/v2/MetricDistinctVolume.md +++ b/api_docs/v2/MetricDistinctVolume.md @@ -3,6 +3,7 @@ # MetricDistinctVolume Object for a single metric's distinct volume. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricDistinctVolumeAttributes.md b/api_docs/v2/MetricDistinctVolumeAttributes.md index 3c3efb82ac7..f80d335047c 100644 --- a/api_docs/v2/MetricDistinctVolumeAttributes.md +++ b/api_docs/v2/MetricDistinctVolumeAttributes.md @@ -3,6 +3,7 @@ # MetricDistinctVolumeAttributes Object containing the definition of a metric's distinct volume. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricIngestedIndexedVolume.md b/api_docs/v2/MetricIngestedIndexedVolume.md index 4dacad785d8..2cf4d0d04d4 100644 --- a/api_docs/v2/MetricIngestedIndexedVolume.md +++ b/api_docs/v2/MetricIngestedIndexedVolume.md @@ -3,6 +3,7 @@ # MetricIngestedIndexedVolume Object for a single metric's ingested and indexed volume. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricIngestedIndexedVolumeAttributes.md b/api_docs/v2/MetricIngestedIndexedVolumeAttributes.md index b63d2066372..1249aa79d80 100644 --- a/api_docs/v2/MetricIngestedIndexedVolumeAttributes.md +++ b/api_docs/v2/MetricIngestedIndexedVolumeAttributes.md @@ -3,6 +3,7 @@ # MetricIngestedIndexedVolumeAttributes Object containing the definition of a metric's ingested and indexed volume. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricTagConfiguration.md b/api_docs/v2/MetricTagConfiguration.md index 057f219feb2..240806883fe 100644 --- a/api_docs/v2/MetricTagConfiguration.md +++ b/api_docs/v2/MetricTagConfiguration.md @@ -3,6 +3,7 @@ # MetricTagConfiguration Object for a single metric tag configuration. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricTagConfigurationAttributes.md b/api_docs/v2/MetricTagConfigurationAttributes.md index 0e3fc361de7..64a27c00d7f 100644 --- a/api_docs/v2/MetricTagConfigurationAttributes.md +++ b/api_docs/v2/MetricTagConfigurationAttributes.md @@ -3,6 +3,7 @@ # MetricTagConfigurationAttributes Object containing the definition of a metric tag configuration attributes. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricTagConfigurationCreateAttributes.md b/api_docs/v2/MetricTagConfigurationCreateAttributes.md index 2db6e808e0f..2b973184ea0 100644 --- a/api_docs/v2/MetricTagConfigurationCreateAttributes.md +++ b/api_docs/v2/MetricTagConfigurationCreateAttributes.md @@ -3,6 +3,7 @@ # MetricTagConfigurationCreateAttributes Object containing the definition of a metric tag configuration to be created. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricTagConfigurationCreateData.md b/api_docs/v2/MetricTagConfigurationCreateData.md index 6fe88887bcc..5bd55eff3fc 100644 --- a/api_docs/v2/MetricTagConfigurationCreateData.md +++ b/api_docs/v2/MetricTagConfigurationCreateData.md @@ -3,6 +3,7 @@ # MetricTagConfigurationCreateData Object for a single metric to be configure tags on. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricTagConfigurationCreateRequest.md b/api_docs/v2/MetricTagConfigurationCreateRequest.md index a887ce99307..3428cf99d79 100644 --- a/api_docs/v2/MetricTagConfigurationCreateRequest.md +++ b/api_docs/v2/MetricTagConfigurationCreateRequest.md @@ -3,6 +3,7 @@ # MetricTagConfigurationCreateRequest Request object that includes the metric that you would like to configure tags for. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricTagConfigurationResponse.md b/api_docs/v2/MetricTagConfigurationResponse.md index 1838910b861..3487918ffaa 100644 --- a/api_docs/v2/MetricTagConfigurationResponse.md +++ b/api_docs/v2/MetricTagConfigurationResponse.md @@ -3,6 +3,7 @@ # MetricTagConfigurationResponse Response object which includes a single metric's tag configuration. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricTagConfigurationUpdateAttributes.md b/api_docs/v2/MetricTagConfigurationUpdateAttributes.md index 9dd3c0d781b..2481e6cb5c7 100644 --- a/api_docs/v2/MetricTagConfigurationUpdateAttributes.md +++ b/api_docs/v2/MetricTagConfigurationUpdateAttributes.md @@ -3,6 +3,7 @@ # MetricTagConfigurationUpdateAttributes Object containing the definition of a metric tag configuration to be updated. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricTagConfigurationUpdateData.md b/api_docs/v2/MetricTagConfigurationUpdateData.md index db9bfb353e2..e84514e89ec 100644 --- a/api_docs/v2/MetricTagConfigurationUpdateData.md +++ b/api_docs/v2/MetricTagConfigurationUpdateData.md @@ -3,6 +3,7 @@ # MetricTagConfigurationUpdateData Object for a single tag configuration to be edited. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricTagConfigurationUpdateRequest.md b/api_docs/v2/MetricTagConfigurationUpdateRequest.md index 70299faa487..bb6aa90a709 100644 --- a/api_docs/v2/MetricTagConfigurationUpdateRequest.md +++ b/api_docs/v2/MetricTagConfigurationUpdateRequest.md @@ -3,6 +3,7 @@ # MetricTagConfigurationUpdateRequest Request object that includes the metric that you would like to edit the tag configuration on. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricVolumesResponse.md b/api_docs/v2/MetricVolumesResponse.md index 4381fda3512..ab8ef6d1c65 100644 --- a/api_docs/v2/MetricVolumesResponse.md +++ b/api_docs/v2/MetricVolumesResponse.md @@ -3,6 +3,7 @@ # MetricVolumesResponse Response object which includes a single metric's volume. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/MetricsAndMetricTagConfigurationsResponse.md b/api_docs/v2/MetricsAndMetricTagConfigurationsResponse.md index a5bafdf8fd9..108364fa9b4 100644 --- a/api_docs/v2/MetricsAndMetricTagConfigurationsResponse.md +++ b/api_docs/v2/MetricsAndMetricTagConfigurationsResponse.md @@ -3,6 +3,7 @@ # MetricsAndMetricTagConfigurationsResponse Response object that includes metrics and metric tag configurations. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/Organization.md b/api_docs/v2/Organization.md index 1fc96cba632..9cef57893d3 100644 --- a/api_docs/v2/Organization.md +++ b/api_docs/v2/Organization.md @@ -3,6 +3,7 @@ # Organization Organization object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/OrganizationAttributes.md b/api_docs/v2/OrganizationAttributes.md index 870d633c983..859602142ce 100644 --- a/api_docs/v2/OrganizationAttributes.md +++ b/api_docs/v2/OrganizationAttributes.md @@ -3,6 +3,7 @@ # OrganizationAttributes Attributes of the organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/Pagination.md b/api_docs/v2/Pagination.md index ca940b448b7..ba03b9dc3b0 100644 --- a/api_docs/v2/Pagination.md +++ b/api_docs/v2/Pagination.md @@ -3,6 +3,7 @@ # Pagination Pagination object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/PartialAPIKey.md b/api_docs/v2/PartialAPIKey.md index 24fc25f9607..50be9dc0f64 100644 --- a/api_docs/v2/PartialAPIKey.md +++ b/api_docs/v2/PartialAPIKey.md @@ -3,6 +3,7 @@ # PartialAPIKey Partial Datadog API key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/PartialAPIKeyAttributes.md b/api_docs/v2/PartialAPIKeyAttributes.md index 5382ec41e3d..b762f30a35f 100644 --- a/api_docs/v2/PartialAPIKeyAttributes.md +++ b/api_docs/v2/PartialAPIKeyAttributes.md @@ -3,6 +3,7 @@ # PartialAPIKeyAttributes Attributes of a partial API key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/PartialApplicationKey.md b/api_docs/v2/PartialApplicationKey.md index 0bf0f415f70..d499638a840 100644 --- a/api_docs/v2/PartialApplicationKey.md +++ b/api_docs/v2/PartialApplicationKey.md @@ -3,6 +3,7 @@ # PartialApplicationKey Partial Datadog application key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/PartialApplicationKeyAttributes.md b/api_docs/v2/PartialApplicationKeyAttributes.md index 405af931c33..9e994caed17 100644 --- a/api_docs/v2/PartialApplicationKeyAttributes.md +++ b/api_docs/v2/PartialApplicationKeyAttributes.md @@ -3,6 +3,7 @@ # PartialApplicationKeyAttributes Attributes of a partial application key. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/Permission.md b/api_docs/v2/Permission.md index d10c08be4e8..c94bfba237a 100644 --- a/api_docs/v2/Permission.md +++ b/api_docs/v2/Permission.md @@ -3,6 +3,7 @@ # Permission Permission object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/PermissionAttributes.md b/api_docs/v2/PermissionAttributes.md index 572dc023cc7..b21e8ede063 100644 --- a/api_docs/v2/PermissionAttributes.md +++ b/api_docs/v2/PermissionAttributes.md @@ -3,6 +3,7 @@ # PermissionAttributes Attributes of a permission. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/PermissionsResponse.md b/api_docs/v2/PermissionsResponse.md index d58bb3f34ba..5d1d9a33544 100644 --- a/api_docs/v2/PermissionsResponse.md +++ b/api_docs/v2/PermissionsResponse.md @@ -3,6 +3,7 @@ # PermissionsResponse Payload with API-returned permissions. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ProcessSummariesMeta.md b/api_docs/v2/ProcessSummariesMeta.md index a3131766f91..e23e684412f 100644 --- a/api_docs/v2/ProcessSummariesMeta.md +++ b/api_docs/v2/ProcessSummariesMeta.md @@ -3,6 +3,7 @@ # ProcessSummariesMeta Response metadata object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ProcessSummariesMetaPage.md b/api_docs/v2/ProcessSummariesMetaPage.md index 7a87a017c0b..38b838d27c1 100644 --- a/api_docs/v2/ProcessSummariesMetaPage.md +++ b/api_docs/v2/ProcessSummariesMetaPage.md @@ -3,6 +3,7 @@ # ProcessSummariesMetaPage Paging attributes. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ProcessSummariesResponse.md b/api_docs/v2/ProcessSummariesResponse.md index f8942638ecf..66ae986b943 100644 --- a/api_docs/v2/ProcessSummariesResponse.md +++ b/api_docs/v2/ProcessSummariesResponse.md @@ -3,6 +3,7 @@ # ProcessSummariesResponse List of process summaries. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ProcessSummary.md b/api_docs/v2/ProcessSummary.md index fff8669b2d2..fbd6f7a2388 100644 --- a/api_docs/v2/ProcessSummary.md +++ b/api_docs/v2/ProcessSummary.md @@ -3,6 +3,7 @@ # ProcessSummary Process summary object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ProcessSummaryAttributes.md b/api_docs/v2/ProcessSummaryAttributes.md index ec15facca51..db62924de35 100644 --- a/api_docs/v2/ProcessSummaryAttributes.md +++ b/api_docs/v2/ProcessSummaryAttributes.md @@ -3,6 +3,7 @@ # ProcessSummaryAttributes Attributes for a process summary. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToIncidentIntegrationMetadataData.md b/api_docs/v2/RelationshipToIncidentIntegrationMetadataData.md index dd029cf67f5..1df2d9c8502 100644 --- a/api_docs/v2/RelationshipToIncidentIntegrationMetadataData.md +++ b/api_docs/v2/RelationshipToIncidentIntegrationMetadataData.md @@ -3,6 +3,7 @@ # RelationshipToIncidentIntegrationMetadataData A relationship reference for an integration metadata object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToIncidentIntegrationMetadatas.md b/api_docs/v2/RelationshipToIncidentIntegrationMetadatas.md index fc4a541c8cf..1f22776ed04 100644 --- a/api_docs/v2/RelationshipToIncidentIntegrationMetadatas.md +++ b/api_docs/v2/RelationshipToIncidentIntegrationMetadatas.md @@ -3,6 +3,7 @@ # RelationshipToIncidentIntegrationMetadatas A relationship reference for multiple integration metadata objects. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToIncidentPostmortem.md b/api_docs/v2/RelationshipToIncidentPostmortem.md index 26d24815858..f1379b660c6 100644 --- a/api_docs/v2/RelationshipToIncidentPostmortem.md +++ b/api_docs/v2/RelationshipToIncidentPostmortem.md @@ -3,6 +3,7 @@ # RelationshipToIncidentPostmortem A relationship reference for postmortems. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToIncidentPostmortemData.md b/api_docs/v2/RelationshipToIncidentPostmortemData.md index 16ce9b81321..e8030cf2aeb 100644 --- a/api_docs/v2/RelationshipToIncidentPostmortemData.md +++ b/api_docs/v2/RelationshipToIncidentPostmortemData.md @@ -3,6 +3,7 @@ # RelationshipToIncidentPostmortemData The postmortem relationship data. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToOrganization.md b/api_docs/v2/RelationshipToOrganization.md index f9ed5a3f288..d90be206e8d 100644 --- a/api_docs/v2/RelationshipToOrganization.md +++ b/api_docs/v2/RelationshipToOrganization.md @@ -3,6 +3,7 @@ # RelationshipToOrganization Relationship to an organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToOrganizationData.md b/api_docs/v2/RelationshipToOrganizationData.md index 2730c92ac25..9ae1fd92b49 100644 --- a/api_docs/v2/RelationshipToOrganizationData.md +++ b/api_docs/v2/RelationshipToOrganizationData.md @@ -3,6 +3,7 @@ # RelationshipToOrganizationData Relationship to organization object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToOrganizations.md b/api_docs/v2/RelationshipToOrganizations.md index fb1a445a862..f6927f5b395 100644 --- a/api_docs/v2/RelationshipToOrganizations.md +++ b/api_docs/v2/RelationshipToOrganizations.md @@ -3,6 +3,7 @@ # RelationshipToOrganizations Relationship to organizations. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToPermission.md b/api_docs/v2/RelationshipToPermission.md index 5e55ecb51e5..71f73299929 100644 --- a/api_docs/v2/RelationshipToPermission.md +++ b/api_docs/v2/RelationshipToPermission.md @@ -3,6 +3,7 @@ # RelationshipToPermission Relationship to a permissions object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToPermissionData.md b/api_docs/v2/RelationshipToPermissionData.md index 0d7ed527c85..8d74a2941dc 100644 --- a/api_docs/v2/RelationshipToPermissionData.md +++ b/api_docs/v2/RelationshipToPermissionData.md @@ -3,6 +3,7 @@ # RelationshipToPermissionData Relationship to permission object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToPermissions.md b/api_docs/v2/RelationshipToPermissions.md index af3227c528c..aac924bdbb4 100644 --- a/api_docs/v2/RelationshipToPermissions.md +++ b/api_docs/v2/RelationshipToPermissions.md @@ -3,6 +3,7 @@ # RelationshipToPermissions Relationship to multiple permissions objects. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToRole.md b/api_docs/v2/RelationshipToRole.md index 79e8e300ab3..bf49e6e61ca 100644 --- a/api_docs/v2/RelationshipToRole.md +++ b/api_docs/v2/RelationshipToRole.md @@ -3,6 +3,7 @@ # RelationshipToRole Relationship to role. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToRoleData.md b/api_docs/v2/RelationshipToRoleData.md index 7c382a9ae5b..55ddc839008 100644 --- a/api_docs/v2/RelationshipToRoleData.md +++ b/api_docs/v2/RelationshipToRoleData.md @@ -3,6 +3,7 @@ # RelationshipToRoleData Relationship to role object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToRoles.md b/api_docs/v2/RelationshipToRoles.md index 9146ec4ba19..d9dec333a66 100644 --- a/api_docs/v2/RelationshipToRoles.md +++ b/api_docs/v2/RelationshipToRoles.md @@ -3,6 +3,7 @@ # RelationshipToRoles Relationship to roles. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToUser.md b/api_docs/v2/RelationshipToUser.md index ec114fb08b3..db2d5ade8db 100644 --- a/api_docs/v2/RelationshipToUser.md +++ b/api_docs/v2/RelationshipToUser.md @@ -3,6 +3,7 @@ # RelationshipToUser Relationship to user. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToUserData.md b/api_docs/v2/RelationshipToUserData.md index 6618a89e2e0..5c428058b45 100644 --- a/api_docs/v2/RelationshipToUserData.md +++ b/api_docs/v2/RelationshipToUserData.md @@ -3,6 +3,7 @@ # RelationshipToUserData Relationship to user object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RelationshipToUsers.md b/api_docs/v2/RelationshipToUsers.md index fa2f88f77e3..67cf1d5fa3e 100644 --- a/api_docs/v2/RelationshipToUsers.md +++ b/api_docs/v2/RelationshipToUsers.md @@ -3,6 +3,7 @@ # RelationshipToUsers Relationship to users. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/ResponseMetaAttributes.md b/api_docs/v2/ResponseMetaAttributes.md index 7ad4361c8ab..bac13c8e6e9 100644 --- a/api_docs/v2/ResponseMetaAttributes.md +++ b/api_docs/v2/ResponseMetaAttributes.md @@ -3,6 +3,7 @@ # ResponseMetaAttributes Object describing meta attributes of response. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/Role.md b/api_docs/v2/Role.md index 0f24186a6ba..bc0ccc31f66 100644 --- a/api_docs/v2/Role.md +++ b/api_docs/v2/Role.md @@ -3,6 +3,7 @@ # Role Role object returned by the API. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleAttributes.md b/api_docs/v2/RoleAttributes.md index deddeaa719b..f9faaec1369 100644 --- a/api_docs/v2/RoleAttributes.md +++ b/api_docs/v2/RoleAttributes.md @@ -3,6 +3,7 @@ # RoleAttributes Attributes of the role. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleCreateAttributes.md b/api_docs/v2/RoleCreateAttributes.md index 5c37888c92d..80d42bdc71c 100644 --- a/api_docs/v2/RoleCreateAttributes.md +++ b/api_docs/v2/RoleCreateAttributes.md @@ -3,6 +3,7 @@ # RoleCreateAttributes Attributes of the created role. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleCreateData.md b/api_docs/v2/RoleCreateData.md index 4f25801a0b0..ee734849cb8 100644 --- a/api_docs/v2/RoleCreateData.md +++ b/api_docs/v2/RoleCreateData.md @@ -3,6 +3,7 @@ # RoleCreateData Data related to the creation of a role. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleCreateRequest.md b/api_docs/v2/RoleCreateRequest.md index e60214000f7..0d0769438d8 100644 --- a/api_docs/v2/RoleCreateRequest.md +++ b/api_docs/v2/RoleCreateRequest.md @@ -3,6 +3,7 @@ # RoleCreateRequest Create a role. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleCreateResponse.md b/api_docs/v2/RoleCreateResponse.md index f9344f53fea..2984e0f881a 100644 --- a/api_docs/v2/RoleCreateResponse.md +++ b/api_docs/v2/RoleCreateResponse.md @@ -3,6 +3,7 @@ # RoleCreateResponse Response containing information about a created role. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleCreateResponseData.md b/api_docs/v2/RoleCreateResponseData.md index 0279ea95c30..eca70aeb787 100644 --- a/api_docs/v2/RoleCreateResponseData.md +++ b/api_docs/v2/RoleCreateResponseData.md @@ -3,6 +3,7 @@ # RoleCreateResponseData Role object returned by the API. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleRelationships.md b/api_docs/v2/RoleRelationships.md index e17077e93eb..46ea3af6fd9 100644 --- a/api_docs/v2/RoleRelationships.md +++ b/api_docs/v2/RoleRelationships.md @@ -3,6 +3,7 @@ # RoleRelationships Relationships of the role object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleResponse.md b/api_docs/v2/RoleResponse.md index 7fdfe3c646d..1ea6def5206 100644 --- a/api_docs/v2/RoleResponse.md +++ b/api_docs/v2/RoleResponse.md @@ -3,6 +3,7 @@ # RoleResponse Response containing information about a single role. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleResponseRelationships.md b/api_docs/v2/RoleResponseRelationships.md index 6a8db9a0879..796713b30ac 100644 --- a/api_docs/v2/RoleResponseRelationships.md +++ b/api_docs/v2/RoleResponseRelationships.md @@ -3,6 +3,7 @@ # RoleResponseRelationships Relationships of the role object returned by the API. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleUpdateAttributes.md b/api_docs/v2/RoleUpdateAttributes.md index 651c2f4ce72..65617404c21 100644 --- a/api_docs/v2/RoleUpdateAttributes.md +++ b/api_docs/v2/RoleUpdateAttributes.md @@ -3,6 +3,7 @@ # RoleUpdateAttributes Attributes of the role. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleUpdateData.md b/api_docs/v2/RoleUpdateData.md index 342044ed6cc..caac4fd2820 100644 --- a/api_docs/v2/RoleUpdateData.md +++ b/api_docs/v2/RoleUpdateData.md @@ -3,6 +3,7 @@ # RoleUpdateData Data related to the update of a role. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleUpdateRequest.md b/api_docs/v2/RoleUpdateRequest.md index 70838a29819..9194626393e 100644 --- a/api_docs/v2/RoleUpdateRequest.md +++ b/api_docs/v2/RoleUpdateRequest.md @@ -3,6 +3,7 @@ # RoleUpdateRequest Update a role. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleUpdateResponse.md b/api_docs/v2/RoleUpdateResponse.md index b9597231806..938dd09b835 100644 --- a/api_docs/v2/RoleUpdateResponse.md +++ b/api_docs/v2/RoleUpdateResponse.md @@ -3,6 +3,7 @@ # RoleUpdateResponse Response containing information about an updated role. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RoleUpdateResponseData.md b/api_docs/v2/RoleUpdateResponseData.md index a1bb5c6a820..af4033ce1dd 100644 --- a/api_docs/v2/RoleUpdateResponseData.md +++ b/api_docs/v2/RoleUpdateResponseData.md @@ -3,6 +3,7 @@ # RoleUpdateResponseData Role object returned by the API. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/RolesResponse.md b/api_docs/v2/RolesResponse.md index e5933025db3..6c95178c6c4 100644 --- a/api_docs/v2/RolesResponse.md +++ b/api_docs/v2/RolesResponse.md @@ -3,6 +3,7 @@ # RolesResponse Response containing information about multiple roles. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringFilter.md b/api_docs/v2/SecurityMonitoringFilter.md index fc156800f45..6aa9be8de28 100644 --- a/api_docs/v2/SecurityMonitoringFilter.md +++ b/api_docs/v2/SecurityMonitoringFilter.md @@ -3,6 +3,7 @@ # SecurityMonitoringFilter The rule's suppression filter. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringListRulesResponse.md b/api_docs/v2/SecurityMonitoringListRulesResponse.md index a95ef16516d..439a9a07104 100644 --- a/api_docs/v2/SecurityMonitoringListRulesResponse.md +++ b/api_docs/v2/SecurityMonitoringListRulesResponse.md @@ -3,6 +3,7 @@ # SecurityMonitoringListRulesResponse List of rules. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringRuleCase.md b/api_docs/v2/SecurityMonitoringRuleCase.md index 8ed8eb130af..1fa1d0838d3 100644 --- a/api_docs/v2/SecurityMonitoringRuleCase.md +++ b/api_docs/v2/SecurityMonitoringRuleCase.md @@ -3,6 +3,7 @@ # SecurityMonitoringRuleCase Case when signal is generated. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringRuleCaseCreate.md b/api_docs/v2/SecurityMonitoringRuleCaseCreate.md index 5caa2bc3dc2..8d84dd98dc2 100644 --- a/api_docs/v2/SecurityMonitoringRuleCaseCreate.md +++ b/api_docs/v2/SecurityMonitoringRuleCaseCreate.md @@ -3,6 +3,7 @@ # SecurityMonitoringRuleCaseCreate Case when signal is generated. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringRuleCreatePayload.md b/api_docs/v2/SecurityMonitoringRuleCreatePayload.md index e2ec1c54027..3c720f67ce1 100644 --- a/api_docs/v2/SecurityMonitoringRuleCreatePayload.md +++ b/api_docs/v2/SecurityMonitoringRuleCreatePayload.md @@ -3,6 +3,7 @@ # SecurityMonitoringRuleCreatePayload Create a new rule. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringRuleNewValueOptions.md b/api_docs/v2/SecurityMonitoringRuleNewValueOptions.md index 883bbc595ab..9e3215f36d8 100644 --- a/api_docs/v2/SecurityMonitoringRuleNewValueOptions.md +++ b/api_docs/v2/SecurityMonitoringRuleNewValueOptions.md @@ -3,6 +3,7 @@ # SecurityMonitoringRuleNewValueOptions Options on new value rules. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringRuleOptions.md b/api_docs/v2/SecurityMonitoringRuleOptions.md index b225bcc2491..9b262ed1d37 100644 --- a/api_docs/v2/SecurityMonitoringRuleOptions.md +++ b/api_docs/v2/SecurityMonitoringRuleOptions.md @@ -3,6 +3,7 @@ # SecurityMonitoringRuleOptions Options on rules. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringRuleQuery.md b/api_docs/v2/SecurityMonitoringRuleQuery.md index 8533f1559ca..949a173c96f 100644 --- a/api_docs/v2/SecurityMonitoringRuleQuery.md +++ b/api_docs/v2/SecurityMonitoringRuleQuery.md @@ -3,6 +3,7 @@ # SecurityMonitoringRuleQuery Query for matching rule. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringRuleQueryCreate.md b/api_docs/v2/SecurityMonitoringRuleQueryCreate.md index cf15beb41cc..9be512fd2a1 100644 --- a/api_docs/v2/SecurityMonitoringRuleQueryCreate.md +++ b/api_docs/v2/SecurityMonitoringRuleQueryCreate.md @@ -3,6 +3,7 @@ # SecurityMonitoringRuleQueryCreate Query for matching rule. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringRuleResponse.md b/api_docs/v2/SecurityMonitoringRuleResponse.md index 36e40cde886..e9a58923f8c 100644 --- a/api_docs/v2/SecurityMonitoringRuleResponse.md +++ b/api_docs/v2/SecurityMonitoringRuleResponse.md @@ -3,6 +3,7 @@ # SecurityMonitoringRuleResponse Detection rule. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringRuleUpdatePayload.md b/api_docs/v2/SecurityMonitoringRuleUpdatePayload.md index d2c79d9e844..b407261b3b3 100644 --- a/api_docs/v2/SecurityMonitoringRuleUpdatePayload.md +++ b/api_docs/v2/SecurityMonitoringRuleUpdatePayload.md @@ -3,6 +3,7 @@ # SecurityMonitoringRuleUpdatePayload Update an existing rule. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringSignal.md b/api_docs/v2/SecurityMonitoringSignal.md index d04f770938a..e47c68846b0 100644 --- a/api_docs/v2/SecurityMonitoringSignal.md +++ b/api_docs/v2/SecurityMonitoringSignal.md @@ -3,6 +3,7 @@ # SecurityMonitoringSignal Object description of a security signal. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringSignalAttributes.md b/api_docs/v2/SecurityMonitoringSignalAttributes.md index b64a711ebd4..497b3b1a8e7 100644 --- a/api_docs/v2/SecurityMonitoringSignalAttributes.md +++ b/api_docs/v2/SecurityMonitoringSignalAttributes.md @@ -3,6 +3,7 @@ # SecurityMonitoringSignalAttributes The object containing all signal attributes and their associated values. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringSignalListRequest.md b/api_docs/v2/SecurityMonitoringSignalListRequest.md index 786e75f7c23..3b0a9478502 100644 --- a/api_docs/v2/SecurityMonitoringSignalListRequest.md +++ b/api_docs/v2/SecurityMonitoringSignalListRequest.md @@ -3,6 +3,7 @@ # SecurityMonitoringSignalListRequest The request for a security signal list. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringSignalListRequestFilter.md b/api_docs/v2/SecurityMonitoringSignalListRequestFilter.md index ad234a685a9..f3b3ed9ce8f 100644 --- a/api_docs/v2/SecurityMonitoringSignalListRequestFilter.md +++ b/api_docs/v2/SecurityMonitoringSignalListRequestFilter.md @@ -3,6 +3,7 @@ # SecurityMonitoringSignalListRequestFilter Search filters for listing security signals. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringSignalListRequestPage.md b/api_docs/v2/SecurityMonitoringSignalListRequestPage.md index 54d22964e7f..817a4bb5e80 100644 --- a/api_docs/v2/SecurityMonitoringSignalListRequestPage.md +++ b/api_docs/v2/SecurityMonitoringSignalListRequestPage.md @@ -3,6 +3,7 @@ # SecurityMonitoringSignalListRequestPage The paging attributes for listing security signals. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringSignalsListResponse.md b/api_docs/v2/SecurityMonitoringSignalsListResponse.md index 76589633dff..995d6050df0 100644 --- a/api_docs/v2/SecurityMonitoringSignalsListResponse.md +++ b/api_docs/v2/SecurityMonitoringSignalsListResponse.md @@ -3,6 +3,7 @@ # SecurityMonitoringSignalsListResponse The response object with all security signals matching the request and pagination information. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringSignalsListResponseLinks.md b/api_docs/v2/SecurityMonitoringSignalsListResponseLinks.md index a40d7719f0c..4939bf387bd 100644 --- a/api_docs/v2/SecurityMonitoringSignalsListResponseLinks.md +++ b/api_docs/v2/SecurityMonitoringSignalsListResponseLinks.md @@ -3,6 +3,7 @@ # SecurityMonitoringSignalsListResponseLinks Links attributes. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringSignalsListResponseMeta.md b/api_docs/v2/SecurityMonitoringSignalsListResponseMeta.md index fecb387538d..61184350518 100644 --- a/api_docs/v2/SecurityMonitoringSignalsListResponseMeta.md +++ b/api_docs/v2/SecurityMonitoringSignalsListResponseMeta.md @@ -3,6 +3,7 @@ # SecurityMonitoringSignalsListResponseMeta Meta attributes. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/SecurityMonitoringSignalsListResponseMetaPage.md b/api_docs/v2/SecurityMonitoringSignalsListResponseMetaPage.md index 0062c375bf0..c3b9964247e 100644 --- a/api_docs/v2/SecurityMonitoringSignalsListResponseMetaPage.md +++ b/api_docs/v2/SecurityMonitoringSignalsListResponseMetaPage.md @@ -3,6 +3,7 @@ # SecurityMonitoringSignalsListResponseMetaPage Paging attributes. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/User.md b/api_docs/v2/User.md index 37f6eab4a91..eb8af98df9f 100644 --- a/api_docs/v2/User.md +++ b/api_docs/v2/User.md @@ -3,6 +3,7 @@ # User User object returned by the API. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserAttributes.md b/api_docs/v2/UserAttributes.md index eb8d7702e8f..f8e78ef11c0 100644 --- a/api_docs/v2/UserAttributes.md +++ b/api_docs/v2/UserAttributes.md @@ -3,6 +3,7 @@ # UserAttributes Attributes of user object returned by the API. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserCreateAttributes.md b/api_docs/v2/UserCreateAttributes.md index 106c901c825..2781a6a121b 100644 --- a/api_docs/v2/UserCreateAttributes.md +++ b/api_docs/v2/UserCreateAttributes.md @@ -3,6 +3,7 @@ # UserCreateAttributes Attributes of the created user. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserCreateData.md b/api_docs/v2/UserCreateData.md index e4ff1334bfe..0d937a0e2fd 100644 --- a/api_docs/v2/UserCreateData.md +++ b/api_docs/v2/UserCreateData.md @@ -3,6 +3,7 @@ # UserCreateData Object to create a user. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserCreateRequest.md b/api_docs/v2/UserCreateRequest.md index 3dfd7bb5e32..dd199d2cd5d 100644 --- a/api_docs/v2/UserCreateRequest.md +++ b/api_docs/v2/UserCreateRequest.md @@ -3,6 +3,7 @@ # UserCreateRequest Create a user. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserInvitationData.md b/api_docs/v2/UserInvitationData.md index efaf97b003a..35067e1ad75 100644 --- a/api_docs/v2/UserInvitationData.md +++ b/api_docs/v2/UserInvitationData.md @@ -3,6 +3,7 @@ # UserInvitationData Object to create a user invitation. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserInvitationDataAttributes.md b/api_docs/v2/UserInvitationDataAttributes.md index 1bda5c0e392..3d944d358d9 100644 --- a/api_docs/v2/UserInvitationDataAttributes.md +++ b/api_docs/v2/UserInvitationDataAttributes.md @@ -3,6 +3,7 @@ # UserInvitationDataAttributes Attributes of a user invitation. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserInvitationRelationships.md b/api_docs/v2/UserInvitationRelationships.md index 8c06f800bc1..a6b43939ace 100644 --- a/api_docs/v2/UserInvitationRelationships.md +++ b/api_docs/v2/UserInvitationRelationships.md @@ -3,6 +3,7 @@ # UserInvitationRelationships Relationships data for user invitation. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserInvitationResponse.md b/api_docs/v2/UserInvitationResponse.md index 64c50d64e5b..8aac3ee501d 100644 --- a/api_docs/v2/UserInvitationResponse.md +++ b/api_docs/v2/UserInvitationResponse.md @@ -3,6 +3,7 @@ # UserInvitationResponse User invitation as returned by the API. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserInvitationResponseData.md b/api_docs/v2/UserInvitationResponseData.md index 4db7c9b648c..5157f137e0c 100644 --- a/api_docs/v2/UserInvitationResponseData.md +++ b/api_docs/v2/UserInvitationResponseData.md @@ -3,6 +3,7 @@ # UserInvitationResponseData Object of a user invitation returned by the API. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserInvitationsRequest.md b/api_docs/v2/UserInvitationsRequest.md index 4cd84944d18..d9e43430ed4 100644 --- a/api_docs/v2/UserInvitationsRequest.md +++ b/api_docs/v2/UserInvitationsRequest.md @@ -3,6 +3,7 @@ # UserInvitationsRequest Object to invite users to join the organization. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserInvitationsResponse.md b/api_docs/v2/UserInvitationsResponse.md index d4d029be2e2..8ea7db862df 100644 --- a/api_docs/v2/UserInvitationsResponse.md +++ b/api_docs/v2/UserInvitationsResponse.md @@ -3,6 +3,7 @@ # UserInvitationsResponse User invitations as returned by the API. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserRelationships.md b/api_docs/v2/UserRelationships.md index f79f722fe94..4a8f9e91e8e 100644 --- a/api_docs/v2/UserRelationships.md +++ b/api_docs/v2/UserRelationships.md @@ -3,6 +3,7 @@ # UserRelationships Relationships of the user object. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserResponse.md b/api_docs/v2/UserResponse.md index 88a7a9f518c..08b5cc7f1f0 100644 --- a/api_docs/v2/UserResponse.md +++ b/api_docs/v2/UserResponse.md @@ -3,6 +3,7 @@ # UserResponse Response containing information about a single user. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserResponseRelationships.md b/api_docs/v2/UserResponseRelationships.md index 0d787de51bb..ffff90e91b5 100644 --- a/api_docs/v2/UserResponseRelationships.md +++ b/api_docs/v2/UserResponseRelationships.md @@ -3,6 +3,7 @@ # UserResponseRelationships Relationships of the user object returned by the API. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserUpdateAttributes.md b/api_docs/v2/UserUpdateAttributes.md index 2882483ad84..db4b6b01d8f 100644 --- a/api_docs/v2/UserUpdateAttributes.md +++ b/api_docs/v2/UserUpdateAttributes.md @@ -3,6 +3,7 @@ # UserUpdateAttributes Attributes of the edited user. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserUpdateData.md b/api_docs/v2/UserUpdateData.md index 00d50e79ca5..5de8590b933 100644 --- a/api_docs/v2/UserUpdateData.md +++ b/api_docs/v2/UserUpdateData.md @@ -3,6 +3,7 @@ # UserUpdateData Object to update a user. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UserUpdateRequest.md b/api_docs/v2/UserUpdateRequest.md index f1922159e42..9e29692c600 100644 --- a/api_docs/v2/UserUpdateRequest.md +++ b/api_docs/v2/UserUpdateRequest.md @@ -3,6 +3,7 @@ # UserUpdateRequest Update a user. + ## Properties Name | Type | Description | Notes diff --git a/api_docs/v2/UsersResponse.md b/api_docs/v2/UsersResponse.md index 8d0d2f5142e..89a10f33d64 100644 --- a/api_docs/v2/UsersResponse.md +++ b/api_docs/v2/UsersResponse.md @@ -3,6 +3,7 @@ # UsersResponse Response containing information about multiple users. + ## Properties Name | Type | Description | Notes