();
- authentications.put("APIKeyHeader", new ApiKeyAuth("header", "API-Key"));
- authentications.put("basicAuth", new HttpBasicAuth());
+ authentications = new HashMap<>();
+ Authentication auth = null;
+ if (authMap != null) {
+ auth = authMap.get("APIKeyHeader");
+ }
+ if (auth instanceof ApiKeyAuth) {
+ authentications.put("APIKeyHeader", auth);
+ } else {
+ authentications.put("APIKeyHeader", new ApiKeyAuth("header", "API-Key"));
+ }
+ if (authMap != null) {
+ auth = authMap.get("basicAuth");
+ }
+ if (auth instanceof HttpBasicAuth) {
+ authentications.put("basicAuth", auth);
+ } else {
+ authentications.put("basicAuth", new HttpBasicAuth());
+ }
+ if (authMap != null) {
+ auth = authMap.get("bearerAuth");
+ }
+ if (auth instanceof HttpBearerAuth) {
+ authentications.put("bearerAuth", auth);
+ } else {
+ authentications.put("bearerAuth", new HttpBearerAuth("bearer"));
+ }
// Prevent the authentications from being modified.
authentications = Collections.unmodifiableMap(authentications);
+
+ // Setup authentication lookup (key: authentication alias, value: authentication name)
+ authenticationLookup = new HashMap<>();
}
/**
* Gets the JSON instance to do JSON serialization and deserialization.
+ *
* @return JSON
*/
public JSON getJSON() {
return json;
}
+ /**
+ * Getter for the field httpClient.
+ *
+ * @return a {@link jakarta.ws.rs.client.Client} object.
+ */
public Client getHttpClient() {
return httpClient;
}
+ /**
+ * Setter for the field httpClient.
+ *
+ * @param httpClient a {@link jakarta.ws.rs.client.Client} object.
+ * @return a {@link ApiClient} object.
+ */
public ApiClient setHttpClient(Client httpClient) {
this.httpClient = httpClient;
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.
+ * @return a {@link ApiClient} object.
+ */
public ApiClient setBasePath(String basePath) {
this.basePath = basePath;
return this;
}
/**
- * Gets the status code of the previous request
- * @return Status code
+ * Getter for the field servers.
+ *
+ * @return a {@link java.util.List} of servers.
+ */
+ public List getServers() {
+ return servers;
+ }
+
+ /**
+ * Setter for the field servers.
+ *
+ * @param servers a {@link java.util.List} of servers.
+ * @return a {@link ApiClient} object.
*/
- public int getStatusCode() {
- return statusCode;
+ public ApiClient setServers(List servers) {
+ this.servers = servers;
+ updateBasePath();
+ return this;
}
/**
- * Gets the response headers of the previous request
- * @return Response headers
+ * Getter for the field serverIndex.
+ *
+ * @return a {@link java.lang.Integer} object.
*/
- public Map> getResponseHeaders() {
- return responseHeaders;
+ public Integer getServerIndex() {
+ return serverIndex;
+ }
+
+ /**
+ * Setter for the field serverIndex.
+ *
+ * @param serverIndex the server index
+ * @return a {@link ApiClient} object.
+ */
+ public ApiClient setServerIndex(Integer serverIndex) {
+ this.serverIndex = serverIndex;
+ updateBasePath();
+ return this;
+ }
+
+ /**
+ * Getter for the field serverVariables.
+ *
+ * @return a {@link java.util.Map} of server variables.
+ */
+ public Map getServerVariables() {
+ return serverVariables;
+ }
+
+ /**
+ * Setter for the field serverVariables.
+ *
+ * @param serverVariables a {@link java.util.Map} of server variables.
+ * @return a {@link ApiClient} object.
+ */
+ public ApiClient setServerVariables(Map serverVariables) {
+ this.serverVariables = serverVariables;
+ updateBasePath();
+ return this;
+ }
+
+ protected void updateBasePath() {
+ if (serverIndex != null) {
+ setBasePath(servers.get(serverIndex).URL(serverVariables));
+ }
}
/**
* Get authentications (key: authentication name, value: authentication).
+ *
* @return Map of authentication object
*/
public Map getAuthentications() {
@@ -148,13 +312,15 @@ public Authentication getAuthentication(String authName) {
/**
* Helper method to set username for the first HTTP basic authentication.
+ *
* @param username Username
+ * @return a {@link ApiClient} object.
*/
- 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!");
@@ -162,13 +328,15 @@ public void setUsername(String username) {
/**
* Helper method to set password for the first HTTP basic authentication.
+ *
* @param password Password
+ * @return a {@link ApiClient} object.
*/
- 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!");
@@ -176,70 +344,144 @@ public void setPassword(String password) {
/**
* Helper method to set API key value for the first API key authentication.
+ *
* @param apiKey API key
+ * @return a {@link ApiClient} object.
*/
- 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!");
}
+ /**
+ * Helper method to configure authentications which respects aliases of API keys.
+ *
+ * @param secrets Hash map from authentication name to its secret.
+ * @return a {@link ApiClient} object.
+ */
+ public ApiClient configureApiKeys(Map 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);
+ String secret = secrets.get(name);
+ if (secret != null) {
+ ((ApiKeyAuth) auth).setApiKey(secret);
+ }
+ }
+ }
+ return this;
+ }
+
/**
* Helper method to set API key prefix for the first API key authentication.
+ *
* @param apiKeyPrefix API key prefix
+ * @return a {@link ApiClient} object.
*/
- 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!");
}
/**
- * Helper method to set access token for the first OAuth2 authentication.
- * @param accessToken Access token
+ * Helper method to set bearer token for the first Bearer authentication.
+ *
+ * @param bearerToken Bearer token
+ * @return a {@link ApiClient} object.
*/
- public void setAccessToken(String accessToken) {
+ public ApiClient setBearerToken(String bearerToken) {
for (Authentication auth : authentications.values()) {
- if (auth instanceof OAuth) {
- ((OAuth) auth).setAccessToken(accessToken);
- return;
+ if (auth instanceof HttpBearerAuth) {
+ ((HttpBearerAuth) auth).setBearerToken(bearerToken);
+ return this;
}
}
- throw new RuntimeException("No OAuth2 authentication configured!");
+ throw new RuntimeException("No Bearer authentication configured!");
}
/**
* Set the User-Agent header's value (by adding to the default header map).
+ *
* @param userAgent Http user agent
- * @return API client
+ * @return a {@link ApiClient} object.
*/
public ApiClient setUserAgent(String userAgent) {
+ this.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.
*
* @param key The header's key
* @param value The header's value
- * @return API client
+ * @return a {@link ApiClient} object.
*/
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 a {@link ApiClient} object.
+ */
+ public ApiClient addDefaultCookie(String key, String value) {
+ defaultCookieMap.put(key, value);
+ 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 a {@link ApiClient} object.
+ */
+ 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
*/
public boolean isDebugging() {
@@ -250,19 +492,20 @@ public boolean isDebugging() {
* Enable/disable debugging for this API client.
*
* @param debugging To enable (true) or disable (false) debugging
- * @return API client
+ * @return a {@link ApiClient} object.
*/
public ApiClient setDebugging(boolean debugging) {
this.debugging = debugging;
+ applyDebugSetting(this.clientConfig);
// Rebuild HTTP Client according to the new "debugging" value.
- this.httpClient = buildHttpClient(debugging);
+ this.httpClient = buildHttpClient();
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.
+ * the system's default temporary folder.
*
* @return Temp folder path
*/
@@ -272,8 +515,9 @@ public String getTempFolderPath() {
/**
* Set temp folder path
+ *
* @param tempFolderPath Temp folder path
- * @return API client
+ * @return a {@link ApiClient} object.
*/
public ApiClient setTempFolderPath(String tempFolderPath) {
this.tempFolderPath = tempFolderPath;
@@ -282,6 +526,7 @@ public ApiClient setTempFolderPath(String tempFolderPath) {
/**
* Connect timeout (in milliseconds).
+ *
* @return Connection timeout
*/
public int getConnectTimeout() {
@@ -292,8 +537,9 @@ public int getConnectTimeout() {
* 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
+ * @return a {@link ApiClient} object.
*/
public ApiClient setConnectTimeout(int connectionTimeout) {
this.connectionTimeout = connectionTimeout;
@@ -303,18 +549,20 @@ public ApiClient setConnectTimeout(int connectionTimeout) {
/**
* 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
+ * @return a {@link ApiClient} object.
*/
public ApiClient setReadTimeout(int readTimeout) {
this.readTimeout = readTimeout;
@@ -324,6 +572,7 @@ public ApiClient setReadTimeout(int readTimeout) {
/**
* Get the date format used to parse/format date parameters.
+ *
* @return Date format
*/
public DateFormat getDateFormat() {
@@ -332,8 +581,9 @@ public DateFormat getDateFormat() {
/**
* Set the date format used to parse/format date parameters.
+ *
* @param dateFormat Date format
- * @return API client
+ * @return a {@link ApiClient} object.
*/
public ApiClient setDateFormat(DateFormat dateFormat) {
this.dateFormat = dateFormat;
@@ -344,6 +594,7 @@ public ApiClient setDateFormat(DateFormat dateFormat) {
/**
* Parse the given string into Date object.
+ *
* @param str String
* @return Date
*/
@@ -357,6 +608,7 @@ public Date parseDate(String str) {
/**
* Format the given Date object into string.
+ *
* @param date Date
* @return Date in string format
*/
@@ -366,6 +618,7 @@ public String formatDate(Date date) {
/**
* Format the given parameter object into string.
+ *
* @param param Object
* @return Object in string format
*/
@@ -374,9 +627,11 @@ public String parameterToString(Object param) {
return "";
} else if (param instanceof Date) {
return formatDate((Date) param);
- } else if (param instanceof Collection) {
+ } else if (param instanceof OffsetDateTime) {
+ return formatOffsetDateTime((OffsetDateTime) param);
+ } 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(',');
}
@@ -390,20 +645,21 @@ public String parameterToString(Object 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();
+ List params = new ArrayList<>();
// preconditions
if (name == null || name.isEmpty() || value == null) return params;
- Collection valueCollection;
- if (value instanceof Collection) {
- valueCollection = (Collection) value;
+ Collection> valueCollection;
+ if (value instanceof Collection>) {
+ valueCollection = (Collection>) value;
} else {
params.add(new Pair(name, parameterToString(value)));
return params;
@@ -455,13 +711,13 @@ public List parameterToPairs(String collectionFormat, String name, Object
* application/json; charset=UTF8
* APPLICATION/JSON
* application/vnd.company+json
- * "* / *" is also default to JSON
+ * "*{@literal /}*" is also considered JSON by this method.
+ *
* @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("*/*"));
+ return mime != null && (mime.equals("*/*") || JSON_MIME_PATTERN.matcher(mime).matches());
}
/**
@@ -473,8 +729,8 @@ public boolean isJsonMime(String mime) {
* @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) {
+ public String selectHeaderAccept(String... accepts) {
+ if (accepts == null || accepts.length == 0) {
return null;
}
for (String accept : accepts) {
@@ -494,8 +750,8 @@ public String selectHeaderAccept(String[] accepts) {
* @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) {
+ public String selectHeaderContentType(String... contentTypes) {
+ if (contentTypes == null || contentTypes.length == 0) {
return "application/json";
}
for (String contentType : contentTypes) {
@@ -508,6 +764,7 @@ public String selectHeaderContentType(String[] contentTypes) {
/**
* Escape the given string to be used as URL query value.
+ *
* @param str String
* @return Escaped string
*/
@@ -522,25 +779,22 @@ public String escapeString(String 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 {
+ 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();
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));
+ if (param.getValue() instanceof Iterable>) {
+ ((Iterable>)param.getValue()).forEach(v -> addParamToMultipart(v, param.getKey(), multiPart));
} else {
- FormDataContentDisposition contentDisp = FormDataContentDisposition.name(param.getKey()).build();
- multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(param.getValue())));
+ addParamToMultipart(param.getValue(), param.getKey(), multiPart);
}
}
entity = Entity.entity(multiPart, MediaType.MULTIPART_FORM_DATA_TYPE);
@@ -552,13 +806,94 @@ public Entity> serialize(Object obj, Map formParams, String co
entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE);
} else {
// We let jersey handle the serialization
- entity = Entity.entity(obj, contentType);
+ if (isBodyNullable) { // payload is nullable
+ 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 {
+ 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;
}
+ /**
+ * Adds the object with the provided key to the MultiPart.
+ * Based on the object type sets Content-Disposition and Content-Type.
+ *
+ * @param obj Object
+ * @param key Key of the object
+ * @param multiPart MultiPart to add the form param to
+ */
+ protected void addParamToMultipart(Object value, String key, MultiPart multiPart) {
+ if (value instanceof File) {
+ File file = (File) value;
+ FormDataContentDisposition contentDisp = FormDataContentDisposition.name(key)
+ .fileName(file.getName()).size(file.length()).build();
+
+ // Attempt to probe the content type for the file so that the form part is more correctly
+ // and precisely identified, but fall back to application/octet-stream if that fails.
+ MediaType type;
+ try {
+ type = MediaType.valueOf(Files.probeContentType(file.toPath()));
+ } catch (IOException | IllegalArgumentException e) {
+ type = MediaType.APPLICATION_OCTET_STREAM_TYPE;
+ }
+
+ multiPart.bodyPart(new FormDataBodyPart(contentDisp, file, type));
+ } else {
+ FormDataContentDisposition contentDisp = FormDataContentDisposition.name(key).build();
+ multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(value)));
+ }
+ }
+
+ /**
+ * 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
+ * @param isBodyNullable True if the body is nullable
+ * @return String
+ * @throws ApiException API exception
+ */
+ 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)");
+ } 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 {
+ if (isBodyNullable) {
+ return obj == null ? "null" : json.getMapper().writeValueAsString(obj);
+ } else {
+ return obj == null ? "" : json.getMapper().writeValueAsString(obj);
+ }
+ }
+ } catch (Exception ex) {
+ throw new ApiException("Failed to perform serializeToString: " + ex.toString());
+ }
+ }
+
/**
* Deserialize response body to Java object according to the Content-Type.
+ *
* @param Type
* @param response Response
* @param returnType Return type
@@ -580,16 +915,15 @@ public T deserialize(Response response, GenericType returnType) throws Ap
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
@@ -604,6 +938,13 @@ public File downloadFileFromResponse(Response response) throws ApiException {
}
}
+ /**
+ * Prepare the file for download from the response.
+ *
+ * @param response a {@link jakarta.ws.rs.core.Response} object.
+ * @return a {@link java.io.File} object.
+ * @throws java.io.IOException if any.
+ */
public File prepareDownloadFile(Response response) throws IOException {
String filename = null;
String contentDisposition = (String) response.getHeaders().getFirst("Content-Disposition");
@@ -628,99 +969,143 @@ public File prepareDownloadFile(Response response) throws IOException {
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();
}
/**
* 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 isBodyNullable True if the body is nullable
* @return The response body in type of string
* @throws ApiException API exception
*/
- 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,
+ 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,
+ boolean isBodyNullable)
+ throws ApiException {
+
+ String targetURL;
+ List serverConfigurations;
+ if (serverIndex != null && (serverConfigurations = operationServers.get(operation)) != null) {
+ int index = operationServerIndex.getOrDefault(operation, serverIndex).intValue();
+ Map variables = operationServerVariables.getOrDefault(operation, serverVariables);
+ if (index < 0 || index >= serverConfigurations.size()) {
+ throw new ArrayIndexOutOfBoundsException(
+ String.format(
+ java.util.Locale.ROOT,
+ "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;
+ }
+ // 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);
+ WebTarget target = httpClient.target(targetURL);
+
+ // put all headers in one place
+ Map allHeaderParams = new HashMap<>(defaultHeaderMap);
+ allHeaderParams.putAll(headerParams);
+
+ if (authNames != null) {
+ // update different parameters (e.g. headers) for authentication
+ updateParamsForAuth(
+ authNames,
+ queryParams,
+ allHeaderParams,
+ cookieParams,
+ null,
+ method,
+ target.getUri());
+ }
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()));
}
}
}
- Invocation.Builder invocationBuilder = target.request().accept(accept);
+ Invocation.Builder invocationBuilder = target.request();
+
+ if (accept != null) {
+ invocationBuilder = invocationBuilder.accept(accept);
+ }
- for (Entry entry : headerParams.entrySet()) {
+ for (Entry entry : cookieParams.entrySet()) {
String value = entry.getValue();
if (value != null) {
- invocationBuilder = invocationBuilder.header(entry.getKey(), value);
+ 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);
- }
+ for (Entry entry : defaultCookieMap.entrySet()) {
+ String value = entry.getValue();
+ if (value != null) {
+ invocationBuilder = invocationBuilder.cookie(entry.getKey(), value);
}
}
- Entity> entity = serialize(body, formParams, contentType);
+ Entity> entity = serialize(body, formParams, contentType, isBodyNullable);
+
+ 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.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);
- }
+ response = sendRequest(method, invocationBuilder, entity);
- statusCode = response.getStatusInfo().getStatusCode();
- responseHeaders = buildResponseHeaders(response);
+ final int statusCode = response.getStatusInfo().getStatusCode();
- if (response.getStatus() == Status.NO_CONTENT.getStatusCode()) {
- return null;
+ Map> responseHeaders = buildResponseHeaders(response);
+
+ if (statusCode == Status.NO_CONTENT.getStatusCode()) {
+ return new ApiResponse(statusCode, responseHeaders);
} else if (response.getStatusInfo().getFamily() == Status.Family.SUCCESSFUL) {
- if (returnType == null)
- return null;
- else
- return deserialize(response, returnType);
+ if (returnType == null) {
+ return new ApiResponse(statusCode, responseHeaders);
+ } else {
+ return new ApiResponse(statusCode, responseHeaders, deserialize(response, returnType));
+ }
} else {
String message = "error";
String respBody = null;
@@ -733,50 +1118,153 @@ public T invokeAPI(String path, String method, List queryParams, Objec
}
}
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
+ }
+ }
+ }
+
+ protected 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)) {
+ if ("".equals(entity.getEntity())) {
+ response = invocationBuilder.method("DELETE");
+ } else {
+ 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, boolean isBodyNullable) throws ApiException {
+ return invokeAPI(null, path, method, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType, isBodyNullable);
}
/**
* 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() {
+ // Create ClientConfig if it has not been initialized yet
+ if (clientConfig == null) {
+ clientConfig = getDefaultClientConfig();
+ }
+
+ ClientBuilder clientBuilder = ClientBuilder.newBuilder();
+ clientBuilder = clientBuilder.withConfig(clientConfig);
+ customizeClientBuilder(clientBuilder);
+ 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);
- clientConfig.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true);
+ // Removed HttpUrlConnectorProvider.SET_METHOD_WORKAROUND as it uses internal Jersey API
+ // turn off compliance validation to be able to send payloads with DELETE calls
+ clientConfig.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
+ applyDebugSetting(clientConfig);
+ return clientConfig;
+ }
+
+ protected void applyDebugSetting(ClientConfig clientConfig) {
if (debugging) {
- 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);
+ // Simplified logging setup - removed internal Jersey constants
+ clientConfig.register(new LoggingFeature(java.util.logging.Logger.getLogger("org.glassfish.jersey.client"), java.util.logging.Level.INFO, LoggingFeature.Verbosity.PAYLOAD_ANY, 1024*50 /* Log payloads up to 50K */));
// Set logger to ALL
- java.util.logging.Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME).setLevel(java.util.logging.Level.ALL);
+ java.util.logging.Logger.getLogger("org.glassfish.jersey.client").setLevel(java.util.logging.Level.ALL);
+ } 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) {
+ /**
+ * Customize the client builder.
+ *
+ * This method can be overridden 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).
+ *
+ * @param clientBuilder a {@link jakarta.ws.rs.client.ClientBuilder} object.
+ */
+ 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.
+ *
+ * @param clientBuilder a {@link jakarta.ws.rs.client.ClientBuilder} object.
+ * @throws java.security.KeyManagementException if any.
+ * @throws java.security.NoSuchAlgorithmException if any.
+ */
+ 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);
+ }
+
+ /**
+ * Build the response headers.
+ *
+ * @param response a {@link jakarta.ws.rs.core.Response} object.
+ * @return a {@link java.util.Map} of response headers.
+ */
protected Map> buildResponseHeaders(Response response) {
- Map> responseHeaders = new HashMap>();
+ Map> responseHeaders = new HashMap<>();
for (Entry> entry: response.getHeaders().entrySet()) {
List values = entry.getValue();
- List headers = new ArrayList();
+ List headers = new ArrayList<>();
for (Object o : values) {
headers.add(String.valueOf(o));
}
@@ -789,12 +1277,21 @@ protected Map> buildResponseHeaders(Response response) {
* 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) {
+ 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);
+ if (auth == null) {
+ continue;
+ }
+ auth.applyToParams(queryParams, headerParams, cookieParams, payload, method, uri);
}
}
}
+
diff --git a/src/main/java/com/codedx/client/ApiException.java b/src/main/java/com/codedx/client/ApiException.java
index 22f5740..38b4c20 100644
--- a/src/main/java/com/codedx/client/ApiException.java
+++ b/src/main/java/com/codedx/client/ApiException.java
@@ -1,12 +1,12 @@
/*
- * Code Dx API
- * Code Dx provides a variety of REST APIs, allowing external applications and scripts to interface with core functionality. This guide documents the various REST resources provided by Code Dx. ## Authentication Authentication is a requirement when accessing API endpoints. There are two methods by which authentication may be performed. ### API Keys The primary method for authentication is passing an `API-Key` header containing a valid API key with all requests. For example: `API-Key: 550e8400-e29b-41d4-a716-44665544000` API keys may be generated by Code Dx admins. Once they are generated, in most cases, they behave like regular users. They will need to be assigned user roles for any projects they will be used with. Although it is possible to assign the *admin* [role](UserGuide.html#UserRolesConfiguration) to an API key, the recommendation is to avoid doing so unless absolutely necessary. See the user guide for an overview about how to create and manage [API keys](UserGuide.html#APIKeysAdministration). ### HTTP Basic Authentication HTTP Basic authentication may be used to authenticate with the API as a regular user. This is accomplished by including an `Authorization` header containing a typical authorization credential. ## Error Handling ### Bad Requests For API calls that accept input, invalid values will trigger an HTTP 400 Bad Request status code. ### Server Errors For any API call, if an unexpected error occurs, an HTTP 500 Internal Server Error status code will be returned. If an error message is available, the response will include a basic message body describing the error: ` { \"error\": \"error message\" } ` The error property will contain a string message indicating the nature of the error. ### Errors with Third-Party Applications Sometimes Code Dx must communicate with third-party applications like JIRA, Git, and certain enterprise tools. Some users may have in-house versions of these with self-signed certificates which may not be \"trusted\". In these cases, the API will respond with an HTTP 502 BAD GATEWAY status. If this happens, refer to [Trusting Self-Signed Certificates](InstallGuide.html#TrustingSelfSignedCertificates) in the install guide. ### API Unavailable In special circumstances, particularly during the installation and update phases, the API will be unavailable. When the API is unavailable, all calls will return an HTTP 503 Service Unavailable status, and no actions or side effects will occur as a result of the calls. ## Examples Code Dx's API uses REST over HTTP. As such, you can use any language/utility that supports making HTTP requests to interact with the API. The examples below use curl , a popular command-line utility, to do so. First, you'll need to [generate an API Key](UserGuide.html#APIKeysAdministration). Second, while you can create projects through the API, these examples will assume that you've already created one. You'll need to know its project id number, which you can find by looking at the URL for the [Findings Page](UserGuide.html#Findings), which will end in a number. **Note:** Many API endpoints require a JSON body in the request. Most JSON will contain double-quotes (`\"`) and spaces, which have special meaning when used on the command line. In order to ensure your JSON body is interpreted as a single argument, you must escape it properly. For example, if you wanted to `POST` the following JSON body: ``` { \"name\": \"John Doe\" } ``` You would put a backslash (`\\`) before each double-quote (`\"`), and surround the whole thing with double-quotes: ``` \"{ \\\"name\\\": \\\"John Doe\\\" }\" ``` The outermost double-quotes tell the command-line interpreter that everything within them is to be treated as a single argument (as opposed to the usual space-separated behavior). The backslash before each inner double-quote tells the command-line interpreter that you mean the literal double-quote character, and not the end of the quoted argument. In many *non-Windows* operating systems, you can also use a single-quote (`'`) to surround the argument, and skip the backslashes: ``` '{ \"name\": \"John Doe\" }' ``` The examples below will use the double-quotes and backslashes style, as it works on most (if not all) operating systems. ### Running an Analysis To start an analysis, you can run ``` curl -F file1=@src.zip -H \"API-Key: 942d16d4-fb3f-4653-9cb3-a9da2e28e574\" https:///codedx/api/projects//analysis ``` Make sure you use your own values for the `src.zip` file, the API Key, the hostname for your Code Dx server, and the project id. **Note:** This endpoint is not listed below due to a swagger limitation. ### Retrieving Finding Data There is a wide variety of data available for the findings of a project after running an analysis. Two examples are provided here. ### Findings Table Data You can retrieve the data that's used to populate the [findings table](UserGuide.html#FindingsTable): ``` curl -H \"Content-Type: application/json\" -X POST -d \"{\\\"filter\\\":{},\\\"sort\\\":{\\\"by\\\":\\\"id\\\",\\\"direction\\\":\\\"ascending\\\"},\\\"pagination\\\":{\\\"page\\\":1,\\\"perPage\\\":10}}\" -H \"API-Key: 942d16d4-fb3f-4653-9cb3-a9da2e28e574\" https:///codedx/api/projects//findings/table ``` Additional information about how to construct more useful filter and sort requests can be found in the documentation. ### Finding Metadata You can retrieve metadata for a finding, if you know the finding id. You can take the ID for a finding from the Findings Table: ``` curl -H \"API-Key: 942d16d4-fb3f-4653-9cb3-a9da2e28e574\" https:///codedx/api/findings/ ``` ### Generating a Report You can use the API to generate a PDF [report](UserGuide.html#GenerateReport). ``` curl -H \"Content-Type: application/json\" -X POST -d \"{\\\"filter\\\":{},\\\"config\\\":{\\\"summaryMode\\\":\\\"simple\\\",\\\"detailsMode\\\":\\\"simple\\\",\\\"includeResultDetails\\\":true,\\\"includeComments\\\":false}}\" -H \"API-Key: 942d16d4-fb3f-4653-9cb3-a9da2e28e574\" https:///codedx/api/projects//report/pdf ``` ## Generating a Client SDK If you require a client SDK for Code Dx, you can generate one using [Swagger Code Generator](https://github.com/swagger-api/swagger-codegen). Detailed instructions are available on the github page and our swagger spec can be found [here](swagger/swagger.json).
+ * Software Risk Manager API Guide
+ * Software Risk Manager provides a variety of REST APIs, allowing external applications and scripts to interface with core functionality. This guide documents the various REST resources provided by Software Risk Manager. ## Authentication Authentication is a requirement when accessing API endpoints. There are two methods by which authentication may be performed. ### API Keys The primary method for authentication is passing an `API-Key` header containing a valid API key with all requests, i.e. `API-Key: ` API Keys come in two possible forms: - `api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24` - latest format - `550e8400-e29b-41d4-a716-44665544000` - legacy format For example: `API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24` `API-Key: 550e8400-e29b-41d4-a716-44665544000` API keys may be generated by Software Risk Manager admins. Once they are generated, in most cases, they behave like regular users. They will need to be assigned user roles for any projects they will be used with. Although it is possible to assign the *admin* [role](../user_guide/Project-Management/user_role_configuration.html) to an API key, the recommendation is to avoid doing so unless absolutely necessary. See the user guide for an overview about how to create and manage [API keys](../user_guide/Settings/api_keys_administration.html). ### Personal Access Tokens Personal Access Tokens can be used as [bearer tokens](https://swagger.io/docs/specification/authentication/bearer-authentication/), e.g. `Authorization: Bearer secret-token:qRuXr1BqgoTWXNxUhYQ8H_Yl2zfy6vxuqMIRnkGO` Personal Access Tokens can be created by any user, and represent a subset of that user's permissions. ### HTTP Basic Authentication HTTP Basic authentication may be used to authenticate with the API as a regular user. This is accomplished by including an `Authorization` header containing a typical authorization credential. ## Error Handling ### Bad Requests For API calls that accept input, invalid values will trigger an HTTP 400 Bad Request status code. ### Server Errors For any API call, if an unexpected error occurs, an HTTP 500 Internal Server Error status code will be returned. If an error message is available, the response will include a basic message body describing the error: ` { \"error\": \"error message\" } ` The error property will contain a string message indicating the nature of the error. ### Errors with Third-Party Applications Sometimes Software Risk Manager must communicate with third-party applications like JIRA, Git, and certain enterprise tools. Some users may have in-house versions of these with self-signed certificates which may not be \"trusted\". In these cases, the API will respond with an HTTP 502 BAD GATEWAY status. If this happens, refer to [Trusting Certificates](../install_guide/Installation/trusting-certs.html) in the install guide. ### API Unavailable In special circumstances, particularly during the installation and update phases, the API will be unavailable. When the API is unavailable, all calls will return an HTTP 503 Service Unavailable status, and no actions or side effects will occur as a result of the calls. ## Examples Software Risk Manager's API uses REST over HTTP. As such, you can use any language/utility that supports making HTTP requests to interact with the API. The examples below use curl , a popular command-line utility, to do so. First, you'll need to [generate an API Key](../user_guide/Settings/api_keys_administration.html). Second, while you can create projects through the API, these examples will assume that you've already created one. You'll need to know its project id number, which you can find by looking at the URL for the [Findings Page](../user_guide/Findings/findings_overview.html), which will end in a number. **Note:** Many API endpoints require a JSON body in the request. Most JSON will contain double-quotes (`\"`) and spaces, which have special meaning when used on the command line. In order to ensure your JSON body is interpreted as a single argument, you must escape it properly. For example, if you wanted to `POST` the following JSON body: ```{ \"name\": \"John Doe\" }``` You would put a backslash (`\\`) before each double-quote (`\"`), and surround the whole thing with double-quotes: ```\"{ \\\"name\\\": \\\"John Doe\\\" }\"``` The outermost double-quotes tell the command-line interpreter that everything within them is to be treated as a single argument (as opposed to the usual space-separated behavior). The backslash before each inner double-quote tells the command-line interpreter that you mean the literal double-quote character, and not the end of the quoted argument. In many *non-Windows* operating systems, you can also use a single-quote (`'`) to surround the argument, and skip the backslashes: ```'{ \"name\": \"John Doe\" }'``` The examples below will use the double-quotes and backslashes style, as it works on most (if not all) operating systems. ### Running an Analysis To start an analysis, you can run ```curl -F file1=@src.zip -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/projects//analysis``` Make sure you use your own values for the `src.zip` file, the API Key, the hostname for your Software Risk Manager server, and the project id. ### Retrieving Finding Data There is a wide variety of data available for the findings of a project after running an analysis. Two examples are provided here. ### Findings Table Data You can retrieve the data that's used to populate the [findings table](../user_guide/Findings/findings_table.html): ```curl -H \"Content-Type: application/json\" -X POST -d \"{\\\"filter\\\":{},\\\"sort\\\":{\\\"by\\\":\\\"id\\\",\\\"direction\\\":\\\"ascending\\\"},\\\"pagination\\\":{\\\"page\\\":1,\\\"perPage\\\":10}}\" -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/projects//findings/table``` Additional information about how to construct more useful filter and sort requests can be found in the documentation. ### Finding Metadata You can retrieve metadata for a finding, if you know the finding ID. You can take the ID for a finding from the Findings Table: ```curl -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/findings/``` ### Generating a Report You can use the API to generate a PDF [report](../user_guide/Findings/generate_report.html). ```curl -H \"Content-Type: application/json\" -X POST -d \"{\\\"filter\\\":{},\\\"config\\\":{\\\"summaryMode\\\":\\\"simple\\\",\\\"detailsMode\\\":\\\"simple\\\",\\\"includeResultDetails\\\":true,\\\"includeComments\\\":false}}\" -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/projects//report/pdf``` ## Generating a Client SDK If you require a client SDK for Software Risk Manager, you can generate one using [OpenAPI Generator](https://openapi-generator.tech/). Detailed instructions are available on the [GitHub page](https://github.com/OpenAPITools/openapi-generator) and our OpenAPI spec can be found [here](swagger/swagger.json).
*
- * OpenAPI spec version: 3.0.0
+ * The version of the OpenAPI document:
*
*
- * 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.
*/
@@ -16,8 +16,13 @@
import java.util.Map;
import java.util.List;
-@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2019-01-02T17:17:22.434-05:00")
+/**
+ * API Exception
+ */
+@jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2026-04-02T11:55:06.722228-04:00[America/New_York]", comments = "Generator version: 7.21.0")
public class ApiException extends Exception {
+ private static final long serialVersionUID = 1L;
+
private int code = 0;
private Map> responseHeaders = null;
private String responseBody = null;
diff --git a/src/main/java/com/codedx/client/ApiResponse.java b/src/main/java/com/codedx/client/ApiResponse.java
new file mode 100644
index 0000000..bfb45cb
--- /dev/null
+++ b/src/main/java/com/codedx/client/ApiResponse.java
@@ -0,0 +1,74 @@
+/*
+ * Software Risk Manager API Guide
+ * Software Risk Manager provides a variety of REST APIs, allowing external applications and scripts to interface with core functionality. This guide documents the various REST resources provided by Software Risk Manager. ## Authentication Authentication is a requirement when accessing API endpoints. There are two methods by which authentication may be performed. ### API Keys The primary method for authentication is passing an `API-Key` header containing a valid API key with all requests, i.e. `API-Key: ` API Keys come in two possible forms: - `api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24` - latest format - `550e8400-e29b-41d4-a716-44665544000` - legacy format For example: `API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24` `API-Key: 550e8400-e29b-41d4-a716-44665544000` API keys may be generated by Software Risk Manager admins. Once they are generated, in most cases, they behave like regular users. They will need to be assigned user roles for any projects they will be used with. Although it is possible to assign the *admin* [role](../user_guide/Project-Management/user_role_configuration.html) to an API key, the recommendation is to avoid doing so unless absolutely necessary. See the user guide for an overview about how to create and manage [API keys](../user_guide/Settings/api_keys_administration.html). ### Personal Access Tokens Personal Access Tokens can be used as [bearer tokens](https://swagger.io/docs/specification/authentication/bearer-authentication/), e.g. `Authorization: Bearer secret-token:qRuXr1BqgoTWXNxUhYQ8H_Yl2zfy6vxuqMIRnkGO` Personal Access Tokens can be created by any user, and represent a subset of that user's permissions. ### HTTP Basic Authentication HTTP Basic authentication may be used to authenticate with the API as a regular user. This is accomplished by including an `Authorization` header containing a typical authorization credential. ## Error Handling ### Bad Requests For API calls that accept input, invalid values will trigger an HTTP 400 Bad Request status code. ### Server Errors For any API call, if an unexpected error occurs, an HTTP 500 Internal Server Error status code will be returned. If an error message is available, the response will include a basic message body describing the error: ` { \"error\": \"error message\" } ` The error property will contain a string message indicating the nature of the error. ### Errors with Third-Party Applications Sometimes Software Risk Manager must communicate with third-party applications like JIRA, Git, and certain enterprise tools. Some users may have in-house versions of these with self-signed certificates which may not be \"trusted\". In these cases, the API will respond with an HTTP 502 BAD GATEWAY status. If this happens, refer to [Trusting Certificates](../install_guide/Installation/trusting-certs.html) in the install guide. ### API Unavailable In special circumstances, particularly during the installation and update phases, the API will be unavailable. When the API is unavailable, all calls will return an HTTP 503 Service Unavailable status, and no actions or side effects will occur as a result of the calls. ## Examples Software Risk Manager's API uses REST over HTTP. As such, you can use any language/utility that supports making HTTP requests to interact with the API. The examples below use curl , a popular command-line utility, to do so. First, you'll need to [generate an API Key](../user_guide/Settings/api_keys_administration.html). Second, while you can create projects through the API, these examples will assume that you've already created one. You'll need to know its project id number, which you can find by looking at the URL for the [Findings Page](../user_guide/Findings/findings_overview.html), which will end in a number. **Note:** Many API endpoints require a JSON body in the request. Most JSON will contain double-quotes (`\"`) and spaces, which have special meaning when used on the command line. In order to ensure your JSON body is interpreted as a single argument, you must escape it properly. For example, if you wanted to `POST` the following JSON body: ```{ \"name\": \"John Doe\" }``` You would put a backslash (`\\`) before each double-quote (`\"`), and surround the whole thing with double-quotes: ```\"{ \\\"name\\\": \\\"John Doe\\\" }\"``` The outermost double-quotes tell the command-line interpreter that everything within them is to be treated as a single argument (as opposed to the usual space-separated behavior). The backslash before each inner double-quote tells the command-line interpreter that you mean the literal double-quote character, and not the end of the quoted argument. In many *non-Windows* operating systems, you can also use a single-quote (`'`) to surround the argument, and skip the backslashes: ```'{ \"name\": \"John Doe\" }'``` The examples below will use the double-quotes and backslashes style, as it works on most (if not all) operating systems. ### Running an Analysis To start an analysis, you can run ```curl -F file1=@src.zip -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/projects//analysis``` Make sure you use your own values for the `src.zip` file, the API Key, the hostname for your Software Risk Manager server, and the project id. ### Retrieving Finding Data There is a wide variety of data available for the findings of a project after running an analysis. Two examples are provided here. ### Findings Table Data You can retrieve the data that's used to populate the [findings table](../user_guide/Findings/findings_table.html): ```curl -H \"Content-Type: application/json\" -X POST -d \"{\\\"filter\\\":{},\\\"sort\\\":{\\\"by\\\":\\\"id\\\",\\\"direction\\\":\\\"ascending\\\"},\\\"pagination\\\":{\\\"page\\\":1,\\\"perPage\\\":10}}\" -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/projects//findings/table``` Additional information about how to construct more useful filter and sort requests can be found in the documentation. ### Finding Metadata You can retrieve metadata for a finding, if you know the finding ID. You can take the ID for a finding from the Findings Table: ```curl -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/findings/``` ### Generating a Report You can use the API to generate a PDF [report](../user_guide/Findings/generate_report.html). ```curl -H \"Content-Type: application/json\" -X POST -d \"{\\\"filter\\\":{},\\\"config\\\":{\\\"summaryMode\\\":\\\"simple\\\",\\\"detailsMode\\\":\\\"simple\\\",\\\"includeResultDetails\\\":true,\\\"includeComments\\\":false}}\" -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/projects//report/pdf``` ## Generating a Client SDK If you require a client SDK for Software Risk Manager, you can generate one using [OpenAPI Generator](https://openapi-generator.tech/). Detailed instructions are available on the [GitHub page](https://github.com/OpenAPITools/openapi-generator) and our OpenAPI spec can be found [here](swagger/swagger.json).
+ *
+ * The version of the OpenAPI document:
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+
+package com.codedx.client;
+
+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;
+ }
+
+ /**
+ * 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/src/main/java/com/codedx/client/Configuration.java b/src/main/java/com/codedx/client/Configuration.java
index 4ac8a53..6c62218 100644
--- a/src/main/java/com/codedx/client/Configuration.java
+++ b/src/main/java/com/codedx/client/Configuration.java
@@ -1,39 +1,63 @@
/*
- * Code Dx API
- * Code Dx provides a variety of REST APIs, allowing external applications and scripts to interface with core functionality. This guide documents the various REST resources provided by Code Dx. ## Authentication Authentication is a requirement when accessing API endpoints. There are two methods by which authentication may be performed. ### API Keys The primary method for authentication is passing an `API-Key` header containing a valid API key with all requests. For example: `API-Key: 550e8400-e29b-41d4-a716-44665544000` API keys may be generated by Code Dx admins. Once they are generated, in most cases, they behave like regular users. They will need to be assigned user roles for any projects they will be used with. Although it is possible to assign the *admin* [role](UserGuide.html#UserRolesConfiguration) to an API key, the recommendation is to avoid doing so unless absolutely necessary. See the user guide for an overview about how to create and manage [API keys](UserGuide.html#APIKeysAdministration). ### HTTP Basic Authentication HTTP Basic authentication may be used to authenticate with the API as a regular user. This is accomplished by including an `Authorization` header containing a typical authorization credential. ## Error Handling ### Bad Requests For API calls that accept input, invalid values will trigger an HTTP 400 Bad Request status code. ### Server Errors For any API call, if an unexpected error occurs, an HTTP 500 Internal Server Error status code will be returned. If an error message is available, the response will include a basic message body describing the error: ` { \"error\": \"error message\" } ` The error property will contain a string message indicating the nature of the error. ### Errors with Third-Party Applications Sometimes Code Dx must communicate with third-party applications like JIRA, Git, and certain enterprise tools. Some users may have in-house versions of these with self-signed certificates which may not be \"trusted\". In these cases, the API will respond with an HTTP 502 BAD GATEWAY status. If this happens, refer to [Trusting Self-Signed Certificates](InstallGuide.html#TrustingSelfSignedCertificates) in the install guide. ### API Unavailable In special circumstances, particularly during the installation and update phases, the API will be unavailable. When the API is unavailable, all calls will return an HTTP 503 Service Unavailable status, and no actions or side effects will occur as a result of the calls. ## Examples Code Dx's API uses REST over HTTP. As such, you can use any language/utility that supports making HTTP requests to interact with the API. The examples below use curl , a popular command-line utility, to do so. First, you'll need to [generate an API Key](UserGuide.html#APIKeysAdministration). Second, while you can create projects through the API, these examples will assume that you've already created one. You'll need to know its project id number, which you can find by looking at the URL for the [Findings Page](UserGuide.html#Findings), which will end in a number. **Note:** Many API endpoints require a JSON body in the request. Most JSON will contain double-quotes (`\"`) and spaces, which have special meaning when used on the command line. In order to ensure your JSON body is interpreted as a single argument, you must escape it properly. For example, if you wanted to `POST` the following JSON body: ``` { \"name\": \"John Doe\" } ``` You would put a backslash (`\\`) before each double-quote (`\"`), and surround the whole thing with double-quotes: ``` \"{ \\\"name\\\": \\\"John Doe\\\" }\" ``` The outermost double-quotes tell the command-line interpreter that everything within them is to be treated as a single argument (as opposed to the usual space-separated behavior). The backslash before each inner double-quote tells the command-line interpreter that you mean the literal double-quote character, and not the end of the quoted argument. In many *non-Windows* operating systems, you can also use a single-quote (`'`) to surround the argument, and skip the backslashes: ``` '{ \"name\": \"John Doe\" }' ``` The examples below will use the double-quotes and backslashes style, as it works on most (if not all) operating systems. ### Running an Analysis To start an analysis, you can run ``` curl -F file1=@src.zip -H \"API-Key: 942d16d4-fb3f-4653-9cb3-a9da2e28e574\" https:///codedx/api/projects//analysis ``` Make sure you use your own values for the `src.zip` file, the API Key, the hostname for your Code Dx server, and the project id. **Note:** This endpoint is not listed below due to a swagger limitation. ### Retrieving Finding Data There is a wide variety of data available for the findings of a project after running an analysis. Two examples are provided here. ### Findings Table Data You can retrieve the data that's used to populate the [findings table](UserGuide.html#FindingsTable): ``` curl -H \"Content-Type: application/json\" -X POST -d \"{\\\"filter\\\":{},\\\"sort\\\":{\\\"by\\\":\\\"id\\\",\\\"direction\\\":\\\"ascending\\\"},\\\"pagination\\\":{\\\"page\\\":1,\\\"perPage\\\":10}}\" -H \"API-Key: 942d16d4-fb3f-4653-9cb3-a9da2e28e574\" https:///codedx/api/projects//findings/table ``` Additional information about how to construct more useful filter and sort requests can be found in the documentation. ### Finding Metadata You can retrieve metadata for a finding, if you know the finding id. You can take the ID for a finding from the Findings Table: ``` curl -H \"API-Key: 942d16d4-fb3f-4653-9cb3-a9da2e28e574\" https:///codedx/api/findings/ ``` ### Generating a Report You can use the API to generate a PDF [report](UserGuide.html#GenerateReport). ``` curl -H \"Content-Type: application/json\" -X POST -d \"{\\\"filter\\\":{},\\\"config\\\":{\\\"summaryMode\\\":\\\"simple\\\",\\\"detailsMode\\\":\\\"simple\\\",\\\"includeResultDetails\\\":true,\\\"includeComments\\\":false}}\" -H \"API-Key: 942d16d4-fb3f-4653-9cb3-a9da2e28e574\" https:///codedx/api/projects//report/pdf ``` ## Generating a Client SDK If you require a client SDK for Code Dx, you can generate one using [Swagger Code Generator](https://github.com/swagger-api/swagger-codegen). Detailed instructions are available on the github page and our swagger spec can be found [here](swagger/swagger.json).
+ * Software Risk Manager API Guide
+ * Software Risk Manager provides a variety of REST APIs, allowing external applications and scripts to interface with core functionality. This guide documents the various REST resources provided by Software Risk Manager. ## Authentication Authentication is a requirement when accessing API endpoints. There are two methods by which authentication may be performed. ### API Keys The primary method for authentication is passing an `API-Key` header containing a valid API key with all requests, i.e. `API-Key: ` API Keys come in two possible forms: - `api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24` - latest format - `550e8400-e29b-41d4-a716-44665544000` - legacy format For example: `API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24` `API-Key: 550e8400-e29b-41d4-a716-44665544000` API keys may be generated by Software Risk Manager admins. Once they are generated, in most cases, they behave like regular users. They will need to be assigned user roles for any projects they will be used with. Although it is possible to assign the *admin* [role](../user_guide/Project-Management/user_role_configuration.html) to an API key, the recommendation is to avoid doing so unless absolutely necessary. See the user guide for an overview about how to create and manage [API keys](../user_guide/Settings/api_keys_administration.html). ### Personal Access Tokens Personal Access Tokens can be used as [bearer tokens](https://swagger.io/docs/specification/authentication/bearer-authentication/), e.g. `Authorization: Bearer secret-token:qRuXr1BqgoTWXNxUhYQ8H_Yl2zfy6vxuqMIRnkGO` Personal Access Tokens can be created by any user, and represent a subset of that user's permissions. ### HTTP Basic Authentication HTTP Basic authentication may be used to authenticate with the API as a regular user. This is accomplished by including an `Authorization` header containing a typical authorization credential. ## Error Handling ### Bad Requests For API calls that accept input, invalid values will trigger an HTTP 400 Bad Request status code. ### Server Errors For any API call, if an unexpected error occurs, an HTTP 500 Internal Server Error status code will be returned. If an error message is available, the response will include a basic message body describing the error: ` { \"error\": \"error message\" } ` The error property will contain a string message indicating the nature of the error. ### Errors with Third-Party Applications Sometimes Software Risk Manager must communicate with third-party applications like JIRA, Git, and certain enterprise tools. Some users may have in-house versions of these with self-signed certificates which may not be \"trusted\". In these cases, the API will respond with an HTTP 502 BAD GATEWAY status. If this happens, refer to [Trusting Certificates](../install_guide/Installation/trusting-certs.html) in the install guide. ### API Unavailable In special circumstances, particularly during the installation and update phases, the API will be unavailable. When the API is unavailable, all calls will return an HTTP 503 Service Unavailable status, and no actions or side effects will occur as a result of the calls. ## Examples Software Risk Manager's API uses REST over HTTP. As such, you can use any language/utility that supports making HTTP requests to interact with the API. The examples below use curl , a popular command-line utility, to do so. First, you'll need to [generate an API Key](../user_guide/Settings/api_keys_administration.html). Second, while you can create projects through the API, these examples will assume that you've already created one. You'll need to know its project id number, which you can find by looking at the URL for the [Findings Page](../user_guide/Findings/findings_overview.html), which will end in a number. **Note:** Many API endpoints require a JSON body in the request. Most JSON will contain double-quotes (`\"`) and spaces, which have special meaning when used on the command line. In order to ensure your JSON body is interpreted as a single argument, you must escape it properly. For example, if you wanted to `POST` the following JSON body: ```{ \"name\": \"John Doe\" }``` You would put a backslash (`\\`) before each double-quote (`\"`), and surround the whole thing with double-quotes: ```\"{ \\\"name\\\": \\\"John Doe\\\" }\"``` The outermost double-quotes tell the command-line interpreter that everything within them is to be treated as a single argument (as opposed to the usual space-separated behavior). The backslash before each inner double-quote tells the command-line interpreter that you mean the literal double-quote character, and not the end of the quoted argument. In many *non-Windows* operating systems, you can also use a single-quote (`'`) to surround the argument, and skip the backslashes: ```'{ \"name\": \"John Doe\" }'``` The examples below will use the double-quotes and backslashes style, as it works on most (if not all) operating systems. ### Running an Analysis To start an analysis, you can run ```curl -F file1=@src.zip -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/projects//analysis``` Make sure you use your own values for the `src.zip` file, the API Key, the hostname for your Software Risk Manager server, and the project id. ### Retrieving Finding Data There is a wide variety of data available for the findings of a project after running an analysis. Two examples are provided here. ### Findings Table Data You can retrieve the data that's used to populate the [findings table](../user_guide/Findings/findings_table.html): ```curl -H \"Content-Type: application/json\" -X POST -d \"{\\\"filter\\\":{},\\\"sort\\\":{\\\"by\\\":\\\"id\\\",\\\"direction\\\":\\\"ascending\\\"},\\\"pagination\\\":{\\\"page\\\":1,\\\"perPage\\\":10}}\" -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/projects//findings/table``` Additional information about how to construct more useful filter and sort requests can be found in the documentation. ### Finding Metadata You can retrieve metadata for a finding, if you know the finding ID. You can take the ID for a finding from the Findings Table: ```curl -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/findings/``` ### Generating a Report You can use the API to generate a PDF [report](../user_guide/Findings/generate_report.html). ```curl -H \"Content-Type: application/json\" -X POST -d \"{\\\"filter\\\":{},\\\"config\\\":{\\\"summaryMode\\\":\\\"simple\\\",\\\"detailsMode\\\":\\\"simple\\\",\\\"includeResultDetails\\\":true,\\\"includeComments\\\":false}}\" -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/projects//report/pdf``` ## Generating a Client SDK If you require a client SDK for Software Risk Manager, you can generate one using [OpenAPI Generator](https://openapi-generator.tech/). Detailed instructions are available on the [GitHub page](https://github.com/OpenAPITools/openapi-generator) and our OpenAPI spec can be found [here](swagger/swagger.json).
*
- * OpenAPI spec version: 3.0.0
+ * The version of the OpenAPI document:
*
*
- * 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.
*/
package com.codedx.client;
-@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2019-01-02T17:17:22.434-05:00")
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
+
+@jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2026-04-02T11:55:06.722228-04:00[America/New_York]", comments = "Generator version: 7.21.0")
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;
- }
+ public static final String VERSION = "1.0.0";
+
+ private static final AtomicReference defaultApiClient = new AtomicReference<>();
+ private static volatile Supplier apiClientFactory = ApiClient::new;
- /**
- * 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;
+ /**
+ * 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() {
+ ApiClient client = defaultApiClient.get();
+ if (client == null) {
+ client = defaultApiClient.updateAndGet(val -> {
+ if (val != null) { // changed by another thread
+ return val;
+ }
+ return apiClientFactory.get();
+ });
}
-}
+ return client;
+ }
+
+ /**
+ * 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.set(apiClient);
+ }
+
+ /**
+ * set the callback used to create new ApiClient objects
+ */
+ public static void setApiClientFactory(Supplier factory) {
+ apiClientFactory = Objects.requireNonNull(factory);
+ }
+
+ private Configuration() {
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/codedx/client/CustomInstantDeserializer.java b/src/main/java/com/codedx/client/CustomInstantDeserializer.java
deleted file mode 100644
index a5c0c98..0000000
--- a/src/main/java/com/codedx/client/CustomInstantDeserializer.java
+++ /dev/null
@@ -1,240 +0,0 @@
-package com.codedx.client;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-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.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.*;
-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 ThreeTenDateTimeDeserializerBase withDateFormat(DateTimeFormatter dtf) {
- if (dtf == _formatter) {
- return this;
- }
- return new CustomInstantDeserializer(this, dtf);
- }
-
- @Override
- protected ThreeTenDateTimeDeserializerBase withLeniency(Boolean leniency) {
- // not relevant for us
- return this;
- }
-
- @Override
- protected ThreeTenDateTimeDeserializerBase withShape(JsonFormat.Shape shape) {
- // not relevant for us
- return this;
- }
-
- @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.toZoneId(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/src/main/java/com/codedx/client/JSON.java b/src/main/java/com/codedx/client/JSON.java
index 4f15d1d..d0e0e6f 100644
--- a/src/main/java/com/codedx/client/JSON.java
+++ b/src/main/java/com/codedx/client/JSON.java
@@ -1,32 +1,50 @@
+/*
+ * Software Risk Manager API Guide
+ * Software Risk Manager provides a variety of REST APIs, allowing external applications and scripts to interface with core functionality. This guide documents the various REST resources provided by Software Risk Manager. ## Authentication Authentication is a requirement when accessing API endpoints. There are two methods by which authentication may be performed. ### API Keys The primary method for authentication is passing an `API-Key` header containing a valid API key with all requests, i.e. `API-Key: ` API Keys come in two possible forms: - `api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24` - latest format - `550e8400-e29b-41d4-a716-44665544000` - legacy format For example: `API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24` `API-Key: 550e8400-e29b-41d4-a716-44665544000` API keys may be generated by Software Risk Manager admins. Once they are generated, in most cases, they behave like regular users. They will need to be assigned user roles for any projects they will be used with. Although it is possible to assign the *admin* [role](../user_guide/Project-Management/user_role_configuration.html) to an API key, the recommendation is to avoid doing so unless absolutely necessary. See the user guide for an overview about how to create and manage [API keys](../user_guide/Settings/api_keys_administration.html). ### Personal Access Tokens Personal Access Tokens can be used as [bearer tokens](https://swagger.io/docs/specification/authentication/bearer-authentication/), e.g. `Authorization: Bearer secret-token:qRuXr1BqgoTWXNxUhYQ8H_Yl2zfy6vxuqMIRnkGO` Personal Access Tokens can be created by any user, and represent a subset of that user's permissions. ### HTTP Basic Authentication HTTP Basic authentication may be used to authenticate with the API as a regular user. This is accomplished by including an `Authorization` header containing a typical authorization credential. ## Error Handling ### Bad Requests For API calls that accept input, invalid values will trigger an HTTP 400 Bad Request status code. ### Server Errors For any API call, if an unexpected error occurs, an HTTP 500 Internal Server Error status code will be returned. If an error message is available, the response will include a basic message body describing the error: ` { \"error\": \"error message\" } ` The error property will contain a string message indicating the nature of the error. ### Errors with Third-Party Applications Sometimes Software Risk Manager must communicate with third-party applications like JIRA, Git, and certain enterprise tools. Some users may have in-house versions of these with self-signed certificates which may not be \"trusted\". In these cases, the API will respond with an HTTP 502 BAD GATEWAY status. If this happens, refer to [Trusting Certificates](../install_guide/Installation/trusting-certs.html) in the install guide. ### API Unavailable In special circumstances, particularly during the installation and update phases, the API will be unavailable. When the API is unavailable, all calls will return an HTTP 503 Service Unavailable status, and no actions or side effects will occur as a result of the calls. ## Examples Software Risk Manager's API uses REST over HTTP. As such, you can use any language/utility that supports making HTTP requests to interact with the API. The examples below use curl , a popular command-line utility, to do so. First, you'll need to [generate an API Key](../user_guide/Settings/api_keys_administration.html). Second, while you can create projects through the API, these examples will assume that you've already created one. You'll need to know its project id number, which you can find by looking at the URL for the [Findings Page](../user_guide/Findings/findings_overview.html), which will end in a number. **Note:** Many API endpoints require a JSON body in the request. Most JSON will contain double-quotes (`\"`) and spaces, which have special meaning when used on the command line. In order to ensure your JSON body is interpreted as a single argument, you must escape it properly. For example, if you wanted to `POST` the following JSON body: ```{ \"name\": \"John Doe\" }``` You would put a backslash (`\\`) before each double-quote (`\"`), and surround the whole thing with double-quotes: ```\"{ \\\"name\\\": \\\"John Doe\\\" }\"``` The outermost double-quotes tell the command-line interpreter that everything within them is to be treated as a single argument (as opposed to the usual space-separated behavior). The backslash before each inner double-quote tells the command-line interpreter that you mean the literal double-quote character, and not the end of the quoted argument. In many *non-Windows* operating systems, you can also use a single-quote (`'`) to surround the argument, and skip the backslashes: ```'{ \"name\": \"John Doe\" }'``` The examples below will use the double-quotes and backslashes style, as it works on most (if not all) operating systems. ### Running an Analysis To start an analysis, you can run ```curl -F file1=@src.zip -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/projects//analysis``` Make sure you use your own values for the `src.zip` file, the API Key, the hostname for your Software Risk Manager server, and the project id. ### Retrieving Finding Data There is a wide variety of data available for the findings of a project after running an analysis. Two examples are provided here. ### Findings Table Data You can retrieve the data that's used to populate the [findings table](../user_guide/Findings/findings_table.html): ```curl -H \"Content-Type: application/json\" -X POST -d \"{\\\"filter\\\":{},\\\"sort\\\":{\\\"by\\\":\\\"id\\\",\\\"direction\\\":\\\"ascending\\\"},\\\"pagination\\\":{\\\"page\\\":1,\\\"perPage\\\":10}}\" -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/projects//findings/table``` Additional information about how to construct more useful filter and sort requests can be found in the documentation. ### Finding Metadata You can retrieve metadata for a finding, if you know the finding ID. You can take the ID for a finding from the Findings Table: ```curl -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/findings/``` ### Generating a Report You can use the API to generate a PDF [report](../user_guide/Findings/generate_report.html). ```curl -H \"Content-Type: application/json\" -X POST -d \"{\\\"filter\\\":{},\\\"config\\\":{\\\"summaryMode\\\":\\\"simple\\\",\\\"detailsMode\\\":\\\"simple\\\",\\\"includeResultDetails\\\":true,\\\"includeComments\\\":false}}\" -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/projects//report/pdf``` ## Generating a Client SDK If you require a client SDK for Software Risk Manager, you can generate one using [OpenAPI Generator](https://openapi-generator.tech/). Detailed instructions are available on the [GitHub page](https://github.com/OpenAPITools/openapi-generator) and our OpenAPI spec can be found [here](swagger/swagger.json).
+ *
+ * The version of the OpenAPI document:
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+
package com.codedx.client;
-import org.threeten.bp.*;
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.*;
-import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+import org.openapitools.jackson.nullable.JsonNullableModule;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.text.DateFormat;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import jakarta.ws.rs.core.GenericType;
+import jakarta.ws.rs.ext.ContextResolver;
-import javax.ws.rs.ext.ContextResolver;
-
-@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2019-01-02T17:17:22.434-05:00")
+@jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2026-04-02T11:55:06.722228-04:00[America/New_York]", comments = "Generator version: 7.21.0")
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());
- 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);
+ mapper = JsonMapper.builder()
+ .serializationInclusion(JsonInclude.Include.NON_NULL)
+ .configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false)
+ .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
+ .configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true)
+ .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
+ .enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)
+ .enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING)
+ .defaultDateFormat(new RFC3339DateFormat())
+ .addModule(new JavaTimeModule())
+ .addModule(new JsonNullableModule())
+ .addModule(new RFC3339JavaTimeModule())
+ .build();
}
/**
@@ -41,4 +59,204 @@ public void setDateFormat(DateFormat dateFormat) {
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<>();
+
+ /**
+ * A map of oneOf/anyOf descendants for each model class.
+ */
+ private static Map, 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/src/main/java/com/codedx/client/JavaTimeFormatter.java b/src/main/java/com/codedx/client/JavaTimeFormatter.java
new file mode 100644
index 0000000..bfc933c
--- /dev/null
+++ b/src/main/java/com/codedx/client/JavaTimeFormatter.java
@@ -0,0 +1,68 @@
+/*
+ * Software Risk Manager API Guide
+ * Software Risk Manager provides a variety of REST APIs, allowing external applications and scripts to interface with core functionality. This guide documents the various REST resources provided by Software Risk Manager. ## Authentication Authentication is a requirement when accessing API endpoints. There are two methods by which authentication may be performed. ### API Keys The primary method for authentication is passing an `API-Key` header containing a valid API key with all requests, i.e. `API-Key: ` API Keys come in two possible forms: - `api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24` - latest format - `550e8400-e29b-41d4-a716-44665544000` - legacy format For example: `API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24` `API-Key: 550e8400-e29b-41d4-a716-44665544000` API keys may be generated by Software Risk Manager admins. Once they are generated, in most cases, they behave like regular users. They will need to be assigned user roles for any projects they will be used with. Although it is possible to assign the *admin* [role](../user_guide/Project-Management/user_role_configuration.html) to an API key, the recommendation is to avoid doing so unless absolutely necessary. See the user guide for an overview about how to create and manage [API keys](../user_guide/Settings/api_keys_administration.html). ### Personal Access Tokens Personal Access Tokens can be used as [bearer tokens](https://swagger.io/docs/specification/authentication/bearer-authentication/), e.g. `Authorization: Bearer secret-token:qRuXr1BqgoTWXNxUhYQ8H_Yl2zfy6vxuqMIRnkGO` Personal Access Tokens can be created by any user, and represent a subset of that user's permissions. ### HTTP Basic Authentication HTTP Basic authentication may be used to authenticate with the API as a regular user. This is accomplished by including an `Authorization` header containing a typical authorization credential. ## Error Handling ### Bad Requests For API calls that accept input, invalid values will trigger an HTTP 400 Bad Request status code. ### Server Errors For any API call, if an unexpected error occurs, an HTTP 500 Internal Server Error status code will be returned. If an error message is available, the response will include a basic message body describing the error: ` { \"error\": \"error message\" } ` The error property will contain a string message indicating the nature of the error. ### Errors with Third-Party Applications Sometimes Software Risk Manager must communicate with third-party applications like JIRA, Git, and certain enterprise tools. Some users may have in-house versions of these with self-signed certificates which may not be \"trusted\". In these cases, the API will respond with an HTTP 502 BAD GATEWAY status. If this happens, refer to [Trusting Certificates](../install_guide/Installation/trusting-certs.html) in the install guide. ### API Unavailable In special circumstances, particularly during the installation and update phases, the API will be unavailable. When the API is unavailable, all calls will return an HTTP 503 Service Unavailable status, and no actions or side effects will occur as a result of the calls. ## Examples Software Risk Manager's API uses REST over HTTP. As such, you can use any language/utility that supports making HTTP requests to interact with the API. The examples below use curl , a popular command-line utility, to do so. First, you'll need to [generate an API Key](../user_guide/Settings/api_keys_administration.html). Second, while you can create projects through the API, these examples will assume that you've already created one. You'll need to know its project id number, which you can find by looking at the URL for the [Findings Page](../user_guide/Findings/findings_overview.html), which will end in a number. **Note:** Many API endpoints require a JSON body in the request. Most JSON will contain double-quotes (`\"`) and spaces, which have special meaning when used on the command line. In order to ensure your JSON body is interpreted as a single argument, you must escape it properly. For example, if you wanted to `POST` the following JSON body: ```{ \"name\": \"John Doe\" }``` You would put a backslash (`\\`) before each double-quote (`\"`), and surround the whole thing with double-quotes: ```\"{ \\\"name\\\": \\\"John Doe\\\" }\"``` The outermost double-quotes tell the command-line interpreter that everything within them is to be treated as a single argument (as opposed to the usual space-separated behavior). The backslash before each inner double-quote tells the command-line interpreter that you mean the literal double-quote character, and not the end of the quoted argument. In many *non-Windows* operating systems, you can also use a single-quote (`'`) to surround the argument, and skip the backslashes: ```'{ \"name\": \"John Doe\" }'``` The examples below will use the double-quotes and backslashes style, as it works on most (if not all) operating systems. ### Running an Analysis To start an analysis, you can run ```curl -F file1=@src.zip -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/projects//analysis``` Make sure you use your own values for the `src.zip` file, the API Key, the hostname for your Software Risk Manager server, and the project id. ### Retrieving Finding Data There is a wide variety of data available for the findings of a project after running an analysis. Two examples are provided here. ### Findings Table Data You can retrieve the data that's used to populate the [findings table](../user_guide/Findings/findings_table.html): ```curl -H \"Content-Type: application/json\" -X POST -d \"{\\\"filter\\\":{},\\\"sort\\\":{\\\"by\\\":\\\"id\\\",\\\"direction\\\":\\\"ascending\\\"},\\\"pagination\\\":{\\\"page\\\":1,\\\"perPage\\\":10}}\" -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/projects//findings/table``` Additional information about how to construct more useful filter and sort requests can be found in the documentation. ### Finding Metadata You can retrieve metadata for a finding, if you know the finding ID. You can take the ID for a finding from the Findings Table: ```curl -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/findings/``` ### Generating a Report You can use the API to generate a PDF [report](../user_guide/Findings/generate_report.html). ```curl -H \"Content-Type: application/json\" -X POST -d \"{\\\"filter\\\":{},\\\"config\\\":{\\\"summaryMode\\\":\\\"simple\\\",\\\"detailsMode\\\":\\\"simple\\\",\\\"includeResultDetails\\\":true,\\\"includeComments\\\":false}}\" -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/projects//report/pdf``` ## Generating a Client SDK If you require a client SDK for Software Risk Manager, you can generate one using [OpenAPI Generator](https://openapi-generator.tech/). Detailed instructions are available on the [GitHub page](https://github.com/OpenAPITools/openapi-generator) and our OpenAPI spec can be found [here](swagger/swagger.json).
+ *
+ * The version of the OpenAPI document:
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+package com.codedx.client;
+
+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}.
+ */
+@jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2026-04-02T11:55:06.722228-04:00[America/New_York]", comments = "Generator version: 7.21.0")
+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);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/codedx/client/Pair.java b/src/main/java/com/codedx/client/Pair.java
index 245a2e9..ed6b739 100644
--- a/src/main/java/com/codedx/client/Pair.java
+++ b/src/main/java/com/codedx/client/Pair.java
@@ -1,52 +1,37 @@
/*
- * Code Dx API
- * Code Dx provides a variety of REST APIs, allowing external applications and scripts to interface with core functionality. This guide documents the various REST resources provided by Code Dx. ## Authentication Authentication is a requirement when accessing API endpoints. There are two methods by which authentication may be performed. ### API Keys The primary method for authentication is passing an `API-Key` header containing a valid API key with all requests. For example: `API-Key: 550e8400-e29b-41d4-a716-44665544000` API keys may be generated by Code Dx admins. Once they are generated, in most cases, they behave like regular users. They will need to be assigned user roles for any projects they will be used with. Although it is possible to assign the *admin* [role](UserGuide.html#UserRolesConfiguration) to an API key, the recommendation is to avoid doing so unless absolutely necessary. See the user guide for an overview about how to create and manage [API keys](UserGuide.html#APIKeysAdministration). ### HTTP Basic Authentication HTTP Basic authentication may be used to authenticate with the API as a regular user. This is accomplished by including an `Authorization` header containing a typical authorization credential. ## Error Handling ### Bad Requests For API calls that accept input, invalid values will trigger an HTTP 400 Bad Request status code. ### Server Errors For any API call, if an unexpected error occurs, an HTTP 500 Internal Server Error status code will be returned. If an error message is available, the response will include a basic message body describing the error: ` { \"error\": \"error message\" } ` The error property will contain a string message indicating the nature of the error. ### Errors with Third-Party Applications Sometimes Code Dx must communicate with third-party applications like JIRA, Git, and certain enterprise tools. Some users may have in-house versions of these with self-signed certificates which may not be \"trusted\". In these cases, the API will respond with an HTTP 502 BAD GATEWAY status. If this happens, refer to [Trusting Self-Signed Certificates](InstallGuide.html#TrustingSelfSignedCertificates) in the install guide. ### API Unavailable In special circumstances, particularly during the installation and update phases, the API will be unavailable. When the API is unavailable, all calls will return an HTTP 503 Service Unavailable status, and no actions or side effects will occur as a result of the calls. ## Examples Code Dx's API uses REST over HTTP. As such, you can use any language/utility that supports making HTTP requests to interact with the API. The examples below use curl , a popular command-line utility, to do so. First, you'll need to [generate an API Key](UserGuide.html#APIKeysAdministration). Second, while you can create projects through the API, these examples will assume that you've already created one. You'll need to know its project id number, which you can find by looking at the URL for the [Findings Page](UserGuide.html#Findings), which will end in a number. **Note:** Many API endpoints require a JSON body in the request. Most JSON will contain double-quotes (`\"`) and spaces, which have special meaning when used on the command line. In order to ensure your JSON body is interpreted as a single argument, you must escape it properly. For example, if you wanted to `POST` the following JSON body: ``` { \"name\": \"John Doe\" } ``` You would put a backslash (`\\`) before each double-quote (`\"`), and surround the whole thing with double-quotes: ``` \"{ \\\"name\\\": \\\"John Doe\\\" }\" ``` The outermost double-quotes tell the command-line interpreter that everything within them is to be treated as a single argument (as opposed to the usual space-separated behavior). The backslash before each inner double-quote tells the command-line interpreter that you mean the literal double-quote character, and not the end of the quoted argument. In many *non-Windows* operating systems, you can also use a single-quote (`'`) to surround the argument, and skip the backslashes: ``` '{ \"name\": \"John Doe\" }' ``` The examples below will use the double-quotes and backslashes style, as it works on most (if not all) operating systems. ### Running an Analysis To start an analysis, you can run ``` curl -F file1=@src.zip -H \"API-Key: 942d16d4-fb3f-4653-9cb3-a9da2e28e574\" https:///codedx/api/projects//analysis ``` Make sure you use your own values for the `src.zip` file, the API Key, the hostname for your Code Dx server, and the project id. **Note:** This endpoint is not listed below due to a swagger limitation. ### Retrieving Finding Data There is a wide variety of data available for the findings of a project after running an analysis. Two examples are provided here. ### Findings Table Data You can retrieve the data that's used to populate the [findings table](UserGuide.html#FindingsTable): ``` curl -H \"Content-Type: application/json\" -X POST -d \"{\\\"filter\\\":{},\\\"sort\\\":{\\\"by\\\":\\\"id\\\",\\\"direction\\\":\\\"ascending\\\"},\\\"pagination\\\":{\\\"page\\\":1,\\\"perPage\\\":10}}\" -H \"API-Key: 942d16d4-fb3f-4653-9cb3-a9da2e28e574\" https:///codedx/api/projects//findings/table ``` Additional information about how to construct more useful filter and sort requests can be found in the documentation. ### Finding Metadata You can retrieve metadata for a finding, if you know the finding id. You can take the ID for a finding from the Findings Table: ``` curl -H \"API-Key: 942d16d4-fb3f-4653-9cb3-a9da2e28e574\" https:///codedx/api/findings/ ``` ### Generating a Report You can use the API to generate a PDF [report](UserGuide.html#GenerateReport). ``` curl -H \"Content-Type: application/json\" -X POST -d \"{\\\"filter\\\":{},\\\"config\\\":{\\\"summaryMode\\\":\\\"simple\\\",\\\"detailsMode\\\":\\\"simple\\\",\\\"includeResultDetails\\\":true,\\\"includeComments\\\":false}}\" -H \"API-Key: 942d16d4-fb3f-4653-9cb3-a9da2e28e574\" https:///codedx/api/projects//report/pdf ``` ## Generating a Client SDK If you require a client SDK for Code Dx, you can generate one using [Swagger Code Generator](https://github.com/swagger-api/swagger-codegen). Detailed instructions are available on the github page and our swagger spec can be found [here](swagger/swagger.json).
+ * Software Risk Manager API Guide
+ * Software Risk Manager provides a variety of REST APIs, allowing external applications and scripts to interface with core functionality. This guide documents the various REST resources provided by Software Risk Manager. ## Authentication Authentication is a requirement when accessing API endpoints. There are two methods by which authentication may be performed. ### API Keys The primary method for authentication is passing an `API-Key` header containing a valid API key with all requests, i.e. `API-Key: ` API Keys come in two possible forms: - `api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24` - latest format - `550e8400-e29b-41d4-a716-44665544000` - legacy format For example: `API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24` `API-Key: 550e8400-e29b-41d4-a716-44665544000` API keys may be generated by Software Risk Manager admins. Once they are generated, in most cases, they behave like regular users. They will need to be assigned user roles for any projects they will be used with. Although it is possible to assign the *admin* [role](../user_guide/Project-Management/user_role_configuration.html) to an API key, the recommendation is to avoid doing so unless absolutely necessary. See the user guide for an overview about how to create and manage [API keys](../user_guide/Settings/api_keys_administration.html). ### Personal Access Tokens Personal Access Tokens can be used as [bearer tokens](https://swagger.io/docs/specification/authentication/bearer-authentication/), e.g. `Authorization: Bearer secret-token:qRuXr1BqgoTWXNxUhYQ8H_Yl2zfy6vxuqMIRnkGO` Personal Access Tokens can be created by any user, and represent a subset of that user's permissions. ### HTTP Basic Authentication HTTP Basic authentication may be used to authenticate with the API as a regular user. This is accomplished by including an `Authorization` header containing a typical authorization credential. ## Error Handling ### Bad Requests For API calls that accept input, invalid values will trigger an HTTP 400 Bad Request status code. ### Server Errors For any API call, if an unexpected error occurs, an HTTP 500 Internal Server Error status code will be returned. If an error message is available, the response will include a basic message body describing the error: ` { \"error\": \"error message\" } ` The error property will contain a string message indicating the nature of the error. ### Errors with Third-Party Applications Sometimes Software Risk Manager must communicate with third-party applications like JIRA, Git, and certain enterprise tools. Some users may have in-house versions of these with self-signed certificates which may not be \"trusted\". In these cases, the API will respond with an HTTP 502 BAD GATEWAY status. If this happens, refer to [Trusting Certificates](../install_guide/Installation/trusting-certs.html) in the install guide. ### API Unavailable In special circumstances, particularly during the installation and update phases, the API will be unavailable. When the API is unavailable, all calls will return an HTTP 503 Service Unavailable status, and no actions or side effects will occur as a result of the calls. ## Examples Software Risk Manager's API uses REST over HTTP. As such, you can use any language/utility that supports making HTTP requests to interact with the API. The examples below use curl , a popular command-line utility, to do so. First, you'll need to [generate an API Key](../user_guide/Settings/api_keys_administration.html). Second, while you can create projects through the API, these examples will assume that you've already created one. You'll need to know its project id number, which you can find by looking at the URL for the [Findings Page](../user_guide/Findings/findings_overview.html), which will end in a number. **Note:** Many API endpoints require a JSON body in the request. Most JSON will contain double-quotes (`\"`) and spaces, which have special meaning when used on the command line. In order to ensure your JSON body is interpreted as a single argument, you must escape it properly. For example, if you wanted to `POST` the following JSON body: ```{ \"name\": \"John Doe\" }``` You would put a backslash (`\\`) before each double-quote (`\"`), and surround the whole thing with double-quotes: ```\"{ \\\"name\\\": \\\"John Doe\\\" }\"``` The outermost double-quotes tell the command-line interpreter that everything within them is to be treated as a single argument (as opposed to the usual space-separated behavior). The backslash before each inner double-quote tells the command-line interpreter that you mean the literal double-quote character, and not the end of the quoted argument. In many *non-Windows* operating systems, you can also use a single-quote (`'`) to surround the argument, and skip the backslashes: ```'{ \"name\": \"John Doe\" }'``` The examples below will use the double-quotes and backslashes style, as it works on most (if not all) operating systems. ### Running an Analysis To start an analysis, you can run ```curl -F file1=@src.zip -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/projects//analysis``` Make sure you use your own values for the `src.zip` file, the API Key, the hostname for your Software Risk Manager server, and the project id. ### Retrieving Finding Data There is a wide variety of data available for the findings of a project after running an analysis. Two examples are provided here. ### Findings Table Data You can retrieve the data that's used to populate the [findings table](../user_guide/Findings/findings_table.html): ```curl -H \"Content-Type: application/json\" -X POST -d \"{\\\"filter\\\":{},\\\"sort\\\":{\\\"by\\\":\\\"id\\\",\\\"direction\\\":\\\"ascending\\\"},\\\"pagination\\\":{\\\"page\\\":1,\\\"perPage\\\":10}}\" -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/projects//findings/table``` Additional information about how to construct more useful filter and sort requests can be found in the documentation. ### Finding Metadata You can retrieve metadata for a finding, if you know the finding ID. You can take the ID for a finding from the Findings Table: ```curl -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/findings/``` ### Generating a Report You can use the API to generate a PDF [report](../user_guide/Findings/generate_report.html). ```curl -H \"Content-Type: application/json\" -X POST -d \"{\\\"filter\\\":{},\\\"config\\\":{\\\"summaryMode\\\":\\\"simple\\\",\\\"detailsMode\\\":\\\"simple\\\",\\\"includeResultDetails\\\":true,\\\"includeComments\\\":false}}\" -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/projects//report/pdf``` ## Generating a Client SDK If you require a client SDK for Software Risk Manager, you can generate one using [OpenAPI Generator](https://openapi-generator.tech/). Detailed instructions are available on the [GitHub page](https://github.com/OpenAPITools/openapi-generator) and our OpenAPI spec can be found [here](swagger/swagger.json).
*
- * OpenAPI spec version: 3.0.0
+ * The version of the OpenAPI document:
*
*
- * 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.
*/
package com.codedx.client;
-@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaClientCodegen", date = "2019-01-02T17:17:22.434-05:00")
+@jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2026-04-02T11:55:06.722228-04:00[America/New_York]", comments = "Generator version: 7.21.0")
public class Pair {
- private String name = "";
- private String value = "";
+ private final String name;
+ private final String value;
- public Pair (String name, String value) {
- setName(name);
- setValue(value);
- }
+ public Pair(String name, String value) {
+ this.name = isValidString(name) ? name : "";
+ this.value = isValidString(value) ? value : "";
+ }
- private void setName(String name) {
- if (!isValidString(name)) return;
+ public String getName() {
+ return this.name;
+ }
- this.name = name;
- }
+ public String getValue() {
+ return this.value;
+ }
- 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;
- }
+ private static boolean isValidString(String arg) {
+ return arg != null;
+ }
}
diff --git a/src/main/java/com/codedx/client/RFC3339DateFormat.java b/src/main/java/com/codedx/client/RFC3339DateFormat.java
index 284ba9b..7fe579d 100644
--- a/src/main/java/com/codedx/client/RFC3339DateFormat.java
+++ b/src/main/java/com/codedx/client/RFC3339DateFormat.java
@@ -1,32 +1,57 @@
/*
- * Code Dx API
- * Code Dx provides a variety of REST APIs, allowing external applications and scripts to interface with core functionality. This guide documents the various REST resources provided by Code Dx. ## Authentication Authentication is a requirement when accessing API endpoints. There are two methods by which authentication may be performed. ### API Keys The primary method for authentication is passing an `API-Key` header containing a valid API key with all requests. For example: `API-Key: 550e8400-e29b-41d4-a716-44665544000` API keys may be generated by Code Dx admins. Once they are generated, in most cases, they behave like regular users. They will need to be assigned user roles for any projects they will be used with. Although it is possible to assign the *admin* [role](UserGuide.html#UserRolesConfiguration) to an API key, the recommendation is to avoid doing so unless absolutely necessary. See the user guide for an overview about how to create and manage [API keys](UserGuide.html#APIKeysAdministration). ### HTTP Basic Authentication HTTP Basic authentication may be used to authenticate with the API as a regular user. This is accomplished by including an `Authorization` header containing a typical authorization credential. ## Error Handling ### Bad Requests For API calls that accept input, invalid values will trigger an HTTP 400 Bad Request status code. ### Server Errors For any API call, if an unexpected error occurs, an HTTP 500 Internal Server Error status code will be returned. If an error message is available, the response will include a basic message body describing the error: ` { \"error\": \"error message\" } ` The error property will contain a string message indicating the nature of the error. ### Errors with Third-Party Applications Sometimes Code Dx must communicate with third-party applications like JIRA, Git, and certain enterprise tools. Some users may have in-house versions of these with self-signed certificates which may not be \"trusted\". In these cases, the API will respond with an HTTP 502 BAD GATEWAY status. If this happens, refer to [Trusting Self-Signed Certificates](InstallGuide.html#TrustingSelfSignedCertificates) in the install guide. ### API Unavailable In special circumstances, particularly during the installation and update phases, the API will be unavailable. When the API is unavailable, all calls will return an HTTP 503 Service Unavailable status, and no actions or side effects will occur as a result of the calls. ## Examples Code Dx's API uses REST over HTTP. As such, you can use any language/utility that supports making HTTP requests to interact with the API. The examples below use curl , a popular command-line utility, to do so. First, you'll need to [generate an API Key](UserGuide.html#APIKeysAdministration). Second, while you can create projects through the API, these examples will assume that you've already created one. You'll need to know its project id number, which you can find by looking at the URL for the [Findings Page](UserGuide.html#Findings), which will end in a number. **Note:** Many API endpoints require a JSON body in the request. Most JSON will contain double-quotes (`\"`) and spaces, which have special meaning when used on the command line. In order to ensure your JSON body is interpreted as a single argument, you must escape it properly. For example, if you wanted to `POST` the following JSON body: ``` { \"name\": \"John Doe\" } ``` You would put a backslash (`\\`) before each double-quote (`\"`), and surround the whole thing with double-quotes: ``` \"{ \\\"name\\\": \\\"John Doe\\\" }\" ``` The outermost double-quotes tell the command-line interpreter that everything within them is to be treated as a single argument (as opposed to the usual space-separated behavior). The backslash before each inner double-quote tells the command-line interpreter that you mean the literal double-quote character, and not the end of the quoted argument. In many *non-Windows* operating systems, you can also use a single-quote (`'`) to surround the argument, and skip the backslashes: ``` '{ \"name\": \"John Doe\" }' ``` The examples below will use the double-quotes and backslashes style, as it works on most (if not all) operating systems. ### Running an Analysis To start an analysis, you can run ``` curl -F file1=@src.zip -H \"API-Key: 942d16d4-fb3f-4653-9cb3-a9da2e28e574\" https:///codedx/api/projects//analysis ``` Make sure you use your own values for the `src.zip` file, the API Key, the hostname for your Code Dx server, and the project id. **Note:** This endpoint is not listed below due to a swagger limitation. ### Retrieving Finding Data There is a wide variety of data available for the findings of a project after running an analysis. Two examples are provided here. ### Findings Table Data You can retrieve the data that's used to populate the [findings table](UserGuide.html#FindingsTable): ``` curl -H \"Content-Type: application/json\" -X POST -d \"{\\\"filter\\\":{},\\\"sort\\\":{\\\"by\\\":\\\"id\\\",\\\"direction\\\":\\\"ascending\\\"},\\\"pagination\\\":{\\\"page\\\":1,\\\"perPage\\\":10}}\" -H \"API-Key: 942d16d4-fb3f-4653-9cb3-a9da2e28e574\" https:///codedx/api/projects//findings/table ``` Additional information about how to construct more useful filter and sort requests can be found in the documentation. ### Finding Metadata You can retrieve metadata for a finding, if you know the finding id. You can take the ID for a finding from the Findings Table: ``` curl -H \"API-Key: 942d16d4-fb3f-4653-9cb3-a9da2e28e574\" https:///codedx/api/findings/ ``` ### Generating a Report You can use the API to generate a PDF [report](UserGuide.html#GenerateReport). ``` curl -H \"Content-Type: application/json\" -X POST -d \"{\\\"filter\\\":{},\\\"config\\\":{\\\"summaryMode\\\":\\\"simple\\\",\\\"detailsMode\\\":\\\"simple\\\",\\\"includeResultDetails\\\":true,\\\"includeComments\\\":false}}\" -H \"API-Key: 942d16d4-fb3f-4653-9cb3-a9da2e28e574\" https:///codedx/api/projects//report/pdf ``` ## Generating a Client SDK If you require a client SDK for Code Dx, you can generate one using [Swagger Code Generator](https://github.com/swagger-api/swagger-codegen). Detailed instructions are available on the github page and our swagger spec can be found [here](swagger/swagger.json).
+ * Software Risk Manager API Guide
+ * Software Risk Manager provides a variety of REST APIs, allowing external applications and scripts to interface with core functionality. This guide documents the various REST resources provided by Software Risk Manager. ## Authentication Authentication is a requirement when accessing API endpoints. There are two methods by which authentication may be performed. ### API Keys The primary method for authentication is passing an `API-Key` header containing a valid API key with all requests, i.e. `API-Key: ` API Keys come in two possible forms: - `api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24` - latest format - `550e8400-e29b-41d4-a716-44665544000` - legacy format For example: `API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24` `API-Key: 550e8400-e29b-41d4-a716-44665544000` API keys may be generated by Software Risk Manager admins. Once they are generated, in most cases, they behave like regular users. They will need to be assigned user roles for any projects they will be used with. Although it is possible to assign the *admin* [role](../user_guide/Project-Management/user_role_configuration.html) to an API key, the recommendation is to avoid doing so unless absolutely necessary. See the user guide for an overview about how to create and manage [API keys](../user_guide/Settings/api_keys_administration.html). ### Personal Access Tokens Personal Access Tokens can be used as [bearer tokens](https://swagger.io/docs/specification/authentication/bearer-authentication/), e.g. `Authorization: Bearer secret-token:qRuXr1BqgoTWXNxUhYQ8H_Yl2zfy6vxuqMIRnkGO` Personal Access Tokens can be created by any user, and represent a subset of that user's permissions. ### HTTP Basic Authentication HTTP Basic authentication may be used to authenticate with the API as a regular user. This is accomplished by including an `Authorization` header containing a typical authorization credential. ## Error Handling ### Bad Requests For API calls that accept input, invalid values will trigger an HTTP 400 Bad Request status code. ### Server Errors For any API call, if an unexpected error occurs, an HTTP 500 Internal Server Error status code will be returned. If an error message is available, the response will include a basic message body describing the error: ` { \"error\": \"error message\" } ` The error property will contain a string message indicating the nature of the error. ### Errors with Third-Party Applications Sometimes Software Risk Manager must communicate with third-party applications like JIRA, Git, and certain enterprise tools. Some users may have in-house versions of these with self-signed certificates which may not be \"trusted\". In these cases, the API will respond with an HTTP 502 BAD GATEWAY status. If this happens, refer to [Trusting Certificates](../install_guide/Installation/trusting-certs.html) in the install guide. ### API Unavailable In special circumstances, particularly during the installation and update phases, the API will be unavailable. When the API is unavailable, all calls will return an HTTP 503 Service Unavailable status, and no actions or side effects will occur as a result of the calls. ## Examples Software Risk Manager's API uses REST over HTTP. As such, you can use any language/utility that supports making HTTP requests to interact with the API. The examples below use curl , a popular command-line utility, to do so. First, you'll need to [generate an API Key](../user_guide/Settings/api_keys_administration.html). Second, while you can create projects through the API, these examples will assume that you've already created one. You'll need to know its project id number, which you can find by looking at the URL for the [Findings Page](../user_guide/Findings/findings_overview.html), which will end in a number. **Note:** Many API endpoints require a JSON body in the request. Most JSON will contain double-quotes (`\"`) and spaces, which have special meaning when used on the command line. In order to ensure your JSON body is interpreted as a single argument, you must escape it properly. For example, if you wanted to `POST` the following JSON body: ```{ \"name\": \"John Doe\" }``` You would put a backslash (`\\`) before each double-quote (`\"`), and surround the whole thing with double-quotes: ```\"{ \\\"name\\\": \\\"John Doe\\\" }\"``` The outermost double-quotes tell the command-line interpreter that everything within them is to be treated as a single argument (as opposed to the usual space-separated behavior). The backslash before each inner double-quote tells the command-line interpreter that you mean the literal double-quote character, and not the end of the quoted argument. In many *non-Windows* operating systems, you can also use a single-quote (`'`) to surround the argument, and skip the backslashes: ```'{ \"name\": \"John Doe\" }'``` The examples below will use the double-quotes and backslashes style, as it works on most (if not all) operating systems. ### Running an Analysis To start an analysis, you can run ```curl -F file1=@src.zip -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/projects//analysis``` Make sure you use your own values for the `src.zip` file, the API Key, the hostname for your Software Risk Manager server, and the project id. ### Retrieving Finding Data There is a wide variety of data available for the findings of a project after running an analysis. Two examples are provided here. ### Findings Table Data You can retrieve the data that's used to populate the [findings table](../user_guide/Findings/findings_table.html): ```curl -H \"Content-Type: application/json\" -X POST -d \"{\\\"filter\\\":{},\\\"sort\\\":{\\\"by\\\":\\\"id\\\",\\\"direction\\\":\\\"ascending\\\"},\\\"pagination\\\":{\\\"page\\\":1,\\\"perPage\\\":10}}\" -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/projects//findings/table``` Additional information about how to construct more useful filter and sort requests can be found in the documentation. ### Finding Metadata You can retrieve metadata for a finding, if you know the finding ID. You can take the ID for a finding from the Findings Table: ```curl -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/findings/``` ### Generating a Report You can use the API to generate a PDF [report](../user_guide/Findings/generate_report.html). ```curl -H \"Content-Type: application/json\" -X POST -d \"{\\\"filter\\\":{},\\\"config\\\":{\\\"summaryMode\\\":\\\"simple\\\",\\\"detailsMode\\\":\\\"simple\\\",\\\"includeResultDetails\\\":true,\\\"includeComments\\\":false}}\" -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/projects//report/pdf``` ## Generating a Client SDK If you require a client SDK for Software Risk Manager, you can generate one using [OpenAPI Generator](https://openapi-generator.tech/). Detailed instructions are available on the [GitHub page](https://github.com/OpenAPITools/openapi-generator) and our OpenAPI spec can be found [here](swagger/swagger.json).
*
- * OpenAPI spec version: 3.0.0
+ * The version of the OpenAPI document:
*
*
- * 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.
*/
package com.codedx.client;
-import com.fasterxml.jackson.databind.util.ISO8601DateFormat;
-import com.fasterxml.jackson.databind.util.ISO8601Utils;
-
+import java.text.DateFormat;
import java.text.FieldPosition;
+import java.text.ParsePosition;
import java.util.Date;
+import java.text.DecimalFormat;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+import com.fasterxml.jackson.databind.util.StdDateFormat;
+
+@jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2026-04-02T11:55:06.722228-04:00[America/New_York]", comments = "Generator version: 7.21.0")
+public class RFC3339DateFormat extends DateFormat {
+ private static final long serialVersionUID = 1L;
+ private static final TimeZone TIMEZONE_Z = TimeZone.getTimeZone("UTC");
+
+ private final StdDateFormat fmt = new StdDateFormat()
+ .withTimeZone(TIMEZONE_Z)
+ .withColonInTimeZone(true);
+ public RFC3339DateFormat() {
+ this.calendar = new GregorianCalendar();
+ this.numberFormat = new DecimalFormat();
+ }
-public class RFC3339DateFormat extends ISO8601DateFormat {
+ @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);
}
-}
\ No newline at end of file
+ @Override
+ public Object clone() {
+ return super.clone();
+ }
+}
diff --git a/src/main/java/com/codedx/client/RFC3339InstantDeserializer.java b/src/main/java/com/codedx/client/RFC3339InstantDeserializer.java
new file mode 100644
index 0000000..ad3ccdb
--- /dev/null
+++ b/src/main/java/com/codedx/client/RFC3339InstantDeserializer.java
@@ -0,0 +1,100 @@
+/*
+ * Software Risk Manager API Guide
+ * Software Risk Manager provides a variety of REST APIs, allowing external applications and scripts to interface with core functionality. This guide documents the various REST resources provided by Software Risk Manager. ## Authentication Authentication is a requirement when accessing API endpoints. There are two methods by which authentication may be performed. ### API Keys The primary method for authentication is passing an `API-Key` header containing a valid API key with all requests, i.e. `API-Key: ` API Keys come in two possible forms: - `api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24` - latest format - `550e8400-e29b-41d4-a716-44665544000` - legacy format For example: `API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24` `API-Key: 550e8400-e29b-41d4-a716-44665544000` API keys may be generated by Software Risk Manager admins. Once they are generated, in most cases, they behave like regular users. They will need to be assigned user roles for any projects they will be used with. Although it is possible to assign the *admin* [role](../user_guide/Project-Management/user_role_configuration.html) to an API key, the recommendation is to avoid doing so unless absolutely necessary. See the user guide for an overview about how to create and manage [API keys](../user_guide/Settings/api_keys_administration.html). ### Personal Access Tokens Personal Access Tokens can be used as [bearer tokens](https://swagger.io/docs/specification/authentication/bearer-authentication/), e.g. `Authorization: Bearer secret-token:qRuXr1BqgoTWXNxUhYQ8H_Yl2zfy6vxuqMIRnkGO` Personal Access Tokens can be created by any user, and represent a subset of that user's permissions. ### HTTP Basic Authentication HTTP Basic authentication may be used to authenticate with the API as a regular user. This is accomplished by including an `Authorization` header containing a typical authorization credential. ## Error Handling ### Bad Requests For API calls that accept input, invalid values will trigger an HTTP 400 Bad Request status code. ### Server Errors For any API call, if an unexpected error occurs, an HTTP 500 Internal Server Error status code will be returned. If an error message is available, the response will include a basic message body describing the error: ` { \"error\": \"error message\" } ` The error property will contain a string message indicating the nature of the error. ### Errors with Third-Party Applications Sometimes Software Risk Manager must communicate with third-party applications like JIRA, Git, and certain enterprise tools. Some users may have in-house versions of these with self-signed certificates which may not be \"trusted\". In these cases, the API will respond with an HTTP 502 BAD GATEWAY status. If this happens, refer to [Trusting Certificates](../install_guide/Installation/trusting-certs.html) in the install guide. ### API Unavailable In special circumstances, particularly during the installation and update phases, the API will be unavailable. When the API is unavailable, all calls will return an HTTP 503 Service Unavailable status, and no actions or side effects will occur as a result of the calls. ## Examples Software Risk Manager's API uses REST over HTTP. As such, you can use any language/utility that supports making HTTP requests to interact with the API. The examples below use curl , a popular command-line utility, to do so. First, you'll need to [generate an API Key](../user_guide/Settings/api_keys_administration.html). Second, while you can create projects through the API, these examples will assume that you've already created one. You'll need to know its project id number, which you can find by looking at the URL for the [Findings Page](../user_guide/Findings/findings_overview.html), which will end in a number. **Note:** Many API endpoints require a JSON body in the request. Most JSON will contain double-quotes (`\"`) and spaces, which have special meaning when used on the command line. In order to ensure your JSON body is interpreted as a single argument, you must escape it properly. For example, if you wanted to `POST` the following JSON body: ```{ \"name\": \"John Doe\" }``` You would put a backslash (`\\`) before each double-quote (`\"`), and surround the whole thing with double-quotes: ```\"{ \\\"name\\\": \\\"John Doe\\\" }\"``` The outermost double-quotes tell the command-line interpreter that everything within them is to be treated as a single argument (as opposed to the usual space-separated behavior). The backslash before each inner double-quote tells the command-line interpreter that you mean the literal double-quote character, and not the end of the quoted argument. In many *non-Windows* operating systems, you can also use a single-quote (`'`) to surround the argument, and skip the backslashes: ```'{ \"name\": \"John Doe\" }'``` The examples below will use the double-quotes and backslashes style, as it works on most (if not all) operating systems. ### Running an Analysis To start an analysis, you can run ```curl -F file1=@src.zip -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/projects//analysis``` Make sure you use your own values for the `src.zip` file, the API Key, the hostname for your Software Risk Manager server, and the project id. ### Retrieving Finding Data There is a wide variety of data available for the findings of a project after running an analysis. Two examples are provided here. ### Findings Table Data You can retrieve the data that's used to populate the [findings table](../user_guide/Findings/findings_table.html): ```curl -H \"Content-Type: application/json\" -X POST -d \"{\\\"filter\\\":{},\\\"sort\\\":{\\\"by\\\":\\\"id\\\",\\\"direction\\\":\\\"ascending\\\"},\\\"pagination\\\":{\\\"page\\\":1,\\\"perPage\\\":10}}\" -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https:///srm/api/projects//findings/table``` Additional information about how to construct more useful filter and sort requests can be found in the documentation. ### Finding Metadata You can retrieve metadata for a finding, if you know the finding ID. You can take the ID for a finding from the Findings Table: ```curl -H \"API-Key: api-key:stNglRlu0HToJfmZH5EfqcjN6yFjC2ypj_v-jJ24\" https://