diff --git a/CHANGELOG.md b/CHANGELOG.md
index 88c0fba5..2c539dbf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,20 @@
# Changelog
+# 7.0.0
+
+**Major release**
+**Breaking changes**
+
+- Fixed issues:
+ - Issue: [GitChange.changeType: InvalidArgumentValueException: The body of the request contains invalid Json. #96](https://github.com/hkarthik7/azure-devops-java-sdk/issues/96)
+ - Issue: [is there a way to add comments? #103](https://github.com/hkarthik7/azure-devops-java-sdk/issues/103)
+ - Issue: [client attempts to always deserlilize the response regardless if there's an error #102](https://github.com/hkarthik7/azure-devops-java-sdk/issues/102)
+ - Issue: [LookupService keeps the first credentails of the first succesffull call and ignores credentials from subsequent calls #101](https://github.com/hkarthik7/azure-devops-java-sdk/issues/101)
+- Removed support for legacy API
+- Changes in types packages
+- Added support for authentication via service principal client id and secret
+- Added `Comments Api`
+
# 6.1.3
- Added support for Pull Request Iterations in **GitApi**.
diff --git a/README.md b/README.md
index bc470494..bfdbdd8c 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,11 @@
# azure-devops-java-sdk
+# :loudspeaker: Legacy Api is decommissioned in v7.0.0. :exclamation::heavy_exclamation_mark:
+
[](https://dev.azure.com/harishkarthic/azure-devops-java-sdk/_build/latest?definitionId=8&branchName=main)
[](https://github.com/hkarthik7/azure-devops-java-sdk/blob/main/LICENSE)
[](https://azure-devops-java-sdk-docs.readthedocs.io/en/latest/?badge=latest)
-[](https://search.maven.org/artifact/io.github.hkarthik7/azd/6.1.3/jar)
+[](https://search.maven.org/artifact/io.github.hkarthik7/azd/7.0.0/jar)
**azd** library provides a convenient way to manage and interact with **Azure DevOps Services** REST API with ease. This SDK offers a set of APIs and utilities
with declarative syntax and provide functionalities to the significant services.
@@ -33,7 +35,7 @@ To download the library and use it in your project, just add below in your pom.x
io.github.hkarthik7azd
- 6.1.3
+ 7.0.0
```
@@ -43,7 +45,7 @@ To download the library and use it in your project, just add below in your pom.x
io.github.hkarthik7azd
- 6.1.3
+ 7.0.0javadoc
```
@@ -54,7 +56,7 @@ To download the library and use it in your project, just add below in your pom.x
io.github.hkarthik7azd
- 6.1.3
+ 7.0.0sources
```
@@ -100,6 +102,31 @@ public class Main {
}
```
+**Authentication using service principal**
+
+To use spn authentication you should create a new app registration in Entra ID, grant Api permissions on Azure DevOps, select right scope
+and grant admin consent.
+
+```java
+public class Main {
+ public static void main(String[] args) {
+ String project = "myProject";
+ String baseUrl = "https://dev.azure.com/{organization}";
+ // or TFS URL
+ String baseUrl = "https://{server:port}/tfs/{collection}";
+
+ String tenantId = "tenantId";
+ String clientId = "clientId";
+ String clientSecret = "clientSecret";
+
+ AccessTokenCredential spn = new ServicePrincipalAccessTokenCredential(
+ baseUrl,
+ project, tenantId,
+ clientId, clientSecret);
+ }
+}
+```
+
- Sample usage
```java
@@ -110,6 +137,8 @@ public class Main {
AzDServiceClient client = AzDService.builder().authentication(pat).buildClient();
// or
AzDServiceClient client = AzDService.builder().authentication(oauth).buildClient();
+ // or
+ AzDServiceClient client = AzDService.builder().authentication(spn).buildClient();
try {
// Get the list of projects. This return a future object.
diff --git a/azd/pom.xml b/azd/pom.xml
index 11b6f807..64d64103 100644
--- a/azd/pom.xml
+++ b/azd/pom.xml
@@ -6,7 +6,7 @@
io.github.hkarthik7azd
- 6.1.3
+ 7.0.0jarazd
diff --git a/azd/src/main/java/org/azd/abstractions/ClientConfiguration.java b/azd/src/main/java/org/azd/abstractions/ClientConfiguration.java
index 4ba753b6..025ce6ab 100644
--- a/azd/src/main/java/org/azd/abstractions/ClientConfiguration.java
+++ b/azd/src/main/java/org/azd/abstractions/ClientConfiguration.java
@@ -1,14 +1,11 @@
package org.azd.abstractions;
-import org.azd.abstractions.handlers.RetryHandler;
-
/**
* Singleton class that configures Api request options.
*/
public class ClientConfiguration {
private final static ClientConfiguration instance = new ClientConfiguration();
private static RequestOption reqOption;
- private static RetryHandler retry;
private ClientConfiguration() {
}
@@ -29,14 +26,6 @@ public RequestOption getRequestOption() {
return reqOption;
}
- /**
- * Get the retry handler object.
- * @return RetryHandler.
- */
- public RetryHandler getRetryHandler() {
- return retry;
- }
-
/**
* Configures the request option.
* @param requestOption Request option object to configure.
@@ -44,12 +33,4 @@ public RetryHandler getRetryHandler() {
public void configureRequestOption(RequestOption requestOption) {
reqOption = requestOption;
}
-
- /**
- * Configures the retry handler options.
- * @param retryHandler Retry handler object to configure.
- */
- public void configureRetryHandler(RetryHandler retryHandler) {
- retry = retryHandler;
- }
}
diff --git a/azd/src/main/java/org/azd/abstractions/HttpRequestFactory.java b/azd/src/main/java/org/azd/abstractions/HttpRequestFactory.java
index 879585bf..7cb56345 100644
--- a/azd/src/main/java/org/azd/abstractions/HttpRequestFactory.java
+++ b/azd/src/main/java/org/azd/abstractions/HttpRequestFactory.java
@@ -5,7 +5,6 @@
import org.azd.common.Constants;
import org.azd.exceptions.AzDException;
-import java.net.URI;
import java.net.http.HttpRequest;
/**
diff --git a/azd/src/main/java/org/azd/abstractions/InstanceFactory.java b/azd/src/main/java/org/azd/abstractions/InstanceFactory.java
index 7d7f071d..2925c9b4 100644
--- a/azd/src/main/java/org/azd/abstractions/InstanceFactory.java
+++ b/azd/src/main/java/org/azd/abstractions/InstanceFactory.java
@@ -1,7 +1,8 @@
package org.azd.abstractions;
-import org.azd.abstractions.handlers.RequestExecutor;
-import org.azd.abstractions.handlers.RetryHandler;
+import org.azd.abstractions.handlers.*;
+import org.azd.abstractions.pipelines.ResponsePipeline;
+import org.azd.abstractions.pipelines.ResponsePipelineBuilder;
import org.azd.abstractions.serializer.JsonSerializer;
import org.azd.abstractions.serializer.SerializerContext;
import org.azd.authentication.AccessTokenCredential;
@@ -24,6 +25,10 @@ public static SerializerContext createSerializerContext() {
return new JsonSerializer();
}
+ public static RetryHandler createRetryHandler() {
+ return new DefaultRetryHandler();
+ }
+
/**
* Creates an instance of HttpClient.
* @return HttpClient {@link HttpClient}.
@@ -46,16 +51,15 @@ public static HttpRequest createHttpRequest(AccessTokenCredential accessTokenCre
}
/**
- * Creates an instance of response handler object.
- * @param accessTokenCredential Access token credential object.
- * @param requestInformation Request information object to set the request url, request body.
- * @return ResponseHandler {@link ResponseHandler}.
+ * Creates the response pipeline with all handlers.
+ * @return ResponsePipeline with default response handlers.
*/
- public static ResponseHandler createResponseHandler(AccessTokenCredential accessTokenCredential,
- RequestInformation requestInformation) {
- var retryHandler = ClientConfiguration.getInstance().getRetryHandler();
- retryHandler = retryHandler == null ? new RetryHandler(
- new RequestExecutor(accessTokenCredential, requestInformation)) : retryHandler;
- return ResponseHandler.create(retryHandler);
+ public static ResponsePipeline createResponsePipeline() {
+ return ResponsePipelineBuilder.create()
+ .add(ApiResponseHandler::new)
+ .add(RedirectResponseHandler::new)
+ .add(() -> new ErrorResponseHandler(createSerializerContext()))
+ .add(() -> new SerializerHandler(createSerializerContext()))
+ .build();
}
}
diff --git a/azd/src/main/java/org/azd/abstractions/ResponseHandler.java b/azd/src/main/java/org/azd/abstractions/ResponseHandler.java
index 4391fd24..6ba9d0de 100644
--- a/azd/src/main/java/org/azd/abstractions/ResponseHandler.java
+++ b/azd/src/main/java/org/azd/abstractions/ResponseHandler.java
@@ -1,28 +1,36 @@
package org.azd.abstractions;
-import org.azd.abstractions.handlers.DefaultResponseHandler;
-import org.azd.abstractions.handlers.RetryHandler;
+import org.azd.abstractions.handlers.ResponseContext;
-import java.net.http.HttpResponse;
+import java.util.concurrent.CompletableFuture;
/**
- * Handler the Api response.
+ * Handles the Api response.
*/
public abstract class ResponseHandler {
- protected static ApiResponse apiResponse;
- protected final RetryHandler retryHandler;
+ protected ResponseHandler next;
+ private static ApiResponse apiResponse;
- protected ResponseHandler(RetryHandler retryHandler) {
- this.retryHandler = retryHandler;
+ /**
+ * Sets the next handler in pipeline.
+ * @param next Next handler to invoke
+ * @return ResponseHandler handler.
+ */
+ public ResponseHandler setNext(ResponseHandler next) {
+ this.next = next;
+ return next;
}
/**
- * Creates an instance of Response handler.
- * @param retryHandler Retry handler to retry the request.
- * @return Response handler object.
+ * Invokes the next handler in the pipeline
+ * @param context Response context object container.
+ * @return Result of invocation.
*/
- public static ResponseHandler create(RetryHandler retryHandler) {
- return new DefaultResponseHandler(retryHandler);
+ protected CompletableFuture nextAsync(ResponseContext context) {
+ if (next == null) {
+ return CompletableFuture.completedFuture(null);
+ }
+ return next.handleAsync(context);
}
/**
@@ -35,11 +43,16 @@ public static ApiResponse getResponse() {
/**
* Handles the Api response.
- * @param response Http response object.
- * @param requestInformation Request information object. {@link RequestInformation}.
+ * @param context ResponseContext object {@link ResponseContext}
* @return Java type value that is passed.
- * @param Type parameter.
*/
- public abstract T handle(HttpResponse response, RequestInformation requestInformation);
+ public abstract CompletableFuture handleAsync(ResponseContext context);
+ /**
+ * Sets the Api response object.
+ * @param response ApiResponse object to set {@link ApiResponse}
+ */
+ public static void setResponse(ApiResponse response) {
+ apiResponse = response;
+ }
}
diff --git a/azd/src/main/java/org/azd/abstractions/handlers/ApiResponseHandler.java b/azd/src/main/java/org/azd/abstractions/handlers/ApiResponseHandler.java
new file mode 100644
index 00000000..ba15c605
--- /dev/null
+++ b/azd/src/main/java/org/azd/abstractions/handlers/ApiResponseHandler.java
@@ -0,0 +1,24 @@
+package org.azd.abstractions.handlers;
+
+import org.azd.abstractions.ApiResponse;
+import org.azd.abstractions.ResponseHandler;
+import org.azd.enums.HttpStatusCode;
+
+import java.util.concurrent.CompletableFuture;
+
+public final class ApiResponseHandler extends ResponseHandler {
+ @Override
+ public CompletableFuture handleAsync(ResponseContext context) {
+ var response = context.response();
+
+ setResponse(new ApiResponse(
+ HttpStatusCode.from(response.statusCode()),
+ response.headers().map(),
+ response.body(),
+ response.request().uri().toString(),
+ context.request()
+ ));
+
+ return nextAsync(context);
+ }
+}
diff --git a/azd/src/main/java/org/azd/abstractions/handlers/ContentType.java b/azd/src/main/java/org/azd/abstractions/handlers/ContentType.java
new file mode 100644
index 00000000..940bb252
--- /dev/null
+++ b/azd/src/main/java/org/azd/abstractions/handlers/ContentType.java
@@ -0,0 +1,36 @@
+package org.azd.abstractions.handlers;
+
+import org.azd.enums.CustomHeader;
+import org.azd.utils.StringUtils;
+
+import java.net.http.HttpResponse;
+import java.util.Locale;
+import java.util.Objects;
+
+public final class ContentType {
+ private final String value;
+
+ private ContentType(String value) {
+ this.value = value.toLowerCase(Locale.ROOT);
+ }
+
+ public static ContentType from(HttpResponse> response) {
+ Objects.requireNonNull(response, "Response cannot be null.");
+
+ return response.headers()
+ .firstValue(CustomHeader.JSON_CONTENT_TYPE.getName())
+ .map(x -> new ContentType(x.split(";")[0].trim()))
+ .orElse(new ContentType(StringUtils.EMPTY));
+
+ }
+
+ boolean isJson() { return value.equals(CustomHeader.JSON_CONTENT_TYPE.getValue()); }
+ boolean isText() { return value.equals(CustomHeader.TEXT_CONTENT.getValue()); }
+ boolean isHtml() { return value.equals(CustomHeader.HTML_CONTENT.getValue()); }
+ boolean isXml() { return value.equals(CustomHeader.XML_CONTENT_TYPE.getValue()); }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+}
diff --git a/azd/src/main/java/org/azd/abstractions/handlers/DefaultResponseHandler.java b/azd/src/main/java/org/azd/abstractions/handlers/DefaultResponseHandler.java
deleted file mode 100644
index a4433d21..00000000
--- a/azd/src/main/java/org/azd/abstractions/handlers/DefaultResponseHandler.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package org.azd.abstractions.handlers;
-
-import org.azd.abstractions.ApiResponse;
-import org.azd.abstractions.RequestInformation;
-import org.azd.abstractions.ResponseHandler;
-import org.azd.enums.HttpStatusCode;
-
-import java.net.http.HttpResponse;
-import java.util.OptionalLong;
-
-/**
- * Implementation of response handler.
- */
-public class DefaultResponseHandler extends ResponseHandler {
-
- public DefaultResponseHandler(RetryHandler handler) {
- super(handler);
- }
-
- /**
- * Handles response from the API.
- * @param response HttpResponse object.
- * @param requestInformation Request information sent to the API.
- * @return Object or any specified type.
- * @param Type parameter.
- */
- @Override
- public T handle(HttpResponse response, RequestInformation requestInformation) {
- apiResponse = new ApiResponse(HttpStatusCode.getByCode(response.statusCode()), response.headers().map(),
- response.body(), response.request().uri().toString(), requestInformation);
-
- if (shouldRetry(response)) apiResponse = retryHandler.retry(apiResponse);
-
- return (T) apiResponse.getResponseBody();
- }
-
- /**
- * Determines the Api retries.
- * @param response HttpResponse object.
- * @return A boolean.
- * @param Type parameter.
- */
- private boolean shouldRetry(HttpResponse response) {
- var retry = OptionalLong.empty();
- if (response.headers() != null) {
- retry = response.headers().firstValueAsLong("Retry-After");
- }
- return response.statusCode() >= 500 || retry.isPresent();
- }
-}
diff --git a/azd/src/main/java/org/azd/abstractions/handlers/DefaultRetryHandler.java b/azd/src/main/java/org/azd/abstractions/handlers/DefaultRetryHandler.java
new file mode 100644
index 00000000..ef4cc645
--- /dev/null
+++ b/azd/src/main/java/org/azd/abstractions/handlers/DefaultRetryHandler.java
@@ -0,0 +1,67 @@
+package org.azd.abstractions.handlers;
+
+import java.net.http.HttpResponse;
+import java.util.OptionalLong;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Retries the Api call based on Retry-After header value.
+ */
+public class DefaultRetryHandler implements RetryHandler {
+ /**
+ * Maximum retries
+ */
+ private static final int MAX_RETRIES = 6;
+
+ /**
+ * Executes the given retryable operation.
+ * @param operation Function to retry
+ * @return Future of HttpResponse object
+ * @param Typed value.
+ */
+ @Override
+ public CompletableFuture> executeAsync(Retryable operation) {
+ return retry(operation, 1);
+ }
+
+ /**
+ * Retries the given retryable operation.
+ * @param operation Function to retry
+ * @param attempt number of attempts to retry.
+ * @return Future of HttpResponse object
+ * @param Typed value.
+ */
+ private CompletableFuture> retry(Retryable operation, int attempt) {
+ return operation.run().thenCompose(response -> {
+ var retryAfter = response.headers().firstValueAsLong("Retry-After");
+
+ if (shouldRetry(response.statusCode(), retryAfter, attempt)) {
+ long delayMillis = retryAfter.getAsLong() * 1000;
+ return CompletableFuture
+ .runAsync(() -> { },
+ CompletableFuture.delayedExecutor(
+ delayMillis,
+ TimeUnit.MILLISECONDS))
+ .thenCompose(v -> retry(operation, attempt + 1));
+ }
+
+ return CompletableFuture.completedFuture(response);
+ });
+ }
+
+ /**
+ * Returns true if the status code is 429, 503 or retry after interval is present.
+ * @param status Http status code.
+ * @param retryAfter Retry after interval in seconds.
+ * @param attempt Number of attempts. Maximum is 6.
+ * @return boolean.
+ */
+ private boolean shouldRetry(int status, OptionalLong retryAfter, int attempt) {
+ if (attempt >= MAX_RETRIES) {
+ return false;
+ }
+ return (status == 429 || status == 503)
+ && retryAfter.isPresent();
+ }
+}
diff --git a/azd/src/main/java/org/azd/abstractions/handlers/ErrorResponseHandler.java b/azd/src/main/java/org/azd/abstractions/handlers/ErrorResponseHandler.java
new file mode 100644
index 00000000..93955381
--- /dev/null
+++ b/azd/src/main/java/org/azd/abstractions/handlers/ErrorResponseHandler.java
@@ -0,0 +1,139 @@
+package org.azd.abstractions.handlers;
+
+import org.azd.abstractions.ResponseHandler;
+import org.azd.abstractions.serializer.SerializerContext;
+import org.azd.enums.ApiExceptionTypes;
+import org.azd.exceptions.ApiException;
+import org.azd.exceptions.AzDException;
+import org.azd.helpers.StreamHelper;
+
+import java.io.InputStream;
+import java.util.concurrent.CompletableFuture;
+
+public final class ErrorResponseHandler extends ResponseHandler {
+
+ private final SerializerContext serializer;
+
+ public ErrorResponseHandler(SerializerContext serializer) {
+ this.serializer = serializer;
+ }
+
+ @Override
+ public CompletableFuture handleAsync(ResponseContext context) {
+ int status = context.statusCode();
+
+ if (status == 203) {
+ return CompletableFuture.failedFuture(
+ new AzDException(
+ ApiExceptionTypes.InvalidPersonalAccessTokenException.toString(),
+ "Personal access token passed is invalid; Please pass the valid token and try again."
+ )
+ );
+ }
+
+ if (status < 400) {
+ return nextAsync(context);
+ }
+
+ if (status == 401) {
+ return CompletableFuture.failedFuture(
+ new AzDException(
+ ApiExceptionTypes.UnAuthorizedException.toString(),
+ "Given token doesn't have access to resource '"
+ + context.request().getRequestUri() + "'."
+ )
+ );
+ }
+
+ if (RedirectUtils.hasCallback(context)) {
+ return nextAsync(context);
+ }
+
+ if (context.contentType().isXml()) {
+ try {
+ String error;
+ if (context.body() instanceof InputStream) {
+ error = StreamHelper.convertToString((InputStream) context.body());
+ } else {
+ error = String.valueOf(context.body());
+ }
+
+ return CompletableFuture.failedFuture(
+ new AzDException(ApiExceptionTypes.UnknownError.toString(), error)
+ );
+ } catch (AzDException e) {
+ return CompletableFuture.failedFuture(e);
+ }
+ }
+
+ if (context.contentType().isJson() && context.body() instanceof String) {
+
+ String body = context.body().toString();
+
+ if (body.contains("innerException")) {
+ try {
+ var error = serializer.deserialize(body, ApiException.class);
+
+ return CompletableFuture.failedFuture(
+ new AzDException(error.getTypeKey(), error.getMessage())
+ );
+
+ } catch (AzDException e) {
+ return CompletableFuture.failedFuture(e);
+ }
+ }
+
+ return CompletableFuture.failedFuture(new AzDException(body));
+ }
+
+ if (context.contentType().isJson() && context.body() instanceof InputStream) {
+
+ try {
+ var stream = (InputStream) context.body();
+ var body = StreamHelper.convertToString(stream);
+
+ if (body.contains("innerException")) {
+ try {
+ var error = serializer.deserialize(body, ApiException.class);
+
+ return CompletableFuture.failedFuture(
+ new AzDException(error.getTypeKey(), error.getMessage())
+ );
+
+ } catch (AzDException e) {
+ return CompletableFuture.failedFuture(e);
+ }
+ }
+
+ return CompletableFuture.failedFuture(new AzDException(body));
+ } catch (AzDException e) {
+ return CompletableFuture.failedFuture(e);
+ }
+ }
+
+ if (context.contentType().isText() || context.contentType().isHtml()) {
+
+ String body = context.body().toString();
+
+ if (body.contains("The resource cannot be found.")) {
+ return CompletableFuture.failedFuture(
+ new AzDException(
+ ApiExceptionTypes.InvalidOrganizationNameException.toString(),
+ "Server url '" +
+ context.request().accessTokenCredential.getOrganizationUrl()
+ + "' passed is invalid; Please pass the valid url and try again."
+ )
+ );
+ }
+
+ return CompletableFuture.failedFuture(new AzDException(body));
+ }
+
+ return CompletableFuture.failedFuture(
+ new AzDException(
+ ApiExceptionTypes.UnknownError.toString(),
+ String.valueOf(context.body())
+ )
+ );
+ }
+}
diff --git a/azd/src/main/java/org/azd/abstractions/handlers/RedirectResponseHandler.java b/azd/src/main/java/org/azd/abstractions/handlers/RedirectResponseHandler.java
new file mode 100644
index 00000000..7ae51b28
--- /dev/null
+++ b/azd/src/main/java/org/azd/abstractions/handlers/RedirectResponseHandler.java
@@ -0,0 +1,39 @@
+package org.azd.abstractions.handlers;
+
+import org.azd.abstractions.ResponseHandler;
+import org.azd.enums.CustomHeader;
+import org.azd.exceptions.AzDException;
+import org.azd.http.ClientRequest;
+
+import java.util.concurrent.CompletableFuture;
+
+public final class RedirectResponseHandler extends ResponseHandler {
+ @Override
+ public CompletableFuture handleAsync(ResponseContext context) {
+
+ if (!RedirectUtils.hasCallback(context)) {
+ return nextAsync(context);
+ }
+
+ var uriOpt = RedirectUtils.extractCallback(context);
+
+ if (uriOpt.isEmpty()) {
+ return CompletableFuture.failedFuture(
+ new AzDException("Redirect detected but no callback URL found.")
+ );
+ }
+
+ var uri = uriOpt.get();
+
+ return ClientRequest.builder()
+ .URI(uri)
+ .header(CustomHeader.STREAM_ACCEPT)
+ .build()
+ .executeStreamAsync()
+ .thenCompose(stream -> {
+ context.setBody(stream);
+ context.setStatusCode(200);
+ return nextAsync(context);
+ });
+ }
+}
\ No newline at end of file
diff --git a/azd/src/main/java/org/azd/abstractions/handlers/RedirectUtils.java b/azd/src/main/java/org/azd/abstractions/handlers/RedirectUtils.java
new file mode 100644
index 00000000..2916c24d
--- /dev/null
+++ b/azd/src/main/java/org/azd/abstractions/handlers/RedirectUtils.java
@@ -0,0 +1,71 @@
+package org.azd.abstractions.handlers;
+
+import org.azd.abstractions.InstanceFactory;
+
+import java.net.URI;
+import java.util.Map;
+import java.util.Optional;
+
+public final class RedirectUtils {
+
+ public static boolean isRedirectStatus(int status) {
+ return status == 301 || status == 302 || status == 303
+ || status == 307 || status == 308;
+ }
+
+ public static boolean hasCallback(ResponseContext context) {
+ int status = context.statusCode();
+
+ if (!isRedirectStatus(status) && status != 403) {
+ return false;
+ }
+
+ if (context.response().uri() != null && status == 403) {
+ return true;
+ }
+
+ if (context.header("Location").isPresent()) {
+ return true;
+ }
+
+ if (context.contentType().isJson() && context.body() instanceof String) {
+ var body = (String) context.body();
+ return body.contains("downloadUrl") || body.contains("url");
+ }
+
+ return false;
+ }
+
+ public static Optional extractCallback(ResponseContext context) {
+
+ try {
+ var location = context.header("Location");
+ if (location.isPresent()) {
+ return Optional.of(URI.create(location.get()));
+ }
+
+ if (context.response() != null && context.response().uri() != null) {
+ return Optional.of(context.response().uri());
+ }
+
+ if (context.contentType().isJson() && context.body() instanceof String) {
+ var body = (String) context.body();
+ final var serializer = InstanceFactory.createSerializerContext();
+ var map = serializer.deserialize(body, Map.class);
+
+ if (map.containsKey("downloadUrl")) {
+ return Optional.of(URI.create(map.get("downloadUrl").toString()));
+ }
+
+ if (map.containsKey("url")) {
+ return Optional.of(URI.create(map.get("url").toString()));
+ }
+ }
+
+ return Optional.empty();
+
+ } catch (Exception e) {
+ return Optional.empty();
+ }
+ }
+}
diff --git a/azd/src/main/java/org/azd/abstractions/handlers/RequestExecutor.java b/azd/src/main/java/org/azd/abstractions/handlers/RequestExecutor.java
deleted file mode 100644
index ba3136a8..00000000
--- a/azd/src/main/java/org/azd/abstractions/handlers/RequestExecutor.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.azd.abstractions.handlers;
-
-import org.azd.abstractions.ApiResponse;
-import org.azd.abstractions.RequestInformation;
-import org.azd.abstractions.ResponseHandler;
-import org.azd.authentication.AccessTokenCredential;
-import org.azd.exceptions.AzDException;
-import org.azd.http.ClientRequest;
-
-/**
- * Executes the given request.
- */
-public class RequestExecutor {
- private final RequestInformation reqInfo;
- private final AccessTokenCredential accessTokenCredential;
-
- public RequestExecutor(AccessTokenCredential accessTokenCredential,
- RequestInformation requestInformation) {
- this.reqInfo = requestInformation;
- this.accessTokenCredential = accessTokenCredential;
- }
-
- /**
- * Executes the given request and returns the Api response.
- * @return ApiResponse {@link ApiResponse}.
- * @throws AzDException Default exception handler.
- */
- public ApiResponse execute() throws AzDException {
- ClientRequest.builder(accessTokenCredential)
- .request(reqInfo)
- .build()
- .executeStringAsync()
- .join();
- return ResponseHandler.getResponse();
- }
-}
diff --git a/azd/src/main/java/org/azd/abstractions/handlers/ResponseContext.java b/azd/src/main/java/org/azd/abstractions/handlers/ResponseContext.java
new file mode 100644
index 00000000..ffd9f249
--- /dev/null
+++ b/azd/src/main/java/org/azd/abstractions/handlers/ResponseContext.java
@@ -0,0 +1,62 @@
+package org.azd.abstractions.handlers;
+
+import org.azd.abstractions.RequestInformation;
+
+import java.net.http.HttpResponse;
+import java.util.Optional;
+
+public final class ResponseContext {
+ private final HttpResponse> response;
+ private final RequestInformation request;
+ private final Class> model;
+ private final ContentType contentType;
+ private Object body;
+ private int statusCode;
+
+ public ResponseContext(HttpResponse> response,
+ RequestInformation request,
+ Class> model) {
+ this.response = response;
+ this.request = request;
+ this.model = model;
+ this.body = response.body();
+ this.statusCode = response.statusCode();
+ this.contentType = ContentType.from(response);
+ }
+
+ public HttpResponse> response() {
+ return response;
+ }
+
+ public RequestInformation request() {
+ return request;
+ }
+
+ public ContentType contentType() {
+ return contentType;
+ }
+ public Class> model() {
+ return model;
+ }
+
+ public Object body() {
+ return body;
+ }
+
+ public void setBody(Object body) {
+ this.body = body;
+ }
+
+ public int statusCode() {
+ return statusCode;
+ }
+
+ public void setStatusCode(int statusCode) {
+ this.statusCode = statusCode;
+ }
+
+ public Optional header(String value) {
+ return response.headers().firstValue(value);
+ }
+}
+
diff --git a/azd/src/main/java/org/azd/abstractions/handlers/ResponseHandlerFactory.java b/azd/src/main/java/org/azd/abstractions/handlers/ResponseHandlerFactory.java
new file mode 100644
index 00000000..8fe464d2
--- /dev/null
+++ b/azd/src/main/java/org/azd/abstractions/handlers/ResponseHandlerFactory.java
@@ -0,0 +1,8 @@
+package org.azd.abstractions.handlers;
+
+import org.azd.abstractions.ResponseHandler;
+
+@FunctionalInterface
+public interface ResponseHandlerFactory {
+ ResponseHandler create();
+}
diff --git a/azd/src/main/java/org/azd/abstractions/handlers/RetryHandler.java b/azd/src/main/java/org/azd/abstractions/handlers/RetryHandler.java
index b33b38f5..b6a9cc14 100644
--- a/azd/src/main/java/org/azd/abstractions/handlers/RetryHandler.java
+++ b/azd/src/main/java/org/azd/abstractions/handlers/RetryHandler.java
@@ -1,84 +1,8 @@
package org.azd.abstractions.handlers;
-import org.azd.abstractions.ApiResponse;
-import org.azd.exceptions.AzDException;
+import java.net.http.HttpResponse;
+import java.util.concurrent.CompletableFuture;
-import java.net.http.HttpHeaders;
-import java.util.OptionalLong;
-
-/**
- * Retries the Api call based on Retry-After header value.
- */
-public class RetryHandler {
- private final int MAX_RETRIES = 6;
- private final long RETRY_IN_MILLISECONDS = 1000;
- private final RequestExecutor executor;
- private int DEFAULT_MAX_RETRIES = 3;
-
- public RetryHandler(RequestExecutor executor) {
- this.executor = executor;
- }
-
- /**
- * Retries the Api call for the given Api response object. Determines the request information and
- * retries the request for maximum of 6 times.
- * @param response Api response object {@link ApiResponse}.
- * @return Retries Api response. {@link ApiResponse}.
- * @param Type parameter.
- */
- public ApiResponse retry(ApiResponse response) {
- var executionCount = 1;
- while (executionCount < DEFAULT_MAX_RETRIES) {
- var headers = response.getResponseHeaders();
- if (retryAfterInterval(headers).isPresent()) {
- try {
- var delay = retryAfterInterval(headers).getAsLong() * RETRY_IN_MILLISECONDS;
- Thread.sleep(delay);
- executionCount++;
- // Call Api
- response = executor.execute();
- } catch (InterruptedException | AzDException e) {
- Thread.currentThread().interrupt();
- throw new RuntimeException(e);
- }
- } else break;
- }
- return response;
- }
-
- /**
- * Get the default max retry value.
- * @return Default retry value which is 6.
- */
- public int getDefaultMaxRetry() {
- return this.DEFAULT_MAX_RETRIES;
- }
-
- /**
- * Sets the default max retry value.
- * @param defaultMaxRetry Default value to set. The value can't be more than 6.
- */
- public void setDefaultMaxRetry(int defaultMaxRetry) {
- if (defaultMaxRetry > MAX_RETRIES || defaultMaxRetry < 0)
- throw new IllegalArgumentException("Max retry value cannot be less than 0 or greater than 6.");
- this.DEFAULT_MAX_RETRIES = defaultMaxRetry;
- }
-
- /**
- * Http Headers of last request. We want to make these accessible everywhere (i.e) something that
- * can be checked after every request, but we don't want to have to modify all the existing API methods
- * to return the data.
- *
- * We need this to be able to check if we are near any API rate limits - as creating 20+ releases in
- * a short time can cause one to go over the limit and even have requests fail.
- * Method to get retryAfterInterval value from response header
- *
- * @return Value in seconds (if it exists in header) of how long we should wait to send next request.
- */
- private OptionalLong retryAfterInterval(HttpHeaders headers) {
- if (headers != null) {
- return headers.firstValueAsLong("Retry-After");
- }
- return OptionalLong.empty();
- }
+public interface RetryHandler {
+ CompletableFuture> executeAsync(Retryable operation);
}
diff --git a/azd/src/main/java/org/azd/abstractions/handlers/Retryable.java b/azd/src/main/java/org/azd/abstractions/handlers/Retryable.java
new file mode 100644
index 00000000..62ec89ce
--- /dev/null
+++ b/azd/src/main/java/org/azd/abstractions/handlers/Retryable.java
@@ -0,0 +1,8 @@
+package org.azd.abstractions.handlers;
+
+import java.net.http.HttpResponse;
+import java.util.concurrent.CompletableFuture;
+
+public interface Retryable {
+ CompletableFuture> run();
+}
diff --git a/azd/src/main/java/org/azd/abstractions/handlers/SerializerHandler.java b/azd/src/main/java/org/azd/abstractions/handlers/SerializerHandler.java
new file mode 100644
index 00000000..009a38f9
--- /dev/null
+++ b/azd/src/main/java/org/azd/abstractions/handlers/SerializerHandler.java
@@ -0,0 +1,52 @@
+package org.azd.abstractions.handlers;
+
+import org.azd.abstractions.ResponseHandler;
+import org.azd.abstractions.serializer.SerializerContext;
+import org.azd.exceptions.AzDException;
+import org.azd.helpers.StreamHelper;
+
+import java.io.InputStream;
+import java.util.concurrent.CompletableFuture;
+
+public final class SerializerHandler extends ResponseHandler {
+ private final SerializerContext serializer;
+
+ public SerializerHandler(SerializerContext serializer) {
+ this.serializer = serializer;
+ }
+
+ @Override
+ public CompletableFuture handleAsync(ResponseContext context) {
+ if (context.model() == null) {
+ return nextAsync(context);
+ }
+
+ try {
+ var body = context.body();
+
+ if (context.model().isInstance(body)) {
+ return nextAsync(context);
+ }
+
+ if (context.contentType().isJson() && body instanceof String) {
+ var json = (String) context.body();
+ var model = serializer.deserialize(json, context.model());
+ context.setBody(model);
+ return nextAsync(context);
+ }
+
+ if (context.contentType().isJson() && body instanceof InputStream) {
+ var stream = (InputStream) context.body();
+ var json = StreamHelper.convertToString(stream);
+ var model = serializer.deserialize(json, context.model());
+ context.setBody(model);
+ return nextAsync(context);
+ }
+
+ return nextAsync(context);
+
+ } catch (AzDException e) {
+ return CompletableFuture.failedFuture(e);
+ }
+ }
+}
diff --git a/azd/src/main/java/org/azd/abstractions/internals/ClientRequestAdapter.java b/azd/src/main/java/org/azd/abstractions/internals/ClientRequestAdapter.java
index 58e2782d..57546df3 100644
--- a/azd/src/main/java/org/azd/abstractions/internals/ClientRequestAdapter.java
+++ b/azd/src/main/java/org/azd/abstractions/internals/ClientRequestAdapter.java
@@ -2,9 +2,10 @@
import org.azd.abstractions.InstanceFactory;
import org.azd.abstractions.RequestInformation;
-import org.azd.abstractions.ResponseHandler;
+import org.azd.abstractions.handlers.ResponseContext;
+import org.azd.abstractions.handlers.RetryHandler;
+import org.azd.abstractions.pipelines.ResponsePipeline;
import org.azd.abstractions.serializer.SerializableEntity;
-import org.azd.abstractions.serializer.SerializerContext;
import org.azd.authentication.AccessTokenCredential;
import org.azd.exceptions.AzDException;
import org.azd.http.ClientRequest;
@@ -13,9 +14,9 @@
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
-import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
/**
* Implementation of the ClientRequest that executes or sends the request to
@@ -30,14 +31,6 @@ public final class ClientRequestAdapter extends ClientRequest {
* Request information with all required parameters.
*/
private final RequestInformation reqInfo;
- /**
- * Serializer context to serialize and deserialize the objects.
- */
- private final SerializerContext serializer;
- /**
- * Response handler to handle the API response.
- */
- private final ResponseHandler handler;
/**
* HttpClient object to send the request.
*/
@@ -46,133 +39,170 @@ public final class ClientRequestAdapter extends ClientRequest {
* Http request object to construct the request.
*/
private final HttpRequest request;
+ private final ResponsePipeline pipeline;
+ private final RetryHandler retryHandler;
/**
* Default.
+ *
* @param builder Client request builder object.
*/
public ClientRequestAdapter(ClientRequestBuilder builder) {
this.reqInfo = Objects.requireNonNull(builder.request());
this.accessTokenCredential = builder.accessTokenCredential();
this.client = InstanceFactory.createHttpClient();
- this.serializer = InstanceFactory.createSerializerContext();
- this.handler = InstanceFactory.createResponseHandler(this.accessTokenCredential, this.reqInfo);
this.request = InstanceFactory.createHttpRequest(this.accessTokenCredential, this.reqInfo);
+ this.pipeline = InstanceFactory.createResponsePipeline();
+ this.retryHandler = InstanceFactory.createRetryHandler();
}
/**
* Executes the raw request without serialization.
+ *
* @return String response from API.
- * @throws AzDException Default API exception handler.
*/
@Override
- public CompletableFuture executeStringAsync() throws AzDException {
- return client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
- .thenApplyAsync(resp -> handler.handle(resp, reqInfo));
+ public CompletableFuture executeStringAsync() {
+ return retryHandler.executeAsync(() ->
+ client.sendAsync(request, HttpResponse.BodyHandlers.ofString()))
+ .thenCompose(resp -> {
+ var context = new ResponseContext(resp, reqInfo, null);
+ return pipeline.processAsync(context);
+ });
}
/**
* Executes the request and returns the deserialized response.
+ *
* @param model Represents the entity or model for which the response should be deserialized to.
+ * @param Represents model.
* @return Deserialized response from API.
- * @param Represents model.
- * @throws AzDException Default API exception handler.
*/
@Override
- public CompletableFuture executeAsync(Class model) throws AzDException {
- return client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
- .thenApplyAsync(resp -> {
- try {
- var response = handler.handle(resp, reqInfo);
- return serializer.deserialize(response, model);
- } catch (AzDException e) {
- throw new RuntimeException(e);
- }
- });
+ public CompletableFuture executeAsync(Class model) {
+ return retryHandler.executeAsync(() ->
+ client.sendAsync(request, HttpResponse.BodyHandlers.ofString()))
+ .thenCompose(resp -> {
+ var context = new ResponseContext(resp, reqInfo, model);
+ return pipeline.processAsync(context);
+ })
+ .thenApplyAsync(model::cast);
+
}
/**
* Executes the request and returns the stream response from API.
+ *
* @return Stream response. {@link InputStream}
- * @throws AzDException Default API exception handler.
*/
@Override
- public CompletableFuture executeStreamAsync() throws AzDException {
- return client.sendAsync(request, HttpResponse.BodyHandlers.ofInputStream())
- .thenApplyAsync(resp -> handler.handle(resp, reqInfo));
+ public CompletableFuture executeStreamAsync() {
+ return retryHandler.executeAsync(() ->
+ client.sendAsync(request, HttpResponse.BodyHandlers.ofInputStream()))
+ .thenCompose(resp -> {
+ var context = new ResponseContext(resp, reqInfo, null);
+ return pipeline.processAsync(context);
+ });
}
/**
- * Executes the request and doesn't return any response. Useful for DELETE operations.
- * @return Void.
- * @throws AzDException Default API exception handler.
+ * Executes the request built by ClientRequest.Builder and doesn't return any response. This is mainly used for Api calls
+ * that returns 201 or any operation that doesn't return response.
+ *
+ * @return Future void.
*/
@Override
- public CompletableFuture executePrimitiveAsync() throws AzDException {
- return client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
- .thenAcceptAsync(resp -> {
- var response = handler.handle(resp, reqInfo);
- if (!response.isEmpty()) {
- try {
- serializer.deserialize(response, Map.class);
- } catch (AzDException e) {
- throw new RuntimeException(e);
- }
- }
+ public CompletableFuture executePrimitiveAsync() {
+ return retryHandler.executeAsync(() ->
+ client.sendAsync(request, HttpResponse.BodyHandlers.ofString()))
+ .thenCompose(resp -> {
+ var context = new ResponseContext(resp, reqInfo, null);
+ return pipeline.processAsync(context)
+ .thenApply(result -> null);
});
}
/**
* Executes the request and returns the deserialized response.
+ *
* @param model Represents the entity or model for which the response should be deserialized to.
+ * @param Represents model.
* @return Deserialized response from API.
- * @param Represents model.
* @throws AzDException Default API exception handler.
*/
@Override
public T execute(Class model) throws AzDException {
- var result = client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
- .thenApplyAsync(resp -> handler.handle(resp, reqInfo)).join();
- return serializer.deserialize(result, model);
-
+ try {
+ return executeAsync(model).join();
+ } catch (CompletionException e) {
+ var cause = e.getCause();
+ if (cause instanceof AzDException) {
+ throw (AzDException) cause;
+ }
+ throw new AzDException(cause.getMessage());
+ }
}
/**
* Executes the raw request without serialization.
+ *
* @return String response from API.
* @throws AzDException Default API exception handler.
*/
@Override
public String executeString() throws AzDException {
- return executeStringAsync().join();
+ try {
+ return executeStringAsync().join();
+ } catch (CompletionException e) {
+ var cause = e.getCause();
+ if (cause instanceof AzDException) {
+ throw (AzDException) cause;
+ }
+ throw new AzDException(cause.getMessage());
+ }
}
/**
* Executes the request and returns the stream response from API.
+ *
* @return Stream response. {@link InputStream}
* @throws AzDException Default API exception handler.
*/
@Override
public InputStream executeStream() throws AzDException {
- return executeStreamAsync().join();
+ try {
+ return executeStreamAsync().join();
+ } catch (CompletionException e) {
+ var cause = e.getCause();
+ if (cause instanceof AzDException) {
+ throw (AzDException) cause;
+ }
+ throw new AzDException(cause.getMessage());
+ }
}
/**
- * Executes the request and doesn't return any response. Useful for DELETE operations.
- * @return Void.
- * @throws AzDException Default API exception handler.
+ * Executes the request built by ClientRequest.Builder and doesn't return any response. This is mainly used for Api calls
+ * that returns 201 or any operation that doesn't return response.
+ *
+ * @return Future void.
*/
@Override
public Void executePrimitive() throws AzDException {
- var result = client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
- .thenApplyAsync(resp -> handler.handle(resp, reqInfo)).join();
-
- if (!result.isEmpty()) serializer.deserialize(result, Map.class);
- return null;
+ try {
+ return executePrimitiveAsync().join();
+ } catch (CompletionException e) {
+ var cause = e.getCause();
+ if (cause instanceof AzDException) {
+ throw (AzDException) cause;
+ }
+ throw new AzDException(cause.getMessage());
+ }
}
/**
* Return the request information object.
+ *
* @return RequestInformation {@link RequestInformation}
*/
@Override
@@ -182,6 +212,7 @@ public RequestInformation request() {
/**
* Returns the access token credential object.
+ *
* @return AccessTokenCredential {@link AccessTokenCredential}
*/
@Override
diff --git a/azd/src/main/java/org/azd/abstractions/internals/LocationService.java b/azd/src/main/java/org/azd/abstractions/internals/LocationService.java
index dfeb8d52..3b4b73aa 100644
--- a/azd/src/main/java/org/azd/abstractions/internals/LocationService.java
+++ b/azd/src/main/java/org/azd/abstractions/internals/LocationService.java
@@ -4,7 +4,6 @@
import org.azd.common.Constants;
import org.azd.common.types.ApiLocation;
import org.azd.common.types.ApiLocations;
-import org.azd.exceptions.AzDException;
import org.azd.http.ClientRequest;
import org.azd.utils.UrlBuilder;
@@ -16,12 +15,12 @@
* Determines the Api location based on location url, area and resource id.
*/
public final class LocationService {
- private static volatile LocationService instance;
private final Map> locations = new HashMap<>();
private final AccessTokenCredential accessTokenCredential;
/**
* Default
+ *
* @param accessTokenCredential Access token credential object.
*/
private LocationService(AccessTokenCredential accessTokenCredential) {
@@ -30,26 +29,21 @@ private LocationService(AccessTokenCredential accessTokenCredential) {
/**
* Get the instance of location service.
+ *
* @param accessTokenCredential Access token credential object.
* @return LocationService object {@link LocationService}.
*/
public static LocationService getInstance(AccessTokenCredential accessTokenCredential) {
Objects.requireNonNull(accessTokenCredential, "Access token cannot be null.");
- if (instance == null) {
- synchronized (LocationService.class) {
- if (instance == null) {
- instance = new LocationService(accessTokenCredential);
- }
- }
- }
- return instance;
+ return new LocationService(accessTokenCredential);
}
/**
* Get the location details for given url, area and location id.
+ *
* @param locationUrl Base url of the location. For e.g, https://dev.azure.com/{organisation}
- * @param area Specify the area i.e., release, git etc.
- * @param locationId GUID of the location.
+ * @param area Specify the area i.e., release, git etc.
+ * @param locationId GUID of the location.
* @return Api location object {@link ApiLocation}.
*/
public ApiLocation getLocation(String locationUrl, String area, String locationId) {
@@ -59,35 +53,31 @@ public ApiLocation getLocation(String locationUrl, String area, String locationI
/**
* Retrieves the location details for given area and base url. This is then cached for later use.
+ *
* @param locationUrl Base url of the location. For e.g, https://dev.azure.com/{organisation}
- * @param area Specify the area i.e., release, git etc.
+ * @param area Specify the area i.e., release, git etc.
*/
private void getLocations(String locationUrl, String area) {
Objects.requireNonNull(locationUrl);
Objects.requireNonNull(area);
if (locations.get(area) == null) {
- try {
- var reqUrl = UrlBuilder
- .fromBaseUrl(locationUrl)
- .appendPath(Constants.APIS_RELATIVE_PATH)
- .appendPath(area)
- .build();
+ var reqUrl = UrlBuilder
+ .fromBaseUrl(locationUrl)
+ .appendPath(Constants.APIS_RELATIVE_PATH)
+ .appendPath(area)
+ .build();
- ClientRequest.builder(accessTokenCredential)
- .URI(reqUrl)
- .OPTIONS()
- .build()
- .executeAsync(ApiLocations.class)
- .thenAcceptAsync(results -> {
- var resourceAreas = new HashMap();
- results.locations.forEach(result -> resourceAreas.put(result.id.toLowerCase(), result));
- locations.put(area, resourceAreas);
- })
- .join();
- } catch (AzDException e) {
- throw new RuntimeException("An error occurred, couldn't find locations for given area " + "'"
- + area + "'. Error message: " + e.getMessage());
- }
+ ClientRequest.builder(accessTokenCredential)
+ .URI(reqUrl)
+ .OPTIONS()
+ .build()
+ .executeAsync(ApiLocations.class)
+ .thenAcceptAsync(results -> {
+ var resourceAreas = new HashMap();
+ results.locations.forEach(result -> resourceAreas.put(result.id.toLowerCase(), result));
+ locations.put(area, resourceAreas);
+ })
+ .join();
}
locations.get(area);
}
diff --git a/azd/src/main/java/org/azd/abstractions/internals/LookUpService.java b/azd/src/main/java/org/azd/abstractions/internals/LookUpService.java
index 4d1d31fd..681b1dd5 100644
--- a/azd/src/main/java/org/azd/abstractions/internals/LookUpService.java
+++ b/azd/src/main/java/org/azd/abstractions/internals/LookUpService.java
@@ -1,13 +1,12 @@
package org.azd.abstractions.internals;
import org.azd.authentication.AccessTokenCredential;
-import org.azd.common.types.LocationUrl;
import org.azd.common.types.ResourceAreas;
import org.azd.exceptions.AzDException;
import org.azd.http.ClientRequest;
+import org.azd.utils.StringUtils;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.Locale;
import java.util.Objects;
/**
@@ -19,8 +18,6 @@ public class LookUpService {
*/
private final static String id = "e81700f7-3be2-46de-8624-2eb35882fcaa";
private final static String area = "location";
- private static final Map resourceAreasCache = new HashMap<>();
- private static volatile LookUpService instance;
private final AccessTokenCredential accessTokenCredential;
private LookUpService(AccessTokenCredential accessTokenCredential) {
@@ -29,55 +26,52 @@ private LookUpService(AccessTokenCredential accessTokenCredential) {
/**
* Get the instance of lookup service.
+ *
* @param accessTokenCredential Access token credential object.
* @return Lookup service object {@link LookUpService}.
*/
public static LookUpService getInstance(AccessTokenCredential accessTokenCredential) {
Objects.requireNonNull(accessTokenCredential);
- if (instance == null) {
- synchronized (LookUpService.class) {
- if (instance == null) {
- instance = new LookUpService(accessTokenCredential);
- }
- }
- }
- return instance;
+ return new LookUpService(accessTokenCredential);
}
/**
* Get the resource areas for given url.
+ *
* @param organizationUrl Organisation url. E.g., https://dev.azure.com/{organisation}
* @return Resource areas object {@link ResourceAreas}.
*/
public ResourceAreas resourceAreas(String organizationUrl) {
- try {
- return ClientRequest.builder(accessTokenCredential)
- .baseInstance(organizationUrl)
- .area(area)
- .location(id)
- .build()
- .executeAsync(ResourceAreas.class)
- .thenApplyAsync(results -> {
- results.getResourceAreas().forEach(result ->
- resourceAreasCache.put(result.getId().toLowerCase(), result));
- return results;
- })
- .join();
- } catch (AzDException e) {
- throw new RuntimeException(e);
- }
+ return ClientRequest.builder(accessTokenCredential)
+ .baseInstance(organizationUrl)
+ .area(area)
+ .location(id)
+ .build()
+ .executeAsync(ResourceAreas.class)
+ .join();
}
/**
* Get the location url for given base url and resource id.
+ *
* @param organizationUrl Organisation url. E.g., https://dev.azure.com/{organisation}
- * @param resourceId GUID of the resource such as release, git etc.
+ * @param resourceId GUID of the resource such as release, git etc.
* @return Location url.
*/
- public String locationUrl(String organizationUrl, String resourceId) {
+ public String locationUrl(String organizationUrl, String resourceId) throws AzDException {
if (resourceId == null) return organizationUrl;
- if (!resourceAreasCache.containsKey(resourceId)) resourceAreas(organizationUrl);
- var locationUrl = resourceAreasCache.get(resourceId);
- return locationUrl == null ? organizationUrl : locationUrl.getLocationUrl();
+ var resAreas = resourceAreas(organizationUrl);
+
+ if (resAreas == null ||
+ resAreas.getResourceAreas().size() == 0 ||
+ StringUtils.isEmpty((String) resAreas.getResponse().getResponseBody()))
+ return organizationUrl;
+
+ for (var resArea : resAreas.getResourceAreas())
+ if (resArea.getId().toLowerCase(Locale.ROOT)
+ .equals(resourceId.toLowerCase(Locale.ROOT)))
+ return resArea.getLocationUrl();
+
+ throw new AzDException("Couldn't find information for resource " + resourceId + "from " + organizationUrl);
}
}
diff --git a/azd/src/main/java/org/azd/abstractions/pipelines/ResponsePipeline.java b/azd/src/main/java/org/azd/abstractions/pipelines/ResponsePipeline.java
new file mode 100644
index 00000000..2f89f593
--- /dev/null
+++ b/azd/src/main/java/org/azd/abstractions/pipelines/ResponsePipeline.java
@@ -0,0 +1,21 @@
+package org.azd.abstractions.pipelines;
+
+import org.azd.abstractions.ResponseHandler;
+import org.azd.abstractions.handlers.ResponseContext;
+
+import java.util.Objects;
+import java.util.concurrent.CompletableFuture;
+
+public final class ResponsePipeline {
+ private final ResponseHandler handler;
+
+ public ResponsePipeline(ResponseHandler handler) {
+ Objects.requireNonNull(handler, "Response pipeline should have at least one handler.");
+ this.handler = handler;
+ }
+
+ public CompletableFuture processAsync(ResponseContext context) {
+ return handler.handleAsync(context)
+ .thenApply(v -> (T) context.body());
+ }
+}
diff --git a/azd/src/main/java/org/azd/abstractions/pipelines/ResponsePipelineBuilder.java b/azd/src/main/java/org/azd/abstractions/pipelines/ResponsePipelineBuilder.java
new file mode 100644
index 00000000..9c8f5cf6
--- /dev/null
+++ b/azd/src/main/java/org/azd/abstractions/pipelines/ResponsePipelineBuilder.java
@@ -0,0 +1,33 @@
+package org.azd.abstractions.pipelines;
+
+import org.azd.abstractions.ResponseHandler;
+import org.azd.abstractions.handlers.ResponseHandlerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public final class ResponsePipelineBuilder {
+ private final List handlerFactories = new ArrayList<>();
+
+ private ResponsePipelineBuilder() { }
+
+ public static ResponsePipelineBuilder create() {
+ return new ResponsePipelineBuilder();
+ }
+ public ResponsePipelineBuilder add(ResponseHandlerFactory factory) {
+ handlerFactories.add(factory);
+ return this;
+ }
+
+ public ResponsePipeline build() {
+ ResponseHandler next = null;
+
+ for (int i = handlerFactories.size() - 1; i >= 0; i--) {
+ ResponseHandler current = handlerFactories.get(i).create();
+ current.setNext(next);
+ next = current;
+ }
+
+ return new ResponsePipeline(next);
+ }
+}
diff --git a/azd/src/main/java/org/azd/abstractions/serializer/JsonSerializer.java b/azd/src/main/java/org/azd/abstractions/serializer/JsonSerializer.java
index 2a2f2d66..6e7a5a5b 100644
--- a/azd/src/main/java/org/azd/abstractions/serializer/JsonSerializer.java
+++ b/azd/src/main/java/org/azd/abstractions/serializer/JsonSerializer.java
@@ -6,7 +6,6 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.azd.enums.ApiExceptionTypes;
-import org.azd.exceptions.ApiException;
import org.azd.exceptions.AzDException;
import org.azd.helpers.StreamHelper;
@@ -66,13 +65,6 @@ public JsonNode serialize(String jsonString) throws AzDException {
@Override
public T deserialize(final String content, Class valueType) throws AzDException {
try {
- if (content.contains("innerException"))
- throw new AzDException(this.readValue(content, ApiException.class).getTypeKey(), this.readValue(content, ApiException.class).getMessage());
- if (content.contains("The request is invalid."))
- throw new AzDException();
- if (content.contains("Object moved"))
- throw new AzDException(ApiExceptionTypes.InvalidPersonalAccessTokenException.toString(),
- "Personal access token passed is invalid; Pass the valid token and try again.");
return this.readValue(content, valueType);
} catch (JsonProcessingException e) {
throw new AzDException(ApiExceptionTypes.ApiResponseParsingException.toString(), e.getMessage());
@@ -91,12 +83,6 @@ public T deserialize(final String content, Class valueType) throws AzDExc
@Override
public T deserialize(final String content, TypeReference valueType) throws AzDException {
try {
- if (content.contains("innerException"))
- throw new AzDException(this.readValue(content, ApiException.class).getTypeKey(), this.readValue(content, ApiException.class).getMessage());
- if (content.contains("The request is invalid."))
- throw new AzDException();
- if (content.contains("Object moved"))
- throw new AzDException(ApiExceptionTypes.InvalidPersonalAccessTokenException.toString(), "Personal access token passed is invalid; Pass the valid token and try again.");
return this.readValue(content, valueType);
} catch (JsonProcessingException e) {
throw new AzDException(ApiExceptionTypes.ApiResponseParsingException.toString(), e.getMessage());
@@ -121,6 +107,22 @@ public T deserialize(InputStream content, Class valueType) throws AzDExce
}
}
+ /**
+ * Deserializes the json string to object of given type.
+ *
+ * @param content input stream response from API
+ * @return Object
+ * @throws AzDException Default exception handler.
+ */
+ @Override
+ public Object deserialize(String content) throws AzDException {
+ try {
+ return readTree(content);
+ } catch (Exception e) {
+ throw new AzDException(ApiExceptionTypes.StringValueParsingException.name(), e.getMessage());
+ }
+ }
+
/**
* Deserializes the json string to given object from a file.
*
diff --git a/azd/src/main/java/org/azd/abstractions/serializer/SerializableCollectionEntity.java b/azd/src/main/java/org/azd/abstractions/serializer/SerializableCollectionEntity.java
index b437daf9..d83e4e79 100644
--- a/azd/src/main/java/org/azd/abstractions/serializer/SerializableCollectionEntity.java
+++ b/azd/src/main/java/org/azd/abstractions/serializer/SerializableCollectionEntity.java
@@ -1,15 +1,10 @@
package org.azd.abstractions.serializer;
import com.fasterxml.jackson.annotation.JsonIgnore;
-import org.azd.authentication.AccessTokenCredential;
-import org.azd.exceptions.AzDException;
-import org.azd.http.ClientRequest;
import java.net.URI;
import java.net.URISyntaxException;
-import static org.azd.helpers.Utils.isNullOrEmpty;
-
/**
* Collection entity that provides additional functionalities such as next page, continuation token.
*/
diff --git a/azd/src/main/java/org/azd/abstractions/serializer/SerializerContext.java b/azd/src/main/java/org/azd/abstractions/serializer/SerializerContext.java
index 78f428c0..aea5a222 100644
--- a/azd/src/main/java/org/azd/abstractions/serializer/SerializerContext.java
+++ b/azd/src/main/java/org/azd/abstractions/serializer/SerializerContext.java
@@ -57,6 +57,15 @@ public interface SerializerContext {
*/
T deserialize(InputStream content, Class valueType) throws AzDException;
+ /**
+ * Deserializes the json string to object of given type.
+ *
+ * @param content input stream response from API
+ * @return Object
+ * @throws AzDException Default exception handler.
+ */
+ Object deserialize(String content) throws AzDException;
+
/**
* Deserialize JSON string to a specified type.
* @param src File that contains JSON string.
diff --git a/azd/src/main/java/org/azd/accounts/AccountsApi.java b/azd/src/main/java/org/azd/accounts/AccountsApi.java
deleted file mode 100644
index ff40e0a6..00000000
--- a/azd/src/main/java/org/azd/accounts/AccountsApi.java
+++ /dev/null
@@ -1,112 +0,0 @@
-package org.azd.accounts;
-
-import org.azd.accounts.types.Accounts;
-import org.azd.accounts.types.Organizations;
-import org.azd.accounts.types.Profile;
-import org.azd.common.ApiVersion;
-import org.azd.connection.Connection;
-import org.azd.enums.CustomHeader;
-import org.azd.enums.RequestMethod;
-import org.azd.exceptions.AzDException;
-import org.azd.helpers.JsonMapper;
-import org.azd.interfaces.AccountsDetails;
-import org.azd.utils.AzDAsyncApi;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-import static org.azd.utils.RestClient.send;
-
-/**
- * Accounts class to manage Accounts Api
- */
-public class AccountsApi extends AzDAsyncApi implements AccountsDetails {
- /**
- * Connection object
- */
- private final Connection CONNECTION;
- private final JsonMapper MAPPER = new JsonMapper();
- private final String AREA = "accounts";
-
- /**
- * Pass the connection object to work with Accounts Api
- *
- * @param connection Connection object
- */
- public AccountsApi(Connection connection) {
- this.CONNECTION = connection;
- }
-
- /**
- * Get a list of accounts for a specific member.
- *
- * @param memberId Specify the member Id. This can be obtained by running getUserEntitlements() from MemberEntitlementManagementApi.
- * @return Accounts object {@link Accounts}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Accounts getAccounts(String memberId) throws AzDException {
- var q = new HashMap() {{
- put("memberId", memberId);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, AREA, null, AREA, null,
- null, ApiVersion.ACCOUNTS, q, null, null);
-
- return MAPPER.mapJsonResponse(r, Accounts.class);
- }
-
- /**
- * Get the list of organizations that you have access to. Note that while creating and granting access to the personal
- * access token select all organizations to apply the access on all available organizations.
- *
- * @return A list of Organization. {@link Organizations}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Organizations getOrganizations() throws AzDException {
- var ids = new ArrayList<>();
- ids.add("ms.vss-features.my-organizations-data-provider");
-
- var b = new HashMap() {{
- put("contributionIds", ids);
- put("dataProviderContext", new HashMap() {{
- put("properties", "{}");
- }});
- }};
-
- String r = send(RequestMethod.POST, CONNECTION, null, null, "Contribution", null,
- "HierarchyQuery", ApiVersion.ACCOUNTS, null, b, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, Organizations.class);
- }
-
- /**
- * Gets the logged in user profile.
- *
- * @return a profile object. {@link Profile}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Profile getProfile() throws AzDException {
- String r = send(RequestMethod.GET, CONNECTION, AREA, null,
- "/profile/profiles", "me", null, ApiVersion.PROFILE, null, null, null);
-
- return MAPPER.mapJsonResponse(r, Profile.class);
- }
-
- /**
- * Gets a user profile.
- *
- * @param id pass the user id
- * @return a profile object. {@link Profile}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Profile getProfile(String id) throws AzDException {
- String r = send(RequestMethod.GET, CONNECTION, AREA, null,
- "/profile/profiles", id, null, ApiVersion.PROFILE, null, null, null);
-
- return MAPPER.mapJsonResponse(r, Profile.class);
- }
-}
\ No newline at end of file
diff --git a/azd/src/main/java/org/azd/artifacts/feedmanagement/FeedManagementRequestBuilder.java b/azd/src/main/java/org/azd/artifacts/feedmanagement/FeedManagementRequestBuilder.java
index c4ccd33a..7a6c96fd 100644
--- a/azd/src/main/java/org/azd/artifacts/feedmanagement/FeedManagementRequestBuilder.java
+++ b/azd/src/main/java/org/azd/artifacts/feedmanagement/FeedManagementRequestBuilder.java
@@ -2,12 +2,12 @@
import org.azd.abstractions.BaseRequestBuilder;
import org.azd.abstractions.QueryParameter;
+import org.azd.artifacts.types.Feed;
+import org.azd.artifacts.types.Feeds;
import org.azd.authentication.AccessTokenCredential;
import org.azd.common.ApiVersion;
import org.azd.enums.FeedRole;
import org.azd.exceptions.AzDException;
-import org.azd.feedmanagement.types.Feed;
-import org.azd.feedmanagement.types.Feeds;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
diff --git a/azd/src/main/java/org/azd/artifacts/feedmanagement/FeedPermissionsRequestBuilder.java b/azd/src/main/java/org/azd/artifacts/feedmanagement/FeedPermissionsRequestBuilder.java
index ea509af6..9f322edd 100644
--- a/azd/src/main/java/org/azd/artifacts/feedmanagement/FeedPermissionsRequestBuilder.java
+++ b/azd/src/main/java/org/azd/artifacts/feedmanagement/FeedPermissionsRequestBuilder.java
@@ -2,10 +2,10 @@
import org.azd.abstractions.BaseRequestBuilder;
import org.azd.abstractions.QueryParameter;
+import org.azd.artifacts.types.FeedPermissions;
import org.azd.authentication.AccessTokenCredential;
import org.azd.common.ApiVersion;
import org.azd.exceptions.AzDException;
-import org.azd.feedmanagement.types.FeedPermissions;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
diff --git a/azd/src/main/java/org/azd/artifacts/feedmanagement/FeedViewRequestBuilder.java b/azd/src/main/java/org/azd/artifacts/feedmanagement/FeedViewRequestBuilder.java
index 1ae84cc6..9ff7aa07 100644
--- a/azd/src/main/java/org/azd/artifacts/feedmanagement/FeedViewRequestBuilder.java
+++ b/azd/src/main/java/org/azd/artifacts/feedmanagement/FeedViewRequestBuilder.java
@@ -1,11 +1,11 @@
package org.azd.artifacts.feedmanagement;
import org.azd.abstractions.BaseRequestBuilder;
+import org.azd.artifacts.types.FeedView;
+import org.azd.artifacts.types.FeedViews;
import org.azd.authentication.AccessTokenCredential;
import org.azd.common.ApiVersion;
import org.azd.exceptions.AzDException;
-import org.azd.feedmanagement.types.FeedView;
-import org.azd.feedmanagement.types.FeedViews;
import java.util.concurrent.CompletableFuture;
diff --git a/azd/src/main/java/org/azd/feedmanagement/types/Feed.java b/azd/src/main/java/org/azd/artifacts/types/Feed.java
similarity index 99%
rename from azd/src/main/java/org/azd/feedmanagement/types/Feed.java
rename to azd/src/main/java/org/azd/artifacts/types/Feed.java
index a53c8cd3..c85939a9 100644
--- a/azd/src/main/java/org/azd/feedmanagement/types/Feed.java
+++ b/azd/src/main/java/org/azd/artifacts/types/Feed.java
@@ -1,4 +1,4 @@
-package org.azd.feedmanagement.types;
+package org.azd.artifacts.types;
/**
* ----------------------------------------------------------
* GENERATED FILE, should be edited to suit the purpose.
diff --git a/azd/src/main/java/org/azd/feedmanagement/types/FeedPermission.java b/azd/src/main/java/org/azd/artifacts/types/FeedPermission.java
similarity index 98%
rename from azd/src/main/java/org/azd/feedmanagement/types/FeedPermission.java
rename to azd/src/main/java/org/azd/artifacts/types/FeedPermission.java
index 6c56bcbf..1be8ae05 100644
--- a/azd/src/main/java/org/azd/feedmanagement/types/FeedPermission.java
+++ b/azd/src/main/java/org/azd/artifacts/types/FeedPermission.java
@@ -1,4 +1,4 @@
-package org.azd.feedmanagement.types;
+package org.azd.artifacts.types;
/**
* ----------------------------------------------------------
* GENERATED FILE, should be edited to suit the purpose.
diff --git a/azd/src/main/java/org/azd/feedmanagement/types/FeedPermissions.java b/azd/src/main/java/org/azd/artifacts/types/FeedPermissions.java
similarity index 94%
rename from azd/src/main/java/org/azd/feedmanagement/types/FeedPermissions.java
rename to azd/src/main/java/org/azd/artifacts/types/FeedPermissions.java
index 682aafec..f4f80ccc 100644
--- a/azd/src/main/java/org/azd/feedmanagement/types/FeedPermissions.java
+++ b/azd/src/main/java/org/azd/artifacts/types/FeedPermissions.java
@@ -1,4 +1,4 @@
-package org.azd.feedmanagement.types;
+package org.azd.artifacts.types;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/azd/src/main/java/org/azd/feedmanagement/types/FeedView.java b/azd/src/main/java/org/azd/artifacts/types/FeedView.java
similarity index 98%
rename from azd/src/main/java/org/azd/feedmanagement/types/FeedView.java
rename to azd/src/main/java/org/azd/artifacts/types/FeedView.java
index 2cbcf818..b0a3a440 100644
--- a/azd/src/main/java/org/azd/feedmanagement/types/FeedView.java
+++ b/azd/src/main/java/org/azd/artifacts/types/FeedView.java
@@ -1,4 +1,4 @@
-package org.azd.feedmanagement.types;
+package org.azd.artifacts.types;
/**
* ----------------------------------------------------------
* GENERATED FILE, should be edited to suit the purpose.
diff --git a/azd/src/main/java/org/azd/feedmanagement/types/FeedViews.java b/azd/src/main/java/org/azd/artifacts/types/FeedViews.java
similarity index 94%
rename from azd/src/main/java/org/azd/feedmanagement/types/FeedViews.java
rename to azd/src/main/java/org/azd/artifacts/types/FeedViews.java
index 321fe8f9..5f1a1839 100644
--- a/azd/src/main/java/org/azd/feedmanagement/types/FeedViews.java
+++ b/azd/src/main/java/org/azd/artifacts/types/FeedViews.java
@@ -1,4 +1,4 @@
-package org.azd.feedmanagement.types;
+package org.azd.artifacts.types;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/azd/src/main/java/org/azd/feedmanagement/types/Feeds.java b/azd/src/main/java/org/azd/artifacts/types/Feeds.java
similarity index 93%
rename from azd/src/main/java/org/azd/feedmanagement/types/Feeds.java
rename to azd/src/main/java/org/azd/artifacts/types/Feeds.java
index 80c3b607..803aa732 100644
--- a/azd/src/main/java/org/azd/feedmanagement/types/Feeds.java
+++ b/azd/src/main/java/org/azd/artifacts/types/Feeds.java
@@ -1,4 +1,4 @@
-package org.azd.feedmanagement.types;
+package org.azd.artifacts.types;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/azd/src/main/java/org/azd/feedmanagement/types/ProjectReference.java b/azd/src/main/java/org/azd/artifacts/types/ProjectReference.java
similarity index 97%
rename from azd/src/main/java/org/azd/feedmanagement/types/ProjectReference.java
rename to azd/src/main/java/org/azd/artifacts/types/ProjectReference.java
index 037aa268..b92e69bf 100644
--- a/azd/src/main/java/org/azd/feedmanagement/types/ProjectReference.java
+++ b/azd/src/main/java/org/azd/artifacts/types/ProjectReference.java
@@ -1,4 +1,4 @@
-package org.azd.feedmanagement.types;
+package org.azd.artifacts.types;
/**
* ----------------------------------------------------------
* GENERATED FILE, should be edited to suit the purpose.
diff --git a/azd/src/main/java/org/azd/feedmanagement/types/UpstreamSource.java b/azd/src/main/java/org/azd/artifacts/types/UpstreamSource.java
similarity index 99%
rename from azd/src/main/java/org/azd/feedmanagement/types/UpstreamSource.java
rename to azd/src/main/java/org/azd/artifacts/types/UpstreamSource.java
index f1da96ac..7b2c17da 100644
--- a/azd/src/main/java/org/azd/feedmanagement/types/UpstreamSource.java
+++ b/azd/src/main/java/org/azd/artifacts/types/UpstreamSource.java
@@ -1,4 +1,4 @@
-package org.azd.feedmanagement.types;
+package org.azd.artifacts.types;
/**
* ----------------------------------------------------------
* GENERATED FILE, should be edited to suit the purpose.
diff --git a/azd/src/main/java/org/azd/feedmanagement/types/UpstreamStatusDetail.java b/azd/src/main/java/org/azd/artifacts/types/UpstreamStatusDetail.java
similarity index 95%
rename from azd/src/main/java/org/azd/feedmanagement/types/UpstreamStatusDetail.java
rename to azd/src/main/java/org/azd/artifacts/types/UpstreamStatusDetail.java
index a5e4d968..dbf62088 100644
--- a/azd/src/main/java/org/azd/feedmanagement/types/UpstreamStatusDetail.java
+++ b/azd/src/main/java/org/azd/artifacts/types/UpstreamStatusDetail.java
@@ -1,4 +1,4 @@
-package org.azd.feedmanagement.types;
+package org.azd.artifacts.types;
/**
* ----------------------------------------------------------
* GENERATED FILE, should be edited to suit the purpose.
diff --git a/azd/src/main/java/org/azd/artifactspackagetypes/maven/MavenRequestBuilder.java b/azd/src/main/java/org/azd/artifactspackagetypes/maven/MavenRequestBuilder.java
index 14eb8e64..8e312a1c 100644
--- a/azd/src/main/java/org/azd/artifactspackagetypes/maven/MavenRequestBuilder.java
+++ b/azd/src/main/java/org/azd/artifactspackagetypes/maven/MavenRequestBuilder.java
@@ -1,21 +1,17 @@
package org.azd.artifactspackagetypes.maven;
import org.azd.abstractions.BaseRequestBuilder;
-import org.azd.abstractions.ResponseHandler;
import org.azd.artifactspackagetypes.ArtifactsPackageTypesRequestBuilder;
import org.azd.artifactspackagetypes.types.MavenPackagesBatchRequest;
+import org.azd.artifactspackagetypes.types.Package;
import org.azd.artifactspackagetypes.types.PackageVersionDetails;
import org.azd.authentication.AccessTokenCredential;
import org.azd.common.ApiVersion;
import org.azd.enums.CustomHeader;
-import org.azd.enums.HttpStatusCode;
import org.azd.exceptions.AzDException;
import org.azd.helpers.StreamHelper;
-import org.azd.http.ClientRequest;
-import org.azd.maven.types.Package;
import java.io.InputStream;
-import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
@@ -75,37 +71,7 @@ public CompletableFuture downloadAsync(Consumer {
- try {
- var res = ResponseHandler.getResponse();
- var statusCode = res.getStatusCode();
- var headers = res.getResponseHeaders().firstValue("Content-Type");
-
- if (headers.isPresent()) {
- // Error scenarios.
- if (headers.get().equals(CustomHeader.JSON_CONTENT_TYPE_UTF_8.getValue()) && statusCode != HttpStatusCode.OK)
- serializer.deserialize(StreamHelper.convertToString(x), Map.class);
-
- // Obviously VSTS server doesn't return callback URL.
- if (headers.get().equals(CustomHeader.STREAM.getValue()) && statusCode == HttpStatusCode.OK)
- return x;
-
- // Azure DevOps Services successful redirection
- return ClientRequest.builder()
- .URI(res.getRequestUrl())
- .header(CustomHeader.STREAM)
- .build()
- .executeStreamAsync()
- .join();
- }
-
- throw new AzDException("An error occurred while trying to download artifact. " + StreamHelper.convertToString(x));
-
- } catch (AzDException e) {
- throw new RuntimeException(e);
- }
- });
+ .executeStreamAsync();
}
/**
@@ -238,39 +204,15 @@ public InputStream download(Consumer pathParameters) throws
final var values = new MavenPathParameters();
pathParameters.accept(values);
- var stream = builder()
+ return builder()
.location("c338d4b5-d30a-47e2-95b7-f157ef558833")
.serviceEndpoint("artifactId", Objects.requireNonNull(values.artifactId, "Artifact ID cannot be null."))
.serviceEndpoint("feedId", Objects.requireNonNull(values.feedId, "Feed ID cannot be null."))
.serviceEndpoint("groupId", Objects.requireNonNull(values.groupId, "Group ID cannot be null."))
.serviceEndpoint("version", Objects.requireNonNull(values.version, "Version of the artifact is mandatory."))
.serviceEndpoint("fileName", Objects.requireNonNull(values.fileName, "File name cannot be null."))
- .header(CustomHeader.STREAM)
.build()
.executeStream();
-
- var res = ResponseHandler.getResponse();
- var statusCode = res.getStatusCode();
- var headers = res.getResponseHeaders().firstValue("Content-Type");
-
- if (headers.isPresent()) {
- // Error scenarios.
- if (headers.get().equals(CustomHeader.JSON_CONTENT_TYPE_UTF_8.getValue()) && statusCode != HttpStatusCode.OK)
- serializer.deserialize(StreamHelper.convertToString(stream), Map.class);
-
- // VSTS server doesn't return callback URL.
- if (headers.get().equals(CustomHeader.STREAM.getValue()) && statusCode == HttpStatusCode.OK)
- return stream;
-
- // Azure DevOps Services successful redirection
- return ClientRequest.builder()
- .URI(res.getRequestUrl())
- .header(CustomHeader.STREAM)
- .build()
- .executeStream();
- }
-
- throw new AzDException("An error occurred while trying to download artifact. " + StreamHelper.convertToString(stream));
}
/**
diff --git a/azd/src/main/java/org/azd/artifactspackagetypes/maven/PackageFromRecycleBinRequestBuilder.java b/azd/src/main/java/org/azd/artifactspackagetypes/maven/PackageFromRecycleBinRequestBuilder.java
index 8ee77f71..c14d3a45 100644
--- a/azd/src/main/java/org/azd/artifactspackagetypes/maven/PackageFromRecycleBinRequestBuilder.java
+++ b/azd/src/main/java/org/azd/artifactspackagetypes/maven/PackageFromRecycleBinRequestBuilder.java
@@ -1,12 +1,12 @@
package org.azd.artifactspackagetypes.maven;
import org.azd.abstractions.BaseRequestBuilder;
+import org.azd.artifactspackagetypes.types.MavenPackageVersionDeletionState;
import org.azd.artifactspackagetypes.types.MavenPackagesBatchRequest;
import org.azd.artifactspackagetypes.types.MavenRecycleBinPackageVersionDetails;
import org.azd.authentication.AccessTokenCredential;
import org.azd.common.ApiVersion;
import org.azd.exceptions.AzDException;
-import org.azd.maven.types.MavenPackageVersionDeletionState;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
diff --git a/azd/src/main/java/org/azd/artifactspackagetypes/maven/UpstreamingBehaviorRequestBuilder.java b/azd/src/main/java/org/azd/artifactspackagetypes/maven/UpstreamingBehaviorRequestBuilder.java
index befc97e4..6ec4626f 100644
--- a/azd/src/main/java/org/azd/artifactspackagetypes/maven/UpstreamingBehaviorRequestBuilder.java
+++ b/azd/src/main/java/org/azd/artifactspackagetypes/maven/UpstreamingBehaviorRequestBuilder.java
@@ -1,10 +1,10 @@
package org.azd.artifactspackagetypes.maven;
import org.azd.abstractions.BaseRequestBuilder;
+import org.azd.artifactspackagetypes.types.UpstreamingBehavior;
import org.azd.authentication.AccessTokenCredential;
import org.azd.common.ApiVersion;
import org.azd.exceptions.AzDException;
-import org.azd.maven.types.UpstreamingBehavior;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
diff --git a/azd/src/main/java/org/azd/maven/types/MavenPackageVersionDeletionState.java b/azd/src/main/java/org/azd/artifactspackagetypes/types/MavenPackageVersionDeletionState.java
similarity index 96%
rename from azd/src/main/java/org/azd/maven/types/MavenPackageVersionDeletionState.java
rename to azd/src/main/java/org/azd/artifactspackagetypes/types/MavenPackageVersionDeletionState.java
index 57b6f7a7..fe050f10 100644
--- a/azd/src/main/java/org/azd/maven/types/MavenPackageVersionDeletionState.java
+++ b/azd/src/main/java/org/azd/artifactspackagetypes/types/MavenPackageVersionDeletionState.java
@@ -1,4 +1,4 @@
-package org.azd.maven.types;
+package org.azd.artifactspackagetypes.types;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/azd/src/main/java/org/azd/upack/types/Package.java b/azd/src/main/java/org/azd/artifactspackagetypes/types/Package.java
similarity index 97%
rename from azd/src/main/java/org/azd/upack/types/Package.java
rename to azd/src/main/java/org/azd/artifactspackagetypes/types/Package.java
index 39a4d2b7..6283a92d 100644
--- a/azd/src/main/java/org/azd/upack/types/Package.java
+++ b/azd/src/main/java/org/azd/artifactspackagetypes/types/Package.java
@@ -1,4 +1,4 @@
-package org.azd.upack.types;
+package org.azd.artifactspackagetypes.types;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/azd/src/main/java/org/azd/maven/types/PackagingSourceType.java b/azd/src/main/java/org/azd/artifactspackagetypes/types/PackagingSourceType.java
similarity index 95%
rename from azd/src/main/java/org/azd/maven/types/PackagingSourceType.java
rename to azd/src/main/java/org/azd/artifactspackagetypes/types/PackagingSourceType.java
index 87af81bd..fdf3d5cf 100644
--- a/azd/src/main/java/org/azd/maven/types/PackagingSourceType.java
+++ b/azd/src/main/java/org/azd/artifactspackagetypes/types/PackagingSourceType.java
@@ -1,4 +1,4 @@
-package org.azd.maven.types;
+package org.azd.artifactspackagetypes.types;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/azd/src/main/java/org/azd/maven/types/ReferenceLinks.java b/azd/src/main/java/org/azd/artifactspackagetypes/types/ReferenceLinks.java
similarity index 92%
rename from azd/src/main/java/org/azd/maven/types/ReferenceLinks.java
rename to azd/src/main/java/org/azd/artifactspackagetypes/types/ReferenceLinks.java
index 1d364967..c10683e5 100644
--- a/azd/src/main/java/org/azd/maven/types/ReferenceLinks.java
+++ b/azd/src/main/java/org/azd/artifactspackagetypes/types/ReferenceLinks.java
@@ -1,4 +1,4 @@
-package org.azd.maven.types;
+package org.azd.artifactspackagetypes.types;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/azd/src/main/java/org/azd/upack/types/UPackPackageVersionDeletionState.java b/azd/src/main/java/org/azd/artifactspackagetypes/types/UPackPackageVersionDeletionState.java
similarity index 96%
rename from azd/src/main/java/org/azd/upack/types/UPackPackageVersionDeletionState.java
rename to azd/src/main/java/org/azd/artifactspackagetypes/types/UPackPackageVersionDeletionState.java
index b767c13a..be4e3b4a 100644
--- a/azd/src/main/java/org/azd/upack/types/UPackPackageVersionDeletionState.java
+++ b/azd/src/main/java/org/azd/artifactspackagetypes/types/UPackPackageVersionDeletionState.java
@@ -1,4 +1,4 @@
-package org.azd.upack.types;
+package org.azd.artifactspackagetypes.types;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/azd/src/main/java/org/azd/maven/types/UpstreamSourceInfo.java b/azd/src/main/java/org/azd/artifactspackagetypes/types/UpstreamSourceInfo.java
similarity index 97%
rename from azd/src/main/java/org/azd/maven/types/UpstreamSourceInfo.java
rename to azd/src/main/java/org/azd/artifactspackagetypes/types/UpstreamSourceInfo.java
index c9b241ac..7f5f840a 100644
--- a/azd/src/main/java/org/azd/maven/types/UpstreamSourceInfo.java
+++ b/azd/src/main/java/org/azd/artifactspackagetypes/types/UpstreamSourceInfo.java
@@ -1,4 +1,4 @@
-package org.azd.maven.types;
+package org.azd.artifactspackagetypes.types;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/azd/src/main/java/org/azd/maven/types/UpstreamingBehavior.java b/azd/src/main/java/org/azd/artifactspackagetypes/types/UpstreamingBehavior.java
similarity index 95%
rename from azd/src/main/java/org/azd/maven/types/UpstreamingBehavior.java
rename to azd/src/main/java/org/azd/artifactspackagetypes/types/UpstreamingBehavior.java
index 6a3ead9d..16604aa1 100644
--- a/azd/src/main/java/org/azd/maven/types/UpstreamingBehavior.java
+++ b/azd/src/main/java/org/azd/artifactspackagetypes/types/UpstreamingBehavior.java
@@ -1,4 +1,4 @@
-package org.azd.maven.types;
+package org.azd.artifactspackagetypes.types;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/azd/src/main/java/org/azd/artifactspackagetypes/universal/UniversalPackageFromRecycleBinRequestBuilder.java b/azd/src/main/java/org/azd/artifactspackagetypes/universal/UniversalPackageFromRecycleBinRequestBuilder.java
index 54b656b2..79079073 100644
--- a/azd/src/main/java/org/azd/artifactspackagetypes/universal/UniversalPackageFromRecycleBinRequestBuilder.java
+++ b/azd/src/main/java/org/azd/artifactspackagetypes/universal/UniversalPackageFromRecycleBinRequestBuilder.java
@@ -1,12 +1,12 @@
package org.azd.artifactspackagetypes.universal;
import org.azd.abstractions.BaseRequestBuilder;
+import org.azd.artifactspackagetypes.types.UPackPackageVersionDeletionState;
import org.azd.artifactspackagetypes.types.UPackPackagesBatchRequest;
import org.azd.artifactspackagetypes.types.UPackRecycleBinPackageVersionDetails;
import org.azd.authentication.AccessTokenCredential;
import org.azd.common.ApiVersion;
import org.azd.exceptions.AzDException;
-import org.azd.upack.types.UPackPackageVersionDeletionState;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
diff --git a/azd/src/main/java/org/azd/artifactspackagetypes/universal/UniversalRequestBuilder.java b/azd/src/main/java/org/azd/artifactspackagetypes/universal/UniversalRequestBuilder.java
index 964acb1c..ba523ea2 100644
--- a/azd/src/main/java/org/azd/artifactspackagetypes/universal/UniversalRequestBuilder.java
+++ b/azd/src/main/java/org/azd/artifactspackagetypes/universal/UniversalRequestBuilder.java
@@ -2,13 +2,12 @@
import org.azd.abstractions.BaseRequestBuilder;
import org.azd.artifactspackagetypes.ArtifactsPackageTypesRequestBuilder;
-import org.azd.artifactspackagetypes.maven.PackageFromRecycleBinRequestBuilder;
+import org.azd.artifactspackagetypes.types.Package;
import org.azd.artifactspackagetypes.types.PackageVersionDetails;
import org.azd.artifactspackagetypes.types.UPackPackagesBatchRequest;
import org.azd.authentication.AccessTokenCredential;
import org.azd.common.ApiVersion;
import org.azd.exceptions.AzDException;
-import org.azd.upack.types.Package;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
diff --git a/azd/src/main/java/org/azd/authentication/ServicePrincipalAccessTokenCredential.java b/azd/src/main/java/org/azd/authentication/ServicePrincipalAccessTokenCredential.java
new file mode 100644
index 00000000..114e7968
--- /dev/null
+++ b/azd/src/main/java/org/azd/authentication/ServicePrincipalAccessTokenCredential.java
@@ -0,0 +1,148 @@
+package org.azd.authentication;
+
+import org.azd.abstractions.RequestInformation;
+import org.azd.common.types.AccessToken;
+import org.azd.enums.CustomHeader;
+import org.azd.enums.RequestMethod;
+import org.azd.exceptions.AzDException;
+import org.azd.http.ClientRequest;
+
+import java.net.http.HttpRequest;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Represents service principal access token modal.
+ *
+ * @see SPN authentication
+ */
+public class ServicePrincipalAccessTokenCredential implements AccessTokenCredential{
+ /**
+ * Access token request base URL
+ */
+ private static final String BASEURL = "https://login.microsoftonline.com/";
+ /**
+ * Access token request endpoint v2.0
+ */
+ private static final String TOKEN_ENDPOINT = "/oauth2/v2.0/token";
+ /**
+ * Default resource for requesting access token
+ */
+ private static final String SCOPES = "499b84ac-1321-427f-aa17-267ca6975798/.default";
+ /**
+ * Authentication grant type when using service principal.
+ */
+ private static final String GRANT_TYPE = "&grant_type=client_credentials";
+
+ /**
+ * Azure DevOps organization or TFS collection url.
+ */
+ private String organizationUrl;
+ /**
+ * Project name
+ */
+ private String projectName;
+ /**
+ * Client Id.
+ */
+ private final String clientId;
+ /**
+ * Client Secret.
+ */
+ private final String clientSecret;
+ /**
+ * Tenant Id.
+ */
+ private final String tenantId;
+ /**
+ * Represents the bearer access token
+ */
+ private String accessToken;
+
+ /**
+ * Creates a new Service Principal token credential provider object.
+ *
+ * @param organizationUrl Azure DevOps organization url.
+ * @param clientId Client id of registered app in Entra Id.
+ * @param clientSecret Client secret of registered app in Entra Id.
+ * @param tenantId Tenant id of the registered app in Entra Id.
+ */
+ public ServicePrincipalAccessTokenCredential(String organizationUrl, String tenantId,
+ String clientId, String clientSecret) {
+ this(organizationUrl, null, tenantId, clientId, clientSecret);
+ }
+
+ /**
+ * Creates a new Service Principal token credential provider object.
+ *
+ * @param organizationUrl Azure DevOps organization url.
+ * @param clientId Client id of registered app in Entra Id.
+ * @param clientSecret Client secret of registered app in Entra Id.
+ * @param tenantId Tenant id of the registered app in Entra Id.
+ */
+ public ServicePrincipalAccessTokenCredential(String organizationUrl, String projectName, String tenantId,
+ String clientId, String clientSecret) {
+ this.organizationUrl = organizationUrl;
+ this.projectName = projectName;
+ this.tenantId = tenantId;
+ this.clientId = clientId;
+ this.clientSecret = clientSecret;
+ }
+
+ @Override
+ public String getOrganizationUrl() {
+ return organizationUrl;
+ }
+
+ @Override
+ public void setOrganizationUrl(String organizationUrl) {
+ this.organizationUrl = organizationUrl;
+ }
+
+ @Override
+ public String getProjectName() {
+ return projectName;
+ }
+
+ @Override
+ public void setProjectName(String projectName) {
+ this.projectName = projectName;
+ }
+
+ @Override
+ public String getAccessToken() {
+ authenticate();
+ return accessToken;
+ }
+
+ @Override
+ public void setAccessToken(String accessToken) {
+ this.accessToken = "Bearer " + accessToken;
+ }
+
+ /**
+ * Authenticate with given client id, tenant id & client secret and generates the access token.
+ */
+ private void authenticate() {
+ var body = "client_id=" + this.clientId +
+ "&scope=" + SCOPES +
+ "&client_secret=" + this.clientSecret +
+ GRANT_TYPE;
+
+ try {
+ var reqInfo = new RequestInformation();
+ reqInfo.requestMethod = RequestMethod.POST;
+ reqInfo.setRequestUrl(BASEURL + this.tenantId + TOKEN_ENDPOINT);
+ reqInfo.requestHeaders.add(CustomHeader.URL_ENCODED);
+ reqInfo.body = HttpRequest.BodyPublishers.ofString(body, StandardCharsets.UTF_8);
+
+ var res = ClientRequest.builder()
+ .request(reqInfo)
+ .build()
+ .execute(AccessToken.class);
+
+ setAccessToken(res.Token);
+ } catch (AzDException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/azd/src/main/java/org/azd/build/BuildApi.java b/azd/src/main/java/org/azd/build/BuildApi.java
deleted file mode 100644
index 213e7a31..00000000
--- a/azd/src/main/java/org/azd/build/BuildApi.java
+++ /dev/null
@@ -1,1731 +0,0 @@
-package org.azd.build;
-
-import org.azd.build.types.*;
-import org.azd.common.ApiVersion;
-import org.azd.connection.Connection;
-import org.azd.enums.*;
-import org.azd.exceptions.AzDException;
-import org.azd.helpers.JsonMapper;
-import org.azd.helpers.URLHelper;
-import org.azd.interfaces.BuildDetails;
-import org.azd.utils.AzDAsyncApi;
-
-import java.io.InputStream;
-import java.util.*;
-import java.util.stream.Collectors;
-
-import static org.azd.utils.RestClient.send;
-
-/**
- * Build class to manage build API
- */
-public class BuildApi extends AzDAsyncApi implements BuildDetails {
- /**
- * Connection object
- */
- private final Connection CONNECTION;
- private final JsonMapper MAPPER = new JsonMapper();
- private final String AREA = "build";
- private final String BUILD = "5d6898bb-45ec-463f-95f9-54d49c71752e";
-
- /**
- * Pass the connection object
- *
- * @param connection Connection object
- */
- public BuildApi(Connection connection) {
- this.CONNECTION = connection;
- }
-
- /**
- * Deletes a build.
- *
- * @param buildId pass the build id to delete
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Void deleteBuild(int buildId) throws AzDException {
- try {
- String r = send(RequestMethod.DELETE, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", Integer.toString(buildId), null, ApiVersion.BUILD, null, null, null);
- if (!r.isEmpty()) MAPPER.mapJsonResponse(r, Map.class);
- } catch (AzDException e) {
- throw e;
- }
- return null;
- }
-
- /**
- * Gets a build
- *
- * @param buildId pass the build id
- * @return a build object {@link Build}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Build getBuild(int buildId) throws AzDException {
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", Integer.toString(buildId), null, ApiVersion.BUILD, null, null, null);
-
- return MAPPER.mapJsonResponse(r, Build.class);
- }
-
- /**
- * Gets the changes associated with a build
- *
- * @param buildId pass the build id
- * @return the object of build changes
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildChanges getBuildChanges(int buildId) throws AzDException {
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", Integer.toString(buildId), "changes", ApiVersion.BUILD_CHANGES, null, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildChanges.class);
- }
-
- /**
- * Gets the changes associated with a build
- *
- * @param buildId pass the build id
- * @param top The maximum number of changes to return
- * @param continuationToken pass the continuation token
- * @param includeSourceChange if set to true gets the source changes
- * @return the object of build changes
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildChanges getBuildChanges(
- int buildId, int top, String continuationToken, boolean includeSourceChange) throws AzDException {
-
- HashMap q = new HashMap<>() {{
- put("$top", top);
- put("continuationToken", continuationToken);
- put("includeSourceChange", includeSourceChange);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", Integer.toString(buildId), "changes", ApiVersion.BUILD_CHANGES, q, null, null);
- return MAPPER.mapJsonResponse(r, BuildChanges.class);
- }
-
- /**
- * Gets an individual log file for a build.
- *
- * @param buildId pass the build id
- * @param logId pass the log id
- * @return logs associated with the build for given id
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public String getBuildLog(int buildId, int logId) throws AzDException {
- return send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", Integer.toString(buildId), "logs/" + logId, ApiVersion.BUILD_LOGS,
- null, null, CustomHeader.TEXT_CONTENT);
- }
-
- /**
- * Gets an individual log file for a build.
- *
- * @param buildId pass the build id
- * @param logId pass the log id
- * @param startLine pass the line number from log which you need to fetch
- * @param endLine pass till which line number you need to fetch from the log
- * @return logs associated with the build for given id
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public String getBuildLog(int buildId, int logId, long startLine, long endLine) throws AzDException {
-
- HashMap q = new HashMap<>() {{
- put("startLine", startLine);
- put("endLine", endLine);
- }};
-
- return send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", Integer.toString(buildId), "logs/" + logId, ApiVersion.BUILD_LOGS, q,
- null, CustomHeader.TEXT_CONTENT);
- }
-
- /**
- * Gets the logs for a build.
- *
- * @param buildId pass the build id
- * @return the object of build logs with id. This can be used to fetch the particular log with id
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildLogs getBuildLogs(int buildId) throws AzDException {
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", Integer.toString(buildId), "logs", ApiVersion.BUILD_LOGS, null, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildLogs.class);
- }
-
- /**
- * Gets the work items associated with a build.
- *
- * @param buildId The ID of the build.
- * @return an array of work items associated with the build
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildWorkItems getBuildWorkItems(int buildId) throws AzDException {
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", Integer.toString(buildId), "workitems", ApiVersion.BUILD_WORK_ITEMS, null, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildWorkItems.class);
- }
-
- /**
- * Gets the work items associated with a build.
- *
- * @param buildId id of the build
- * @param top specify how many top work items to return
- * @return an array of work items associated with the build
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildWorkItems getBuildWorkItems(int buildId, int top) throws AzDException {
-
- HashMap q = new HashMap<>() {{
- put("$top", top);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", Integer.toString(buildId), "workitems", ApiVersion.BUILD_WORK_ITEMS, q, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildWorkItems.class);
- }
-
- /**
- * Gets the changes made to the repository between two given builds.
- *
- * @param fromBuildId The ID of the first build.
- * @param toBuildId The ID of the last build.
- * @param top The maximum number of changes to return.
- * @return an array of changes between the builds
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildChanges getChangesBetweenBuilds(int fromBuildId, int toBuildId, int top) throws AzDException {
-
- HashMap q = new HashMap<>() {{
- put("$top", top);
- put("fromBuildId", fromBuildId);
- put("toBuildId", toBuildId);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA, null, "changes", ApiVersion.BUILD_CHANGES, q, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildChanges.class);
- }
-
- /**
- * Gets all the work items between two builds.
- *
- * @param fromBuildId The ID of the first build.
- * @param toBuildId The ID of the last build.
- * @param top The maximum number of changes to return.
- * @return an array of workitems between the builds
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildWorkItems getWorkItemsBetweenBuilds(int fromBuildId, int toBuildId, int top) throws AzDException {
-
- HashMap q = new HashMap<>() {{
- put("$top", top);
- put("fromBuildId", fromBuildId);
- put("toBuildId", toBuildId);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA, null, "workitems", ApiVersion.BUILD_WORK_ITEMS, q, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildWorkItems.class);
- }
-
- /**
- * Gets a list of builds.
- *
- * @return a build array {@link Builds}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Builds getBuilds() throws AzDException {
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", null, null, ApiVersion.BUILD, null, null, null);
-
- return MAPPER.mapJsonResponse(r, Builds.class);
- }
-
- /**
- * Gets a list of builds.
- *
- * @param buildIds array of build ids
- * @return an array of build
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Builds getBuilds(int[] buildIds) throws AzDException {
-
- String ids = Arrays.stream(buildIds).mapToObj(String::valueOf).collect(Collectors.joining(","));
-
- HashMap q = new HashMap<>() {{
- put("buildIds", ids);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", null, null, ApiVersion.BUILD, q, null, null);
-
- return MAPPER.mapJsonResponse(r, Builds.class);
- }
-
- /**
- * Gets a list of builds.
- *
- * @param top specify how many builds to retrieve
- * @return an array of build
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Builds getBuilds(int top) throws AzDException {
-
- HashMap q = new HashMap<>() {{
- put("$top", top);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", null, null, ApiVersion.BUILD, q, null, null);
-
- return MAPPER.mapJsonResponse(r, Builds.class);
- }
-
- /**
- * Gets a list of builds.
- *
- * @param top specify how many builds to retrieve
- * @param branchName If specified, filters to builds that built branches that built this branch.
- * @param buildNumber If specified, filters to builds that match this build number. Append * to do a prefix search.
- * @param continuationToken A continuation token, returned by a previous call to this method, that can be used to return the next set of builds.
- * @param definitions A comma-delimited list of definition IDs. If specified, filters to builds for these definitions.
- * @param deletedFilter Indicates whether to exclude, include, or only return deleted builds.
- * @param maxBuildsPerDefinition The maximum number of builds to return per definition.
- * @param maxTime If specified, filters to builds that finished/started/queued before this date based on the queryOrder specified.
- * @param minTime If specified, filters to builds that finished/started/queued after this date based on the queryOrder specified.
- * @param properties A comma-delimited list of properties to retrieve.
- * @param queryOrder The order in which builds should be returned.
- * @param queues A comma-delimited list of queue IDs. If specified, filters to builds that ran against these queues.
- * @param reasonFilter If specified, filters to builds that match this reason.
- * @param repositoryId If specified, filters to builds that built from this repository.
- * @param repositoryType If specified, filters to builds that built from repositories of this type.
- * @param requestedFor If specified, filters to builds requested for the specified user.
- * @param resultFilter If specified, filters to builds that match this result.
- * @param statusFilter If specified, filters to builds that match this status.
- * @param tagFilters A comma-delimited list of tags. If specified, filters to builds that have the specified tags.
- * @return an array of build
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Builds getBuilds(
- int top, String branchName, String buildNumber, String continuationToken, int[] definitions,
- QueryDeletedOption deletedFilter, int maxBuildsPerDefinition, String maxTime, String minTime,
- String[] properties, BuildQueryOrder queryOrder, int[] queues, BuildReason reasonFilter,
- String repositoryId, String repositoryType, String requestedFor, BuildResult resultFilter,
- BuildStatus statusFilter, String tagFilters) throws AzDException {
-
- String ids = (definitions != null) ? Arrays.stream(definitions).mapToObj(String::valueOf).collect(Collectors.joining(",")) : null;
- String queueIds = (queues != null) ? Arrays.stream(queues).mapToObj(String::valueOf).collect(Collectors.joining(",")) : null;
-
- HashMap q = new HashMap<>() {{
- put("$top", top);
- put("branchName", branchName);
- put("buildNumber", buildNumber);
- put("continuationToken", continuationToken);
- put("definitions", ids);
- put("deletedFilter", deletedFilter);
- put("maxBuildsPerDefinition", maxBuildsPerDefinition);
- put("maxTime", maxTime);
- put("minTime", minTime);
- put("properties", (properties != null) ? String.join(",", properties) : null);
- put("queryOrder", queryOrder);
- put("queues", queueIds);
- put("reasonFilter", reasonFilter);
- put("repositoryType", repositoryType);
- put("requestedFor", requestedFor);
- put("resultFilter", resultFilter);
- put("repositoryId", repositoryId);
- put("statusFilter", statusFilter);
- put("tagFilters", tagFilters);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", null, null, ApiVersion.BUILD, q, null, null);
-
- return MAPPER.mapJsonResponse(r, Builds.class);
- }
-
- /**
- * Queues a build
- *
- * @param definitionId pass the pipeline id to queue the build
- * @return a build object {@link Build}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Build queueBuild(int definitionId) throws AzDException {
-
- HashMap q = new HashMap<>() {{
- put("definitionId", String.valueOf(definitionId));
- }};
-
- String r = send(RequestMethod.POST, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", null, null, ApiVersion.BUILD, q, null, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, Build.class);
- }
-
- /**
- * Queues a build
- *
- * @param buildParameters dictionary of parameters to queue the build.
- * @return a build object {@link Build}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Build queueBuild(Build buildParameters) throws AzDException {
- String r = send(RequestMethod.POST, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", null, null, ApiVersion.BUILD, null, buildParameters, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, Build.class);
- }
-
- /**
- * Updates a build.
- *
- * @param build pass the Build object to update. {@link Build}
- * @param buildId The ID of the build.
- * @param retry None
- * @return Build Object {@link Build}
- * @throws AzDException Default Api Exception handler.
- **/
- @Override
- public Build updateBuild(Build build, int buildId, boolean retry) throws AzDException {
- var q = new HashMap() {{
- put("retry", retry);
- }};
-
- String r = send(RequestMethod.PATCH, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", Integer.toString(buildId), null, ApiVersion.BUILD, q, build, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, Build.class);
- }
-
- /**
- * Updates multiple builds.
- *
- * @param builds List of build to update. {@link Builds}
- * @return Build Object {@link Build}
- * @throws AzDException Default Api Exception handler.
- **/
- @Override
- public Builds updateBuilds(Builds builds) throws AzDException {
- String r = send(RequestMethod.PATCH, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", null, null, ApiVersion.BUILD, null, builds.getBuildResults(), CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, Builds.class);
- }
-
- /**
- * Gets controllers
- *
- * @return array of build controller {@link BuildControllers}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildControllers getBuildControllers() throws AzDException {
- String r = send(RequestMethod.GET, CONNECTION, BUILD, null,
- AREA, null, "controllers", ApiVersion.BUILD_CONTROLLERS, null, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildControllers.class);
- }
-
- /**
- * Gets controller, optionally filtered by name
- *
- * @param name pass the controller name
- * @return array of build controller {@link BuildControllers}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildControllers getBuildControllers(String name) throws AzDException {
-
- HashMap q = new HashMap<>() {{
- put("name", name);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, null,
- AREA, null, "controllers", ApiVersion.BUILD_CONTROLLERS, q, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildControllers.class);
- }
-
- /**
- * Gets a controller
- *
- * @param controllerId pass the controller id
- * @return build controller {@link BuildController}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildController getBuildController(int controllerId) throws AzDException {
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, null,
- AREA + "/controllers", Integer.toString(controllerId), null, ApiVersion.BUILD_CONTROLLERS,
- null, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildController.class);
- }
-
- /**
- * Creates a new definition.
- *
- * @param buildDefinitionParameters json string of the build pipeline. Export the build definition from existing pipeline and edit it.
- * Or get the existing build definition using getBuildDefinition(definitionId) method and call toString() method on it to
- * convert the value to string and create the definition. Easiest way is to use cloneBuildDefinition() method to create
- * a clone of build definition and later edit it to suit the needs.
- * @return build definition {@link BuildDefinition}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildDefinition createBuildDefinition(String buildDefinitionParameters) throws AzDException {
-
- if (buildDefinitionParameters.isEmpty()) throw new AzDException();
-
- var requestBody = MAPPER.mapJsonResponse(buildDefinitionParameters, Map.class);
-
- String r = send(RequestMethod.POST, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA, null, "definitions", ApiVersion.BUILD_DEFINITIONS, null, requestBody, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, BuildDefinition.class);
- }
-
- /**
- * Creates a new definition.
- *
- * @param buildDefinition Build definition object. Export the build definition from existing pipeline and edit it.
- * Or get the existing build definition using getBuildDefinition(definitionId).
- * @return build definition {@link BuildDefinition}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildDefinition createBuildDefinition(BuildDefinition buildDefinition, Number definitionToCloneId,
- Number definitionToCloneRevision) throws AzDException {
-
- Objects.requireNonNull(buildDefinition);
-
- var q = new HashMap() {{
- put("definitionToCloneId", definitionToCloneId);
- put("definitionToCloneRevision", definitionToCloneRevision);
- }};
-
- String r = send(RequestMethod.POST, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA, null, "definitions", ApiVersion.BUILD_DEFINITIONS, q, buildDefinition, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, BuildDefinition.class);
- }
-
- /**
- * Clone an existing definition/pipeline
- *
- * @param definitionName Name of the build definition/pipeline. E.g., WebApp-Deployment-CI
- * @param definitionCloneName Name of the pipeline/definition to be created or cloned. E.g., WebApp-Deployment-CI-Copy
- * @return build definition {@link BuildDefinition}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildDefinition cloneBuildDefinition(String definitionName, String definitionCloneName) throws AzDException {
- // validate if the definition exists
- int def;
-
- try {
- def = getBuildDefinitions()
- .getBuildDefinitions()
- .stream()
- .filter(x -> x.getName().equals(definitionName))
- .findFirst()
- .get()
- .getId();
- } catch (Exception e) {
- throw new AzDException("Cannot find the definition with name '" + definitionName + "'.");
- }
-
- if (!Integer.toString(def).isEmpty()) {
- var definitionObject = getBuildDefinition(def);
- definitionObject.setName(definitionCloneName);
- var res = MAPPER.convertToString(definitionObject);
- return createBuildDefinition(res);
- }
-
- return null;
- }
-
- /**
- * Deletes a definition and all associated builds.
- *
- * @param definitionId pass the definition id
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Void deleteBuildDefinition(int definitionId) throws AzDException {
- try {
- String r = send(RequestMethod.DELETE, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/definitions", Integer.toString(definitionId), null, ApiVersion.BUILD_DEFINITIONS, null, null, null);
- if (!r.isEmpty()) MAPPER.mapJsonResponse(r, Map.class);
- } catch (AzDException e) {
- throw e;
- }
- return null;
- }
-
- /**
- * Gets a definition
- *
- * @param definitionId pass the definition id
- * @return build definition {@link BuildDefinition}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildDefinition getBuildDefinition(int definitionId) throws AzDException {
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/definitions", Integer.toString(definitionId), null, ApiVersion.BUILD_DEFINITIONS,
- null, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildDefinition.class);
- }
-
- /**
- * Gets a definition, optionally at a specific revision.
- *
- * @param definitionId The ID of the definition.
- * @param includeLatestBuilds if specified gets the details of latest build
- * @param minMetricsTime If specified, indicates the date from which metrics should be included.
- * @param revision The revision number to retrieve. If this is not specified, the latest version will be returned.
- * @return Build definition object
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildDefinition getBuildDefinition(
- int definitionId, boolean includeLatestBuilds, String minMetricsTime, int revision) throws AzDException {
-
- HashMap q = new HashMap<>() {{
- put("includeLatestBuilds", includeLatestBuilds);
- put("minMetricsTime", minMetricsTime);
- put("revision", revision);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/definitions", Integer.toString(definitionId), null, ApiVersion.BUILD_DEFINITIONS,
- q, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildDefinition.class);
- }
-
- /**
- * Gets all revisions of a definition.
- *
- * @param definitionId The ID of the definition.
- * @return array of build definition revisions {@link BuildDefinitionRevision}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildDefinitionRevisions getBuildDefinitionRevisions(int definitionId) throws AzDException {
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/definitions", Integer.toString(definitionId), "revisions",
- ApiVersion.BUILD_DEFINITION_REVISIONS, null, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildDefinitionRevisions.class);
- }
-
- /**
- * Gets a list of definitions.
- *
- * @return build definitions {@link BuildDefinitions}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildDefinitions getBuildDefinitions() throws AzDException {
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/definitions", null, null, ApiVersion.BUILD_DEFINITIONS,
- null, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildDefinitions.class);
- }
-
- /**
- * Gets a list of definitions.
- *
- * @param definitionIds array of definition ids
- * @return build definitions {@link BuildDefinitions}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildDefinitions getBuildDefinitions(int[] definitionIds) throws AzDException {
-
- String ids = Arrays.stream(definitionIds).mapToObj(String::valueOf).collect(Collectors.joining(","));
-
- HashMap q = new HashMap<>() {{
- put("definitionIds", ids);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/definitions", null, null, ApiVersion.BUILD_DEFINITIONS, q, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildDefinitions.class);
- }
-
- /**
- * Gets a list of definitions.
- *
- * @param top definitions to retrieve
- * @return build definitions {@link BuildDefinitions}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildDefinitions getBuildDefinitions(int top) throws AzDException {
-
- HashMap q = new HashMap<>() {{
- put("$top", top);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/definitions", null, null, ApiVersion.BUILD_DEFINITIONS, q, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildDefinitions.class);
- }
-
- /**
- * Gets a list of definitions.
- *
- * @param name Name of the build definition
- * @return build definitions {@link BuildDefinitions}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildDefinitions getBuildDefinitions(String name) throws AzDException {
-
- HashMap q = new HashMap<>() {{
- put("name", name);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/definitions", null, null, ApiVersion.BUILD_DEFINITIONS, q, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildDefinitions.class);
- }
-
- /**
- * Gets a list of definitions.
- *
- * @param includeAllProperties Indicates whether the full definitions should be returned. By default, shallow representations of the definitions are returned.
- * @param includeLatestBuilds Indicates whether to return the latest and latest completed builds for this definition.
- * @return build definitions {@link BuildDefinitions}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildDefinitions getBuildDefinitions(boolean includeAllProperties, boolean includeLatestBuilds) throws AzDException {
- HashMap q = new HashMap<>() {{
- put("includeAllProperties", includeAllProperties);
- put("includeLatestBuilds", includeLatestBuilds);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/definitions", null, null, ApiVersion.BUILD_DEFINITIONS, q, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildDefinitions.class);
- }
-
- /**
- * Gets a list of definitions.
- *
- * @param builtAfter If specified, filters to definitions that have builds after this date.
- * @param continuationToken A continuation token, returned by a previous call to this method, that can be used to return the next set of definitions.
- * @param includeAllProperties Indicates whether the full definitions should be returned. By default, shallow representations of the definitions are returned.
- * @param includeLatestBuilds Indicates whether to return the latest and latest completed builds for this definition.
- * @param minMetricsTime If specified, indicates the date from which metrics should be included.
- * @param notBuiltAfter If specified, filters to definitions that do not have builds after this date.
- * @param path If specified, filters to definitions under this folder.
- * @param processType If specified, filters to definitions with the given process type.
- * @param queryOrder Indicates the order in which definitions should be returned.
- * @param repositoryId A repository ID. If specified, filters to definitions that use this repository.
- * @param repositoryType If specified, filters to definitions that have a repository of this type.
- * @param taskIdFilter If specified, filters to definitions that use the specified task.
- * @param yamlFilename If specified, filters to YAML definitions that match the given filename.
- * @return build definitions {@link BuildDefinitions}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildDefinitions getBuildDefinitions(
- String builtAfter, String continuationToken, boolean includeAllProperties,
- boolean includeLatestBuilds, String minMetricsTime, String notBuiltAfter,
- String path, int processType, DefinitionQueryOrder queryOrder, String repositoryId,
- String repositoryType, String taskIdFilter, String yamlFilename) throws AzDException {
-
- HashMap q = new HashMap<>() {{
- put("builtAfter", builtAfter);
- put("continuationToken", continuationToken);
- put("includeAllProperties", includeAllProperties);
- put("includeLatestBuilds", includeLatestBuilds);
- put("minMetricsTime", minMetricsTime);
- put("notBuiltAfter", notBuiltAfter);
- put("path", path);
- put("processType", processType);
- put("queryOrder", queryOrder);
- put("repositoryId", repositoryId);
- put("repositoryType", repositoryType);
- put("taskIdFilter", taskIdFilter);
- put("yamlFilename", yamlFilename);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/definitions", null, null, ApiVersion.BUILD_DEFINITIONS, q, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildDefinitions.class);
- }
-
- /**
- * Restores a deleted definition
- *
- * @param definitionId pass the build definition id
- * @param deleted When false, restores a deleted definition.
- * @return a {@link BuildDefinition} object
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildDefinition restoreBuildDefinition(int definitionId, boolean deleted) throws AzDException {
-
- HashMap q = new HashMap<>() {{
- put("deleted", deleted);
- }};
-
- String r = send(RequestMethod.PATCH, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/definitions", Integer.toString(definitionId), null, ApiVersion.BUILD_DEFINITIONS,
- q, null, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, BuildDefinition.class);
- }
-
- /**
- * Updates an existing build definition.
- * In order for this operation to succeed, the value of the "Revision" property of the request body must match the
- * existing build definition's. It is recommended that you obtain the existing build definition by using GET, modify
- * the build definition as necessary, and then submit the modified definition with PUT.
- *
- * @param definition Build definition object.
- * @return BuildDefinition Object {@link BuildDefinition}
- * @throws AzDException Default Api Exception handler.
- **/
- @Override
- public BuildDefinition updateBuildDefinition(BuildDefinition definition) throws AzDException {
- String r = send(RequestMethod.PUT, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/definitions", Integer.toString(definition.getId()), null, ApiVersion.BUILD_DEFINITIONS, null,
- definition, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, BuildDefinition.class);
- }
-
- /**
- * Updates an existing build definition.
- * In order for this operation to succeed, the value of the "Revision" property of the request body must match the
- * existing build definition's. It is recommended that you obtain the existing build definition by using GET, modify
- * the build definition as necessary, and then submit the modified definition with PUT.
- *
- * @param secretsSourceDefinitionId None
- * @param secretsSourceDefinitionRevision None
- * @param definition Build definition object.
- * @return BuildDefinition Object {@link BuildDefinition}
- * @throws AzDException Default Api Exception handler.
- **/
- @Override
- public BuildDefinition updateBuildDefinition(BuildDefinition definition,
- Number secretsSourceDefinitionId,
- Number secretsSourceDefinitionRevision) throws AzDException {
- var q = new HashMap() {{
- put("secretsSourceDefinitionId", secretsSourceDefinitionId);
- put("secretsSourceDefinitionRevision", secretsSourceDefinitionRevision);
- }};
-
- String r = send(RequestMethod.PUT, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/definitions", Integer.toString(definition.getId()), null, ApiVersion.BUILD_DEFINITIONS, q,
- definition, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, BuildDefinition.class);
- }
-
- /**
- * Creates a new folder.
- *
- * @param path The full path of the folder.
- * @param folder Folder object with mandatory details.
- * @return Folder Object {@link Folder}
- * @throws AzDException Default Api Exception handler.
- **/
- @Override
- public Folder createFolder(String path, Folder folder) throws AzDException {
- var q = new HashMap() {{
- put("path", URLHelper.encodeSpecialWithSpace(path));
- }};
-
- String r = send(RequestMethod.PUT, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA, null, "folders", ApiVersion.BUILD_FOLDER, q, folder, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, Folder.class);
- }
-
- /**
- * Deletes a definition folder. Definitions and their corresponding builds will also be deleted.
- *
- * @param path The full path to the folder.
- * @throws AzDException Default Api Exception handler.
- **/
- @Override
- public Void deleteFolder(String path) throws AzDException {
- try {
- var q = new HashMap() {{
- put("path", URLHelper.encodeSpecialWithSpace(path));
- }};
-
- String r = send(RequestMethod.DELETE, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA, null, "folders", ApiVersion.BUILD_FOLDER, q, null, null);
-
- if (!r.isEmpty()) MAPPER.mapJsonResponse(r, Map.class);
- } catch (AzDException e) {
- throw e;
- }
- return null;
- }
-
- /**
- * Gets a list of build definition folders.
- *
- * @return List of folder Object {@link Folders}
- * @throws AzDException Default Api Exception handler.
- **/
- @Override
- public Folders getFolders() throws AzDException {
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA, null, "folders", ApiVersion.BUILD_FOLDER, null, null, null);
-
- return MAPPER.mapJsonResponse(r, Folders.class);
- }
-
- /**
- * Gets a list of build definition folders.
- *
- * @return List of folder Object {@link Folders}
- * @throws AzDException Default Api Exception handler.
- **/
- @Override
- public Folders getFolders(String path, FolderQueryOrder queryOrder) throws AzDException {
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA, null, "folders/" + path, ApiVersion.BUILD_FOLDER, Map.of("queryOrder", queryOrder), null, null);
-
- return MAPPER.mapJsonResponse(r, Folders.class);
- }
-
- /**
- * Updates an existing folder at given existing path
- *
- * @param path The full path to the folder.
- * @return Folder Object {@link Folder}
- * @throws AzDException Default Api Exception handler.
- **/
- @Override
- public Folder updateFolder(String path, Folder folder) throws AzDException {
- String finalPath;
-
- if (!path.isEmpty() && path.equals("+\\")) finalPath = "\\" + path;
- else finalPath = path;
-
- var q = new HashMap() {{
- put("path", URLHelper.encodeSpecialWithSpace(finalPath));
- }};
-
- String r = send(RequestMethod.POST, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA, null, "folders", ApiVersion.BUILD_FOLDER, q, folder, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, Folder.class);
- }
-
- /**
- * Adds a tag to a build.
- *
- * @param buildId The ID of the build.
- * @param tag The tag to add.
- * @return Sting array of tags {@link BuildTags}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildTags addBuildTag(int buildId, String tag) throws AzDException {
- String r = send(RequestMethod.PUT, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", Integer.toString(buildId), "tags/" + tag, ApiVersion.BUILD_TAGS,
- null, null, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, BuildTags.class);
- }
-
- /**
- * Adds tags to a build.
- *
- * @param buildId The ID of the build.
- * @param tags The tags to add.
- * @return Sting array of tags {@link BuildTags}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildTags addBuildTags(int buildId, List tags) throws AzDException {
- String r = send(RequestMethod.POST, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", Integer.toString(buildId), "tags", ApiVersion.BUILD_TAGS,
- null, tags, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, BuildTags.class);
- }
-
- /**
- * Adds a tag to a definition.
- *
- * @param definitionId Id of build definition.
- * @param tag The tag to add.
- * @return Sting array of tags {@link BuildTags}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildTags addDefinitionTag(int definitionId, String tag) throws AzDException {
- String r = send(RequestMethod.PUT, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/definitions", Integer.toString(definitionId), "tags/" + tag, ApiVersion.BUILD_TAGS,
- null, null, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, BuildTags.class);
- }
-
- /**
- * Adds multiple tags to a definition.
- *
- * @param definitionId Id of build definition.
- * @param tags The tags to add.
- * @return Sting array of tags {@link BuildTags}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildTags addDefinitionTags(int definitionId, List tags) throws AzDException {
- String r = send(RequestMethod.POST, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/definitions", Integer.toString(definitionId), "tags", ApiVersion.BUILD_TAGS,
- null, tags, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, BuildTags.class);
- }
-
- /**
- * Removes a tag from a build.
- * NOTE: This method will not work for tags with special characters. To remove tags with special characters, use the updateBuildTags method instead.
- *
- * @param buildId Id of the build.
- * @param tag The tag to delete.
- * @return Sting array of tags {@link BuildTags}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildTags deleteBuildTag(int buildId, String tag) throws AzDException {
- String r = send(RequestMethod.DELETE, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", Integer.toString(buildId), "tags/" + tag, ApiVersion.BUILD_TAGS,
- null, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildTags.class);
- }
-
- /**
- * Removes a tag from a definition.
- * NOTE: This method will not work for tags with special characters. To remove tags with special characters, use the updateDefinitionTags method instead.
- *
- * @param definitionId Id of the build definition.
- * @param tag The tag to delete
- * @return Sting array of tags {@link BuildTags}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildTags deleteDefinitionTag(int definitionId, String tag) throws AzDException {
- String r = send(RequestMethod.DELETE, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/definitions", Integer.toString(definitionId), "tags/" + tag, ApiVersion.BUILD_TAGS,
- null, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildTags.class);
- }
-
- /**
- * Removes a tag from builds, definitions, and from the tag store
- *
- * @param tag The tag to delete.
- * @return Sting array of tags {@link BuildTags}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildTags deleteTag(String tag) throws AzDException {
- String r = send(RequestMethod.DELETE, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA, null, "tags/" + tag, ApiVersion.BUILD_TAGS, null, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildTags.class);
- }
-
- /**
- * Gets the tags for a build.
- *
- * @param buildId The ID of the build.
- * @return Sting array of tags {@link BuildTags}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildTags getBuildTags(int buildId) throws AzDException {
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", Integer.toString(buildId), "tags", ApiVersion.BUILD_TAGS, null, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildTags.class);
- }
-
- /**
- * Gets the tags for a definition.
- *
- * @param definitionId Id of build definition.
- * @return Sting array of tags
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildTags getDefinitionTags(int definitionId) throws AzDException {
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/definitions", Integer.toString(definitionId), "tags", ApiVersion.BUILD_TAGS,
- null, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildTags.class);
- }
-
- /**
- * Gets the tags for a definition.
- *
- * @param definitionId Id of build definition.
- * @param revision The definition revision number. If not specified, uses the latest revision of the definition.
- * @return Sting array of tags {@link BuildTags}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildTags getDefinitionTags(int definitionId, int revision) throws AzDException {
- var q = new HashMap() {{
- put("revision", revision);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/definitions", Integer.toString(definitionId), "tags", ApiVersion.BUILD_TAGS, q, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildTags.class);
- }
-
- /**
- * Gets a list of all build tags in the project.
- *
- * @return Sting array of tags {@link BuildTags}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildTags getTags() throws AzDException {
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA, null, "tags", ApiVersion.BUILD_TAGS, null, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildTags.class);
- }
-
- /**
- * Adds/Removes tags from a build.
- *
- * @param buildId The ID of the build.
- * @param tags The tags to update.
- * @param toRemove If true removes the tags. Use this to remove tags that has special characters.
- * @return Sting array of tags {@link BuildTags}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildTags updateBuildTags(int buildId, List tags, boolean toRemove) throws AzDException {
-
- var tagValue = toRemove ? "tagsToRemove" : "tagsToAdd";
-
- var body = new HashMap() {{
- put(tagValue, tags);
- }};
-
- String r = send(RequestMethod.PATCH, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", Integer.toString(buildId), "tags", ApiVersion.BUILD_TAGS,
- null, body, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, BuildTags.class);
- }
-
- /**
- * Adds/Removes tags from a build.
- *
- * @param definitionId The Id of the build definition.
- * @param tags The tags to update.
- * @param toRemove If true removes the tags. Use this to remove tags that has special characters.
- * @return Sting array of tags {@link BuildTags}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public BuildTags updateDefinitionTags(int definitionId, List tags, boolean toRemove) throws AzDException {
- var tagValue = toRemove ? "tagsToRemove" : "tagsToAdd";
-
- var body = new HashMap() {{
- put(tagValue, tags);
- }};
-
- String r = send(RequestMethod.PATCH, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/definitions", Integer.toString(definitionId), "tags", ApiVersion.BUILD_TAGS,
- null, body, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, BuildTags.class);
- }
-
- /**
- * Converts a definition to YAML.
- *
- * @param definitionId The ID of the definition.
- * @return Yaml build object {@link YamlBuild}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public YamlBuild getYaml(int definitionId) throws AzDException {
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/definitions", Integer.toString(definitionId), "yaml", ApiVersion.BUILD_YAML,
- null, null, null);
-
- return MAPPER.mapJsonResponse(r, YamlBuild.class);
- }
-
- /**
- * Converts a definition to YAML, optionally at a specific revision.
- *
- * @param definitionId The ID of the definition.
- * @param includeLatestBuilds if true includes latest builds
- * @param minMetricsTime If specified, indicates the date from which metrics should be included.
- * @param propertyFilters A comma-delimited list of properties to include in the results.
- * @param revision The revision number to retrieve. If this is not specified, the latest version will be returned.
- * @return Yaml build object {@link YamlBuild}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public YamlBuild getYaml(int definitionId, boolean includeLatestBuilds, String minMetricsTime,
- String[] propertyFilters, Number revision) throws AzDException {
- var q = new HashMap() {{
- put("includeLatestBuilds", includeLatestBuilds);
- put("minMetricsTime", minMetricsTime);
- put("propertyFilters", String.join(",", propertyFilters));
- put("revision", revision);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/definitions", Integer.toString(definitionId), "yaml", ApiVersion.BUILD_YAML,
- q, null, null);
-
- return MAPPER.mapJsonResponse(r, YamlBuild.class);
- }
-
- /**
- * Update a build stage.
- *
- * @param buildId Id of the build to update the stage.
- * @param stageReferenceName Name of the stage to update.
- * @param forceRetryAllJobs if true forcefully retries all jobs.
- * @param state state to update.
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Void updateBuildStage(int buildId, String stageReferenceName, boolean forceRetryAllJobs, StageUpdateType state) throws AzDException {
- try {
- var body = new HashMap() {{
- put("forceRetryAllJobs", forceRetryAllJobs);
- put("state", state.toString().toLowerCase());
- }};
-
- String r = send(RequestMethod.PATCH, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", buildId + "/stages/" + stageReferenceName, null, ApiVersion.BUILD_STAGE,
- null, body, CustomHeader.JSON_CONTENT_TYPE);
- if (!r.isEmpty()) MAPPER.mapJsonResponse(r, Map.class);
- } catch (AzDException e) {
- throw e;
- }
- return null;
- }
-
- /**
- * Gets the contents of a file in the given source code repository.
- *
- * @param providerName The name of the source provider. E.g., Github
- * @param serviceEndpointId If specified, the ID of the service endpoint to query. Can only be omitted for providers
- * that do not use service endpoints, e.g. TFVC or TFGit.
- * @param repositoryName If specified, the vendor-specific identifier or the name of the repository to get branches.
- * Can only be omitted for providers that do not support multiple repositories.
- * @param branchName The identifier of the commit or branch from which a file's contents are retrieved.
- * @param path The path to the file to retrieve, relative to the root of the repository.
- * @return Contents of the file given String. {@link String}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public String getFileContents(String providerName, String serviceEndpointId, String repositoryName, String branchName, String path)
- throws AzDException {
- var q = new HashMap() {{
- put("serviceEndpointId", serviceEndpointId);
- put("repository", repositoryName);
- put("commitOrBranch", branchName);
- put("path", path);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- "sourceProviders", null, providerName + "/filecontents", ApiVersion.BUILD_SOURCE_PROVIDERS,
- q, null, CustomHeader.TEXT_CONTENT);
-
- // Look for all the keys as genuine response can also contain any key in the content.
- if (!r.isEmpty() && r.contains("innerException") && r.contains("$id") && r.contains("eventId") && r.contains("typeName"))
- MAPPER.mapJsonResponse(r, Map.class);
-
- return r;
- }
-
- /**
- * Gets the contents of a directory in the given source code repository.
- *
- * @param providerName The name of the source provider. E.g., Github
- * @param serviceEndpointId If specified, the ID of the service endpoint to query. Can only be omitted for providers
- * that do not use service endpoints, e.g. TFVC or TFGit.
- * @param repositoryName If specified, the vendor-specific identifier or the name of the repository to get branches.
- * Can only be omitted for providers that do not support multiple repositories.
- * @param branchName The identifier of the commit or branch from which a file's contents are retrieved.
- * @param path The path to the file to retrieve, relative to the root of the repository.
- * @return SourceRepositoryItems {@link SourceRepositoryItems}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public SourceRepositoryItems getPathContents(String providerName, String serviceEndpointId, String repositoryName, String branchName, String path)
- throws AzDException {
- var q = new HashMap() {{
- put("serviceEndpointId", serviceEndpointId);
- put("repository", repositoryName);
- put("commitOrBranch", branchName);
- put("path", path);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- "sourceProviders", null, providerName + "/pathcontents", ApiVersion.BUILD_SOURCE_PROVIDERS,
- q, null, null);
-
- return MAPPER.mapJsonResponse(r, SourceRepositoryItems.class);
- }
-
- /**
- * Gets a pull request object from source provider.
- *
- * @param providerName The name of the source provider.
- * @param pullRequestId Vendor-specific id of the pull request.
- * @param repositoryName Vendor-specific identifier or the name of the repository that contains the pull request.
- * @param serviceEndpointId If specified, the ID of the service endpoint to query.
- * Can only be omitted for providers that do not use service endpoints, e.g. TFVC or TFGit.
- * @return SourceProviderPullRequest {@link SourceProviderPullRequest}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public SourceProviderPullRequest getPullRequest(String providerName, String pullRequestId, String repositoryName, String serviceEndpointId)
- throws AzDException {
- var q = new HashMap() {{
- put("serviceEndpointId", serviceEndpointId);
- put("repositoryId", repositoryName);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- "sourceProviders", null, providerName + "/pullrequests/" + pullRequestId, ApiVersion.BUILD_SOURCE_PROVIDERS,
- q, null, null);
-
- return MAPPER.mapJsonResponse(r, SourceProviderPullRequest.class);
- }
-
- /**
- * Get a list of source providers and their capabilities.
- *
- * @return SourceProviderAttributes {@link SourceProviderAttributes}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public SourceProviderAttributes getSourceProviders() throws AzDException {
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- "sourceProviders", null, null, ApiVersion.BUILD_SOURCE_PROVIDERS,
- null, null, null);
-
- return MAPPER.mapJsonResponse(r, SourceProviderAttributes.class);
- }
-
- /**
- * Gets a list of branches for the given source code repository.
- *
- * @param providerName The name of the source provider.
- * @param serviceEndpointId If specified, the ID of the service endpoint to query.
- * Can only be omitted for providers that do not use service endpoints, e.g. TFVC or TFGit.
- * @param repositoryName The vendor-specific identifier or the name of the repository to get branches.
- * Can only be omitted for providers that do not support multiple repositories.
- * @return SourceProvideBranches {@link SourceProviderBranches}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public SourceProviderBranches getBranches(String providerName, String serviceEndpointId, String repositoryName) throws AzDException {
- var q = new HashMap() {{
- put("serviceEndpointId", serviceEndpointId);
- put("repository", repositoryName);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- "sourceProviders", null, providerName + "/branches", ApiVersion.BUILD_SOURCE_PROVIDERS,
- q, null, null);
-
- return MAPPER.mapJsonResponse(r, SourceProviderBranches.class);
- }
-
- /**
- * Gets a list of branches for the given source code repository.
- *
- * @param providerName The name of the source provider.
- * @param serviceEndpointId If specified, the ID of the service endpoint to query.
- * Can only be omitted for providers that do not use service endpoints, e.g. TFVC or TFGit.
- * @param repositoryName The vendor-specific identifier or the name of the repository to get branches.
- * Can only be omitted for providers that do not support multiple repositories.
- * @param branchName If supplied, the name of the branch to check for specifically.
- * @return SourceProvideBranches {@link SourceProviderBranches}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public SourceProviderBranches getBranches(String providerName, String serviceEndpointId, String repositoryName, String branchName) throws AzDException {
- var q = new HashMap() {{
- put("serviceEndpointId", serviceEndpointId);
- put("repository", repositoryName);
- put("branchName", branchName);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- "sourceProviders", null, providerName + "/branches", ApiVersion.BUILD_SOURCE_PROVIDERS,
- q, null, null);
-
- return MAPPER.mapJsonResponse(r, SourceProviderBranches.class);
- }
-
- /**
- * Gets a list of source code repositories.
- *
- * @param providerName The name of the source provider.
- * @param serviceEndpointId If specified, the ID of the service endpoint to query.
- * Can only be omitted for providers that do not use service endpoints, e.g. TFVC or TFGit.
- * @return SourceRepositories {@link SourceRepositories}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public SourceRepositories getRepositories(String providerName, String serviceEndpointId) throws AzDException {
- var q = new HashMap() {{
- put("serviceEndpointId", serviceEndpointId);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- "sourceProviders", null, providerName + "/repositories", ApiVersion.BUILD_SOURCE_PROVIDERS,
- q, null, null);
-
- return MAPPER.mapJsonResponse(r, SourceRepositories.class);
- }
-
- /**
- * Gets a list of source code repositories.
- *
- * @param providerName The name of the source provider.
- * @param serviceEndpointId If specified, the ID of the service endpoint to query.
- * Can only be omitted for providers that do not use service endpoints, e.g. TFVC or TFGit.
- * @param repositoryName If specified, the vendor-specific identifier or the name of a single repository to get.
- * @return SourceRepositories {@link SourceRepositories}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public SourceRepositories getRepositories(String providerName, String serviceEndpointId, String repositoryName) throws AzDException {
- var q = new HashMap() {{
- put("serviceEndpointId", serviceEndpointId);
- put("repository", repositoryName);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- "sourceProviders", null, providerName + "/repositories", ApiVersion.BUILD_SOURCE_PROVIDERS,
- q, null, null);
-
- return MAPPER.mapJsonResponse(r, SourceRepositories.class);
- }
-
- /**
- * Gets a list of source code repositories.
- *
- * @param providerName The name of the source provider.
- * @param serviceEndpointId If specified, the ID of the service endpoint to query.
- * Can only be omitted for providers that do not use service endpoints, e.g. TFVC or TFGit.
- * @param repositoryName If specified, the vendor-specific identifier or the name of a single repository to get.
- * @param continuationToken When paging results, this is a continuation token, returned by a previous call to
- * this method, that can be used to return the next set of repositories.
- * @param pageResults If set to true, this will limit the set of results and will return a continuation token to continue the query.
- * @param resultSet 'top' for the repositories most relevant for the endpoint. If not set, all repositories are returned. Ignored if 'repository' is set.
- * @return SourceRepositories {@link SourceRepositories}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public SourceRepositories getRepositories(String providerName, String serviceEndpointId, String repositoryName, String continuationToken,
- boolean pageResults, SourceProviderResultSet resultSet) throws AzDException {
- var q = new HashMap() {{
- put("serviceEndpointId", serviceEndpointId);
- put("repository", repositoryName);
- put("resultSet", resultSet.toString().toLowerCase());
- put("pageResults", pageResults);
- put("continuationToken", continuationToken);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- "sourceProviders", null, providerName + "/repositories", ApiVersion.BUILD_SOURCE_PROVIDERS,
- q, null, null);
-
- return MAPPER.mapJsonResponse(r, SourceRepositories.class);
- }
-
- /**
- * Gets a list of webhooks installed in the given source code repository.
- *
- * @param providerName The name of the source provider.
- * @param serviceEndpointId If specified, the ID of the service endpoint to query.
- * Can only be omitted for providers that do not use service endpoints, e.g. TFVC or TFGit.
- * @param repositoryName If specified, the vendor-specific identifier or the name of the repository to get webhooks.
- * Can only be omitted for providers that do not support multiple repositories.
- * @return RepositoryWebhooks {@link RepositoryWebhooks}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public RepositoryWebhooks getWebHooks(String providerName, String serviceEndpointId, String repositoryName) throws AzDException {
- var q = new HashMap() {{
- put("serviceEndpointId", serviceEndpointId);
- put("repository", repositoryName);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- "sourceProviders", null, providerName + "/webhooks", ApiVersion.BUILD_SOURCE_PROVIDERS,
- q, null, null);
-
- return MAPPER.mapJsonResponse(r, RepositoryWebhooks.class);
- }
-
- /**
- * Recreates the webhooks for the specified triggers in the given source code repository.
- *
- * @param providerName The name of the source provider.
- * @param serviceEndpointId If specified, the ID of the service endpoint to query.
- * Can only be omitted for providers that do not use service endpoints, e.g. TFVC or TFGit.
- * @param repositoryName If specified, the vendor-specific identifier or the name of the repository to get webhooks.
- * Can only be omitted for providers that do not support multiple repositories.
- * @param triggerTypes The types of triggers to restore webhooks for.
- * @return Void; successful operation
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Void restoreWebHooks(String providerName, String serviceEndpointId, String repositoryName, List triggerTypes) throws AzDException {
- var q = new HashMap() {{
- put("serviceEndpointId", serviceEndpointId);
- put("repository", repositoryName);
- }};
-
- try {
- String r = send(RequestMethod.POST, CONNECTION, BUILD, CONNECTION.getProject(),
- "sourceProviders", null, providerName + "/webhooks", ApiVersion.BUILD_SOURCE_PROVIDERS,
- q, triggerTypes, CustomHeader.JSON_CONTENT_TYPE);
- if (!r.isEmpty()) MAPPER.mapJsonResponse(r, Map.class);
- } catch (AzDException e) {
- throw e;
- }
- return null;
- }
-
- /**
- * Gets details for a build.
- *
- * @param buildId Id of the build. use getBuilds() to list all the builds.
- * @return a timeline object. {@link Timeline}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Timeline getTimeline(int buildId) throws AzDException {
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", Integer.toString(buildId), "timeline", ApiVersion.BUILD_TIMELINE,
- null, null, null);
-
- return MAPPER.mapJsonResponse(r, Timeline.class);
- }
-
- /**
- * Gets details for a build.
- *
- * @param buildId Id of the build. use getBuilds() to list all the builds.
- * @param timelineId Id of the build timeline.
- * @return a timeline object. {@link Timeline}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Timeline getTimeline(int buildId, String timelineId) throws AzDException {
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", Integer.toString(buildId), "timeline/" + timelineId, ApiVersion.BUILD_TIMELINE,
- null, null, null);
-
- return MAPPER.mapJsonResponse(r, Timeline.class);
- }
-
- /**
- * Gets details for a build.
- *
- * @param buildId Id of the build. use getBuilds() to list all the builds.
- * @param timelineId Id of the build timeline.
- * @param changeId Timeline change id.
- * @param planId Timeline plan id. This value can be null if unknown.
- * @return a timeline object. {@link Timeline}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Timeline getTimeline(int buildId, String timelineId, int changeId, String planId) throws AzDException {
- var q = new HashMap() {{
- put("changeId", changeId);
- put("planId", planId);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", Integer.toString(buildId), "timeline/" + timelineId, ApiVersion.BUILD_TIMELINE,
- q, null, null);
-
- return MAPPER.mapJsonResponse(r, Timeline.class);
- }
-
- /**
- * Associates an artifact with a build.
- *
- * @param buildId The ID of the build.
- * @param artifact Build artifact to associate.
- * @return BuildArtifact Object {@link BuildArtifact}
- * @throws AzDException Default Api Exception handler.
- **/
- @Override
- public BuildArtifact createArtifact(int buildId, BuildArtifact artifact) throws AzDException {
- String r = send(RequestMethod.POST, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", Integer.toString(buildId), "artifacts", ApiVersion.BUILD_ARTIFACTS,
- null, artifact, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, BuildArtifact.class);
- }
-
- /**
- * Gets a specific artifact for a build.
- *
- * @param buildId The ID of the build.
- * @param artifactName The name of the artifact.
- * @return BuildArtifact Object {@link BuildArtifact}
- * @throws AzDException Default Api Exception handler.
- **/
- @Override
- public BuildArtifact getArtifact(int buildId, String artifactName) throws AzDException {
- var q = new HashMap() {{
- put("artifactName", artifactName);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", Integer.toString(buildId), "artifacts", ApiVersion.BUILD_ARTIFACTS,
- q, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildArtifact.class);
- }
-
- /**
- * Gets a specific artifact for a build as a zip file.
- *
- * @param buildId The ID of the build.
- * @param artifactName The name of the artifact.
- * @return Input stream response of artifact
- * @throws AzDException Default Api Exception handler.
- **/
- @Override
- public InputStream getArtifactAsZip(int buildId, String artifactName) throws AzDException {
- var q = new HashMap() {{
- put("artifactName", artifactName);
- }};
-
- return send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", Integer.toString(buildId), "artifacts", ApiVersion.BUILD_ARTIFACTS,
- q, null, CustomHeader.STREAM_ZIP_ACCEPT, false);
- }
-
- /**
- * Gets a file from the build. Returns the file contents as InputStream and {@link org.azd.helpers.StreamHelper}
- * can be used to download the file.
- *
- * @param buildId The ID of the build.
- * @param artifactName The name of the artifact.
- * @return Input stream response of artifact
- * @throws AzDException Default Api Exception handler.
- **/
- @Override
- public InputStream getArtifactFile(int buildId, String artifactName, String fileId, String fileName) throws AzDException {
- var q = new HashMap() {{
- put("artifactName", artifactName);
- put("fileId", fileId);
- put("fileName", fileName);
- }};
-
- return send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", Integer.toString(buildId), "artifacts", ApiVersion.BUILD_ARTIFACTS,
- q, null, CustomHeader.STREAM_ACCEPT, false);
- }
-
- /**
- * Gets all artifacts for a build.
- *
- * @param buildId The ID of the build.
- * @return BuildArtifact Object {@link BuildArtifact}
- * @throws AzDException Default Api Exception handler.
- **/
- @Override
- public BuildArtifacts getArtifacts(int buildId) throws AzDException {
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", Integer.toString(buildId), "artifacts", ApiVersion.BUILD_ARTIFACTS,
- null, null, null);
-
- return MAPPER.mapJsonResponse(r, BuildArtifacts.class);
- }
-
- /**
- * Gets the list of attachments of a specific type that are associated with a build.
- *
- * @param buildId The ID of the build.
- * @param type The type of attachment.
- * @return Attachment Object {@link Attachment}
- * @throws AzDException Default Api Exception handler.
- **/
- @Override
- public Attachments getAttachments(int buildId, String type) throws AzDException {
- String r = send(RequestMethod.GET, CONNECTION, BUILD, CONNECTION.getProject(),
- AREA + "/builds", Integer.toString(buildId), "attachments/" + type, ApiVersion.BUILD_ATTACHMENTS,
- null, null, null);
-
- return MAPPER.mapJsonResponse(r, Attachments.class);
- }
-}
\ No newline at end of file
diff --git a/azd/src/main/java/org/azd/common/ApiVersion.java b/azd/src/main/java/org/azd/common/ApiVersion.java
index 2f22f980..e02b71b6 100644
--- a/azd/src/main/java/org/azd/common/ApiVersion.java
+++ b/azd/src/main/java/org/azd/common/ApiVersion.java
@@ -80,6 +80,7 @@ public abstract class ApiVersion {
public static final String WIKI_PAGES = "7.2-preview.1";
public static final String WORK = "7.2-preview.1";
public static final String WORK_CAPACITY = "7.2-preview.3";
+ public static final String WORK_ITEM_TRACKING_COMMENTS = "7.2-preview.4";
public static final String WORK_ITEM_MIGRATE = "7.2-preview.1";
public static final String WORK_ITEM_TAGS = "7.2-preview.1";
public static final String WORK_ITEM_TRACKING = "7.2-preview.3";
diff --git a/azd/src/main/java/org/azd/common/types/AccessToken.java b/azd/src/main/java/org/azd/common/types/AccessToken.java
new file mode 100644
index 00000000..f99532ac
--- /dev/null
+++ b/azd/src/main/java/org/azd/common/types/AccessToken.java
@@ -0,0 +1,64 @@
+package org.azd.common.types;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.azd.abstractions.serializer.SerializableEntity;
+
+/**
+ * Represents the access token result object
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class AccessToken extends SerializableEntity {
+ /**
+ * Type of token
+ */
+ @JsonProperty("token_type")
+ public String TokenType;
+ /**
+ * Token expiration
+ */
+ @JsonProperty("expires_in")
+ public int ExpiresIn;
+ /**
+ * Token extended expiration
+ */
+ @JsonProperty("ext_expires_in")
+ public int ExtExpiresIn;
+ /**
+ * Access token
+ */
+ @JsonProperty("access_token")
+ public String Token;
+
+ public String getTokenType() {
+ return TokenType;
+ }
+
+ public void setTokenType(String tokenType) {
+ TokenType = tokenType;
+ }
+
+ public int getExpiresIn() {
+ return ExpiresIn;
+ }
+
+ public void setExpiresIn(int expiresIn) {
+ ExpiresIn = expiresIn;
+ }
+
+ public int getExtExpiresIn() {
+ return ExtExpiresIn;
+ }
+
+ public void setExtExpiresIn(int extExpiresIn) {
+ ExtExpiresIn = extExpiresIn;
+ }
+
+ public String getToken() {
+ return Token;
+ }
+
+ public void setToken(String token) {
+ Token = token;
+ }
+}
diff --git a/azd/src/main/java/org/azd/configurations/ClientConfigurationRequestBuilder.java b/azd/src/main/java/org/azd/configurations/ClientConfigurationRequestBuilder.java
index 3b0f6d08..91ad28c3 100644
--- a/azd/src/main/java/org/azd/configurations/ClientConfigurationRequestBuilder.java
+++ b/azd/src/main/java/org/azd/configurations/ClientConfigurationRequestBuilder.java
@@ -1,6 +1,5 @@
package org.azd.configurations;
-import org.azd.abstractions.ClientConfiguration;
import org.azd.abstractions.proxy.ProxyConfiguration;
import org.azd.abstractions.proxy.ProxyProvider;
@@ -28,15 +27,4 @@ public void proxy(ProxyConfiguration proxyConfiguration) {
Objects.requireNonNull(proxyConfiguration, "Proxy configuration cannot be null.");
ProxyProvider.configure(proxyConfiguration);
}
-
- /**
- * Sets the maximum retries for retrying the request if "Retry-After" header is found in the response headers.
- * Default retries is set to 3 and maximum value can be set to 6.
- *
- * @param maxRetry Maximum retry value.
- */
- public void setMaxRetry(int maxRetry) {
- var retryHandler = ClientConfiguration.getInstance().getRetryHandler();
- retryHandler.setDefaultMaxRetry(maxRetry);
- }
}
diff --git a/azd/src/main/java/org/azd/connection/Connection.java b/azd/src/main/java/org/azd/connection/Connection.java
deleted file mode 100644
index fd65b829..00000000
--- a/azd/src/main/java/org/azd/connection/Connection.java
+++ /dev/null
@@ -1,205 +0,0 @@
-package org.azd.connection;
-
-import org.azd.exceptions.AzDException;
-import org.azd.helpers.URLHelper;
-import org.azd.oauth.OAuthApi;
-import org.azd.oauth.types.AuthorizedToken;
-
-/**
- * The factory class which sets the default parameters to use this library.
- *
- * To call the Azure DevOps services REST API organization name and personal access token are
- * mandatory. Setting these parameters as default helps to work with this library on ease.
- *
- */
-@Deprecated(since = "v6.0; This is deprecated; Please use AzDClientApi which uses Personal access token and OAuth2.0 authentication.")
-public class Connection {
- private static final TokenRefreshedHandler defaultTokenRefreshedHandler = newToken -> {
- };
- private String organization;
- private String project;
- private String personalAccessToken;
- private String appSecret;
- private String appCallBackURL;
- private AuthorizedToken oauthToken = null;
- private TokenRefreshedHandler tokenRefreshedHandler = defaultTokenRefreshedHandler;
-
- /**
- * default with no parameters
- */
- public Connection() {
- }
-
- /**
- * Instantiates the class with organization name, project name and personal access token
- *
- * @param organization pass the organization name
- * @param project provide the project name
- * @param personalAccessToken pass the personal access token
- */
- private Connection(String organization, String project, String personalAccessToken, AuthorizedToken oauthToken, String appSecret, String appCallBackURL, TokenRefreshedHandler tokenRefreshedHandler) {
- this.organization = organization;
- this.project = URLHelper.encodeSpace(project);
- this.personalAccessToken = personalAccessToken;
- this.oauthToken = oauthToken;
- this.appSecret = appSecret;
- this.appCallBackURL = appCallBackURL;
- this.tokenRefreshedHandler = tokenRefreshedHandler != null ? tokenRefreshedHandler : defaultTokenRefreshedHandler;
- }
-
- /**
- * Instantiates the class with organization name and personal access token.
- * Use this method if you don't want to specify the devops project
- *
- * @param organization pass the organization name
- * @param personalAccessToken pass the personal access token
- */
- public Connection(String organization, String personalAccessToken) {
- this(organization, null, personalAccessToken, null, null, null, null);
- }
-
- /**
- * Instantiates the class with organization name, project name and personal access token.
- * Use this method if you want to specify the devops project
- *
- * @param organization pass the organization name
- * @param project provide the project name
- * @param personalAccessToken pass the personal access token
- */
- public Connection(String organization, String project, String personalAccessToken) {
- this(organization, project, personalAccessToken, null, null, null, null);
- }
-
- /**
- * Instantiates the class with organization name and oauth access token.
- * Use this method if you don't want to specify the devops project and you don't want to be notified on oauth token refreshing
- *
- * @param organization pass the organization name
- * @param oauthToken pass the oauth access token
- * @param appSecret pass the app/client secret. It is used to refresh the oauth access token
- * @param appCallBackURL pass the app/client callBackURL (declared in the app). It is used to refresh the oauth access token
- */
- public Connection(String organization, AuthorizedToken oauthToken, String appSecret, String appCallBackURL) {
- this(organization, null, null, oauthToken, appSecret, appCallBackURL, null);
- }
-
- /**
- * Instantiates the class with organization name, project name and oauth access token.
- * Use this method if you want to specify the devops project and you want to be notified on oauth token refreshing
- *
- * @param organization pass the organization name
- * @param project provide the project name
- * @param oauthToken pass the oauth access token
- * @param appSecret pass the app/client secret. It is used to refresh the oauth access token
- * @param appCallBackURL pass the app/client callBackURL (declared in the app). It is used to refresh the oauth access token
- * @param tokenRefreshedHandler pass the handler to be called on oauth token refresh
- */
- public Connection(String organization, String project, AuthorizedToken oauthToken, String appSecret, String appCallBackURL, TokenRefreshedHandler tokenRefreshedHandler) {
- this(organization, project, null, oauthToken, appSecret, appCallBackURL, tokenRefreshedHandler);
- }
-
- /**
- * Instantiates the class with organization name and oauth access token.
- * Use this method if you don't want to specify the devops project but you want to be notified on oauth token refreshing
- *
- * @param organization pass the organization name
- * @param oauthToken pass the oauth access token
- * @param appSecret pass the app/client secret. It is used to refresh the oauth access token
- * @param appCallBackURL pass the app/client callBackURL (declared in the app). It is used to refresh the oauth access token
- * @param tokenRefreshedHandler pass the handler to be called on oauth token refresh
- */
- public Connection(String organization, AuthorizedToken oauthToken, String appSecret, String appCallBackURL, TokenRefreshedHandler tokenRefreshedHandler) {
- this(organization, null, null, oauthToken, appSecret, appCallBackURL, tokenRefreshedHandler);
- }
-
- /**
- * Instantiates the class with organization name, project name and oauth access token.
- * Use this method if you want to specify the devops project and you don't want to be notified on oauth token refreshing
- *
- * @param organization pass the organization name
- * @param project provide the project name
- * @param oauthToken pass the oauth access token
- * @param appSecret pass the app/client secret. It is used to refresh the oauth access token
- * @param appCallBackURL pass the app/client callBackURL (declared in the app). It is used to refresh the oauth access token
- */
- public Connection(String organization, String project, AuthorizedToken oauthToken, String appSecret, String appCallBackURL) {
- this(organization, project, null, oauthToken, appSecret, appCallBackURL, null);
- }
-
- /**
- * Get the default organization name
- *
- * @return organization name
- */
- public String getOrganization() {
- return this.organization;
- }
-
- /**
- * Set the organization name to default
- *
- * @param organization pass the organization name
- */
- public void setOrganization(String organization) {
- this.organization = organization;
- }
-
- /**
- * Get the default Project name
- *
- * @return project name
- */
- public String getProject() {
- return this.project;
- }
-
- /**
- * Set the project name to default
- *
- * @param project pass the project name
- */
- public void setProject(String project) {
- this.project = URLHelper.encodeSpace(project);
- }
-
- /**
- * Get the personal access token
- *
- * @return the personal access token
- * @throws AzDException Default Api Exception handler.
- */
- public String getPersonalAccessToken() throws AzDException {
- if (oauthToken != null) {
- if (OAuthApi.hasTokenExpired(oauthToken)) {
- setOauthToken(OAuthApi.getRefreshToken(appSecret, oauthToken.getRefreshToken(), appCallBackURL));
- }
- return oauthToken.getAccessToken();
- }
- return this.personalAccessToken;
- }
-
- /**
- * Set the personal access token
- *
- * @param personalAccessToken pass the personal access token
- */
- public void setPersonalAccessToken(String personalAccessToken) {
- this.oauthToken = null;
- this.personalAccessToken = personalAccessToken;
- }
-
- /**
- * Set the oauth access token
- *
- * @param oauthToken pass the oauth access token
- */
- public void setOauthToken(AuthorizedToken oauthToken) {
- this.oauthToken = oauthToken;
- tokenRefreshedHandler.tokenRefreshed(oauthToken);
- }
-
- public interface TokenRefreshedHandler {
- void tokenRefreshed(AuthorizedToken newToken);
- }
-
-}
diff --git a/azd/src/main/java/org/azd/core/CoreApi.java b/azd/src/main/java/org/azd/core/CoreApi.java
deleted file mode 100644
index 3a007543..00000000
--- a/azd/src/main/java/org/azd/core/CoreApi.java
+++ /dev/null
@@ -1,446 +0,0 @@
-package org.azd.core;
-
-import org.azd.common.ApiVersion;
-import org.azd.connection.Connection;
-import org.azd.core.types.*;
-import org.azd.enums.CustomHeader;
-import org.azd.enums.FeatureManagement;
-import org.azd.enums.ProjectState;
-import org.azd.enums.RequestMethod;
-import org.azd.exceptions.AzDException;
-import org.azd.helpers.JsonMapper;
-import org.azd.interfaces.CoreDetails;
-import org.azd.utils.AzDAsyncApi;
-
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Optional;
-
-import static org.azd.utils.RestClient.send;
-
-/**
- * Core class to manage core API
- */
-public class CoreApi extends AzDAsyncApi implements CoreDetails {
- /**
- * Connection object
- */
- private final Connection CONNECTION;
- private final JsonMapper MAPPER = new JsonMapper();
- private final String CORE = "79134c72-4a58-4b42-976c-04e7115f32bf";
- private final String AREA = "projects";
-
- /**
- * Pass the connection object to work with Core Api
- *
- * @param connection Connection object
- */
- public CoreApi(Connection connection) {
- this.CONNECTION = connection;
- }
-
- /**
- * Get a list of processes.
- *
- * @return a list of processes {@link Processes}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Processes getProcesses() throws AzDException {
-
- String r = send(RequestMethod.GET, CONNECTION, CORE, null,
- "process/processes", null, null, ApiVersion.CORE, null, null, null);
-
- return MAPPER.mapJsonResponse(r, Processes.class);
- }
-
- /**
- * Creates a default scrum project
- *
- * @param projectName pass the project name
- * @param description pass the description for the project
- * @return object with link to the project
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public OperationReference createProject(String projectName, String description) throws AzDException {
-
- LinkedHashMap h = new LinkedHashMap<>() {{
- put("name", projectName);
- put("description", description);
- put("capabilities", new LinkedHashMap() {{
- put("versioncontrol", new LinkedHashMap() {{
- put("sourceControlType", "Git");
- }});
- put("processTemplate", new LinkedHashMap() {{
- put("templateTypeId", "6b724908-ef14-45cf-84f8-768b5384da45");
- }});
- }});
- }};
-
- String r = send(RequestMethod.POST, CONNECTION, CORE, null,
- AREA, null, null, ApiVersion.PROJECT, null, h, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, OperationReference.class);
- }
-
- /**
- * Creates a project for given process id
- *
- * @param projectName pass the project name
- * @param description project description
- * @param sourceControlType type of version control
- * @param templateTypeId pass the process id. Run getProcesses to get the list of process id
- * @return object with link to the project
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public OperationReference createProject(String projectName, String description, String sourceControlType,
- String templateTypeId) throws AzDException {
-
- LinkedHashMap h = new LinkedHashMap<>() {{
- put("name", projectName);
- put("description", description);
- put("capabilities", new LinkedHashMap() {{
- put("versioncontrol", new LinkedHashMap() {{
- put("sourceControlType", sourceControlType);
- }});
- put("processTemplate", new LinkedHashMap() {{
- put("templateTypeId", templateTypeId);
- }});
- }});
- }};
-
- String r = send(RequestMethod.POST, CONNECTION, CORE, null,
- AREA, null, null, ApiVersion.PROJECT, null, h, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, OperationReference.class);
- }
-
- /**
- * Queues a project to be deleted.
- *
- * You should pass the project id to delete it. Passing the project name
- * won't delete. To get the project id run getProject() with projectName
- * and get the Id.
- *
- *
- * @param projectId pass the project id
- * @return object of deleted project with url
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public OperationReference deleteProject(String projectId) throws AzDException {
-
- String r = send(RequestMethod.DELETE, CONNECTION, CORE, null,
- AREA, projectId, null, ApiVersion.PROJECT, null, null, null);
-
- return MAPPER.mapJsonResponse(r, OperationReference.class);
- }
-
- /**
- * Get project with the specified id or name
- *
- * @param projectName pass the project name or id
- * @return project object {@link Project}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Project getProject(String projectName) throws AzDException {
-
- String r = send(RequestMethod.GET, CONNECTION, CORE, null,
- AREA, projectName, null, ApiVersion.PROJECT, null, null, null);
-
- return MAPPER.mapJsonResponse(r, Project.class);
- }
-
- /**
- * Get project with the specified id or name with optional parameters
- *
- * @param projectName pass the project name or id
- * @param includeCapabilities Include capabilities (such as source control) in the team project result (default: false).
- * @param includeHistory Search within renamed projects (that had such name in the past).
- * @return project object {@link Project}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Project getProject(String projectName, boolean includeCapabilities, boolean includeHistory) throws AzDException {
-
- HashMap q = new HashMap<>() {{
- put("includeCapabilities", includeCapabilities);
- put("includeHistory", includeHistory);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, CORE, null,
- AREA, projectName, null, ApiVersion.PROJECT, q, null, null);
-
- return MAPPER.mapJsonResponse(r, Project.class);
- }
-
- /**
- * Get a collection of team project properties.
- *
- * @param projectId provide the project guid not the project name
- * @return ProjectProperties {@link ProjectProperties}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public ProjectProperties getProjectProperties(String projectId) throws AzDException {
-
- String r = send(RequestMethod.GET, CONNECTION, CORE, null,
- AREA, projectId, "properties", ApiVersion.PROJECT_PROPERTIES, null, null, null);
-
- return MAPPER.mapJsonResponse(r, ProjectProperties.class);
- }
-
- /**
- * Get all projects in the organization that the authenticated user has access to.
- *
- * @return array of projects {@link Projects}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Projects getProjects() throws AzDException {
-
- String r = send(RequestMethod.GET, CONNECTION, CORE, null,
- AREA, null, null, ApiVersion.PROJECT, null, null, null);
-
- return MAPPER.mapJsonResponse(r, Projects.class);
- }
-
- /**
- * Get all projects in the organization that the authenticated user has access to.
- *
- * @param skip specify how many projects to skip
- * @param top specify the number projects to retrieve
- * @param continuationToken specify the next value to retrieve
- * @param getDefaultTeamImageUrl if true gets the default team image url
- * @param stateFilter allowed values are [all, createPending, deleted, deleting, new, unchanged, wellFormed]
- * @return array of projects {@link Projects}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Projects getProjects(Integer skip, Integer top, Number continuationToken,
- Boolean getDefaultTeamImageUrl, ProjectState stateFilter) throws AzDException {
-
- HashMap q = new HashMap<>() {{
- put("$skip", skip);
- put("$top", top);
- put("continuationToken", continuationToken);
- put("getDefaultTeamImageUrl", getDefaultTeamImageUrl);
- put("stateFilter", stateFilter);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, CORE, null,
- AREA, null, null, ApiVersion.PROJECT, q, null, null);
-
- return MAPPER.mapJsonResponse(r, Projects.class);
- }
-
- /**
- * Update an existing project's name, abbreviation, description, or restore a project.
- *
- * @param projectId pass the project id
- * @param projectParameters HashMap of project parameters to be updated.
- *
- * @return an object or team project with url
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public OperationReference updateProject(String projectId, Project projectParameters) throws AzDException {
-
- String r = send(RequestMethod.PATCH, CONNECTION, CORE, null,
- AREA, projectId, null, ApiVersion.PROJECT, null, projectParameters, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, OperationReference.class);
- }
-
- /**
- * Create a team in a team project.
- *
- * @param projectName project name or GUID
- * @param teamName pass the team name
- * @return returns web api object
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public WebApiTeam createTeam(String projectName, String teamName) throws AzDException {
-
- HashMap h = new HashMap<>() {{
- put("name", teamName);
- }};
-
- String r = send(RequestMethod.POST, CONNECTION, CORE, null,
- AREA, projectName, "teams", ApiVersion.PROJECT_TEAMS, null, h, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, WebApiTeam.class);
- }
-
- /**
- * Delete a team.
- *
- * @param projectName pass the project name or id
- * @param teamName pass the team name
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Void deleteTeam(String projectName, String teamName) throws AzDException {
- try {
- String r = send(RequestMethod.DELETE, CONNECTION, CORE, null,
- AREA, projectName, "teams/" + teamName, ApiVersion.PROJECT_TEAMS, null, null, null);
- if (!r.isEmpty()) MAPPER.mapJsonResponse(r, Map.class);
- } catch (AzDException e) {
- throw e;
- }
- return null;
- }
-
- /**
- * Get a specific team.
- *
- * @param projectName pass the project name or id
- * @param teamName pass the team name
- * @return team object
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public WebApiTeam getTeam(String projectName, String teamName) throws AzDException {
-
- String r = send(RequestMethod.GET, CONNECTION, CORE, null,
- AREA, projectName, "teams/" + teamName, ApiVersion.PROJECT_TEAMS, null, null, null);
-
- return MAPPER.mapJsonResponse(r, WebApiTeam.class);
- }
-
- /**
- * Get a specific team.
- *
- * @param projectName pass the project name or id
- * @param teamName pass the team name
- * @param expandIdentity if true gets the identity object
- * @return team object
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public WebApiTeam getTeam(String projectName, String teamName, boolean expandIdentity) throws AzDException {
-
- HashMap q = new HashMap<>() {{
- put("$expandIdentity", expandIdentity);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, CORE, null,
- AREA, projectName, "teams/" + teamName, ApiVersion.PROJECT_TEAMS, q, null, null);
-
- return MAPPER.mapJsonResponse(r, WebApiTeam.class);
- }
-
- /**
- * Get a list of all teams.
- *
- * @return array of team
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public WebApiTeams getTeams() throws AzDException {
-
- String r = send(RequestMethod.GET, CONNECTION, CORE, null,
- "teams", null, null, ApiVersion.PROJECT_TEAMS, null, null, null);
- return MAPPER.mapJsonResponse(r, WebApiTeams.class);
- }
-
- /**
- * Get a list of all teams.
- *
- * @param expandIdentity if true gets the identity object
- * @param mine if true gets the team to which user has access to
- * @param skip pass to skip number of teams
- * @param top pass to retrieve number of teams
- * @return array of team
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public WebApiTeams getTeams(boolean expandIdentity, boolean mine, int skip, int top) throws AzDException {
-
- HashMap q = new HashMap<>() {{
- put("$expandIdentity", expandIdentity);
- put("$mine", mine);
- put("$skip", skip);
- put("$top", top);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, CORE, null,
- "teams", null, null, ApiVersion.PROJECT_TEAMS, q, null, null);
-
- return MAPPER.mapJsonResponse(r, WebApiTeams.class);
- }
-
- /**
- * Update a team's name and/or description.
- *
- * @param projectName The name or ID (GUID) of the team project containing the team to update.
- * @param teamName The name or ID of the team to update.
- * @param description provide the description for your team to update
- * @return team object {@link WebApiTeam}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public WebApiTeam updateTeams(String projectName, String teamName, String description) throws AzDException {
-
- HashMap h = new HashMap<>() {{
- put("name", teamName);
- put("description", description);
- }};
-
- String r = send(RequestMethod.PATCH, CONNECTION, CORE, null,
- AREA, projectName, "teams/" + teamName, ApiVersion.PROJECT_TEAMS, null, h, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, WebApiTeam.class);
- }
-
- /**
- * Call un-published API feature to fetch project service feature state.
- * See {@link FeatureManagement} for current list of features.
- * Besides an 'enabled' and 'disabled' state, there is also an undefined state, hence the Optional return wrapper
- *
- * @param projectId project identifier
- * @param feature FeatureManagement enum type for which to return state
- * @return Optional wrapped boolean, empty if state is undefined
- * @throws AzDException Default Api Exception handler
- */
- @Override
- public Optional getFeatureState(String projectId, FeatureManagement feature) throws AzDException {
- String r = send(RequestMethod.GET, CONNECTION, null, null,
- "FeatureManagement/FeatureStates/host/project", projectId, feature.getFeatureId(), ApiVersion.FEATURE_MANAGEMENT,
- null, null, null);
-
- return MAPPER.mapJsonResponse(r, ProjectFeature.class).getStateAsBoolean();
- }
-
- /**
- * Set project feature state for project service
- * See {@link FeatureManagement} for list of features
- *
- * @param projectId project identifier
- * @param feature enum value for feature to enable or disable
- * @param state enable or disable feature
- * @return object containing feature id and state
- * @throws AzDException Default Api Exception handler
- */
- @Override
- public ProjectFeature featureToggle(String projectId, FeatureManagement feature, boolean state) throws AzDException {
- LinkedHashMap b = new LinkedHashMap<>() {{
- put("featureId", feature.getFeatureId());
- put("scope", new LinkedHashMap<>() {{
- put("settingScope", "project");
- put("userScoped", false);
- }});
- put("state", state ? 1 : 0);
- }};
- String r = send(RequestMethod.PATCH, CONNECTION, null, null,
- "FeatureManagement/FeatureStates/host/project", projectId, feature.getFeatureId(), ApiVersion.FEATURE_MANAGEMENT,
- null, b, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, ProjectFeature.class);
- }
-}
\ No newline at end of file
diff --git a/azd/src/main/java/org/azd/core/projects/ProjectsRequestBuilder.java b/azd/src/main/java/org/azd/core/projects/ProjectsRequestBuilder.java
index dd381e81..339c518a 100644
--- a/azd/src/main/java/org/azd/core/projects/ProjectsRequestBuilder.java
+++ b/azd/src/main/java/org/azd/core/projects/ProjectsRequestBuilder.java
@@ -127,6 +127,9 @@ public CompletableFuture getAsync(String projectId, Consumer getAsync() throws AzDException {
+ if(accessTokenCredential.getProjectName() == null || accessTokenCredential.getProjectName().isEmpty()) {
+ throw new AzDException("Project name is null or empty.");
+ }
return builder()
.serviceEndpoint("projectId", accessTokenCredential.getProjectName())
.build()
@@ -261,6 +264,10 @@ public Project get(String projectId, Consumer requestConfi
* @throws AzDException Default Api Exception handler.
*/
public Project get() throws AzDException {
+ if(accessTokenCredential.getProjectName() == null || accessTokenCredential.getProjectName().isEmpty()) {
+ throw new AzDException("Project name is null or empty.");
+ }
+
return builder()
.serviceEndpoint("projectId", accessTokenCredential.getProjectName())
.build()
diff --git a/azd/src/main/java/org/azd/distributedtask/DistributedTaskApi.java b/azd/src/main/java/org/azd/distributedtask/DistributedTaskApi.java
deleted file mode 100644
index 3ac6aece..00000000
--- a/azd/src/main/java/org/azd/distributedtask/DistributedTaskApi.java
+++ /dev/null
@@ -1,846 +0,0 @@
-package org.azd.distributedtask;
-
-import org.azd.common.ApiVersion;
-import org.azd.connection.Connection;
-import org.azd.core.CoreApi;
-import org.azd.distributedtask.types.*;
-import org.azd.enums.*;
-import org.azd.exceptions.AzDException;
-import org.azd.helpers.JsonMapper;
-import org.azd.interfaces.DistributedTaskDetails;
-import org.azd.release.types.ProjectReference;
-import org.azd.utils.AzDAsyncApi;
-
-import java.util.*;
-
-import static org.azd.utils.RestClient.send;
-
-/**
- * DistributedTaskApi class to manage Agents, Deployment groups, Environments and Variable groups API
- */
-public class DistributedTaskApi extends AzDAsyncApi implements DistributedTaskDetails {
- /**
- * Connection object
- */
- private final Connection CONNECTION;
- private final JsonMapper MAPPER = new JsonMapper();
- private final String AREA = "distributedtask";
- private final String DISTRIBUTEDTASK = "a85b8835-c1a1-4aac-ae97-1c3d0ba72dbd";
-
- /**
- * Pass the connection object
- *
- * @param connection Connection object
- */
- public DistributedTaskApi(Connection connection) {
- this.CONNECTION = connection;
- }
-
- /**
- * Delete an agent.
- *
- * @param poolId The pool ID to remove the agent from
- * @param agentId The agent ID to remove
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Void deleteAgent(int poolId, int agentId) throws AzDException {
- try {
- String r = send(RequestMethod.DELETE, CONNECTION, DISTRIBUTEDTASK, null,
- AREA + "/pools", poolId + "/agents/" + agentId, null, ApiVersion.DISTRIBUTED_TASK,
- null, null, null);
-
- if (!r.isEmpty()) MAPPER.mapJsonResponse(r, Map.class);
- } catch (AzDException e) {
- throw e;
- }
- return null;
- }
-
- /**
- * Get information about an agent.
- *
- * @param poolId The agent pool containing the agent
- * @param agentId The agent ID to get information about
- * @return A TaskAgent object {@link TaskAgent}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public TaskAgent getAgent(int poolId, int agentId) throws AzDException {
- String r = send(RequestMethod.GET, CONNECTION, DISTRIBUTEDTASK, null,
- AREA + "/pools", poolId + "/agents/" + agentId, null, ApiVersion.DISTRIBUTED_TASK,
- null, null, null);
-
- return MAPPER.mapJsonResponse(r, TaskAgent.class);
- }
-
- /**
- * Get information about an agent.
- *
- * @param poolId The agent pool containing the agent
- * @param agentId The agent ID to get information about
- * @param includeAssignedRequest Whether to include details about the agent's current work
- * @param includeCapabilities Whether to include the agent's capabilities in the response
- * @param includeLastCompletedRequest Whether to include details about the agents' most recent completed work
- * @param propertyFilters Filter which custom properties will be returned
- * @return A TaskAgent object {@link TaskAgent}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public TaskAgent getAgent(int poolId, int agentId, boolean includeAssignedRequest, boolean includeCapabilities,
- boolean includeLastCompletedRequest, String[] propertyFilters) throws AzDException {
- var q = new HashMap() {{
- put("includeAssignedRequest", includeAssignedRequest);
- put("includeCapabilities", includeCapabilities);
- put("includeLastCompletedRequest", includeLastCompletedRequest);
- put("propertyFilters", String.join(",", propertyFilters));
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, DISTRIBUTEDTASK, null,
- AREA + "/pools", poolId + "/agents/" + agentId, null, ApiVersion.DISTRIBUTED_TASK, q, null, null);
-
- return MAPPER.mapJsonResponse(r, TaskAgent.class);
- }
-
- /**
- * Get a list of agents.
- *
- * @param poolId The agent pool containing the agents
- * @return TaskAgents object {@link TaskAgents}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public TaskAgents getAgents(int poolId) throws AzDException {
- String r = send(RequestMethod.GET, CONNECTION, DISTRIBUTEDTASK, null,
- AREA + "/pools", poolId + "/agents", null, ApiVersion.DISTRIBUTED_TASK, null, null, null);
-
- return MAPPER.mapJsonResponse(r, TaskAgents.class);
- }
-
- /**
- * Get a list of agents.
- *
- * @param poolId The agent pool containing the agents
- * @param agentName Filter on agent name
- * @param demands Filter by demands the agents can satisfy
- * @param includeAssignedRequest Whether to include details about the agents' current work
- * @param includeCapabilities Whether to include the agents' capabilities in the response
- * @param includeLastCompletedRequest Whether to include details about the agents' most recent completed work
- * @param propertyFilters Filter which custom properties will be returned
- * @return TaskAgents object {@link TaskAgents}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public TaskAgents getAgents(int poolId, String agentName, String[] demands, boolean includeAssignedRequest,
- boolean includeCapabilities, boolean includeLastCompletedRequest, String[] propertyFilters)
- throws AzDException {
- var q = new HashMap() {{
- put("agentName", agentName);
- put("demands", String.join(",", demands));
- put("includeAssignedRequest", includeAssignedRequest);
- put("includeCapabilities", includeCapabilities);
- put("includeLastCompletedRequest", includeLastCompletedRequest);
- put("propertyFilters", String.join(",", propertyFilters));
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, DISTRIBUTEDTASK, null,
- AREA + "/pools", poolId + "/agents", null, ApiVersion.DISTRIBUTED_TASK, q, null, null);
-
- return MAPPER.mapJsonResponse(r, TaskAgents.class);
- }
-
- /**
- * Update agent details.
- *
- * @param poolId The agent pool to use
- * @param agentId The agent to update
- * @param requestBody Map of request body.
- *
- * Visit https://docs.microsoft.com/en-us/rest/api/azure/devops/distributedtask/agents/update?view=azure-devops-rest-7.1#request-body for more details.
- *
- * @return A TaskAgent object {@link TaskAgent}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public TaskAgent updateAgent(int poolId, int agentId, TaskAgent requestBody) throws AzDException {
- String r = send(RequestMethod.PATCH, CONNECTION, DISTRIBUTEDTASK, null,
- AREA + "/pools", poolId + "/agents/" + agentId, null, ApiVersion.DISTRIBUTED_TASK,
- null, requestBody, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, TaskAgent.class);
- }
-
- /**
- * Create a deployment group.
- *
- * @param name Name of the deployment group.
- * @param description Description of the deployment group.
- * @return Deployment group object {@link DeploymentGroup}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public DeploymentGroup addDeploymentGroup(String name, String description) throws AzDException {
- var requestBody = new HashMap() {{
- put("name", name);
- put("description", description);
- }};
-
- String r = send(RequestMethod.POST, CONNECTION, DISTRIBUTEDTASK, CONNECTION.getProject(),
- AREA + "/deploymentgroups", null, null, ApiVersion.DISTRIBUTED_TASK,
- null, requestBody, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, DeploymentGroup.class);
- }
-
- /**
- * Create a deployment group.
- *
- * @param name Name of the deployment group.
- * @param description Description of the deployment group.
- * @param poolId Identifier of the deployment pool in which deployment agents are registered.
- * @return Deployment group object {@link DeploymentGroup}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public DeploymentGroup addDeploymentGroup(String name, String description, int poolId) throws AzDException {
- var requestBody = new HashMap() {{
- put("name", name);
- put("description", description);
- put("poolId", poolId);
- }};
-
- String r = send(RequestMethod.POST, CONNECTION, DISTRIBUTEDTASK, CONNECTION.getProject(),
- AREA + "/deploymentgroups", null, null, ApiVersion.DISTRIBUTED_TASK,
- null, requestBody, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, DeploymentGroup.class);
- }
-
- /**
- * Delete a deployment group.
- *
- * @param deploymentGroupId ID of the deployment group to be deleted.
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Void deleteDeploymentGroup(int deploymentGroupId) throws AzDException {
- try {
- String r = send(RequestMethod.DELETE, CONNECTION, DISTRIBUTEDTASK, CONNECTION.getProject(),
- AREA + "/deploymentgroups", Integer.toString(deploymentGroupId), null, ApiVersion.DISTRIBUTED_TASK, null, null, null);
-
- if (!r.isEmpty()) MAPPER.mapJsonResponse(r, Map.class);
- } catch (AzDException e) {
- throw e;
- }
- return null;
- }
-
- /**
- * Get a deployment group by its ID.
- *
- * @param deploymentGroupId ID of the deployment group to be deleted.
- * @return Deployment group object {@link DeploymentGroup}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public DeploymentGroup getDeploymentGroup(int deploymentGroupId) throws AzDException {
- String r = send(RequestMethod.GET, CONNECTION, DISTRIBUTEDTASK, CONNECTION.getProject(),
- AREA + "/deploymentgroups", Integer.toString(deploymentGroupId), null, ApiVersion.DISTRIBUTED_TASK, null, null, null);
-
- return MAPPER.mapJsonResponse(r, DeploymentGroup.class);
- }
-
- /**
- * Get a deployment group by its ID.
- *
- * @param deploymentGroupId ID of the deployment group to be deleted.
- * @param expand Include these additional details in the returned object.
- * @param actionFilter Get the deployment group only if this action can be performed on it.
- * @return Deployment group object {@link DeploymentGroup}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public DeploymentGroup getDeploymentGroup(int deploymentGroupId, DeploymentGroupExpands expand, DeploymentGroupActionFilter actionFilter)
- throws AzDException {
- var q = new HashMap() {{
- put("$expand", expand.toString().toLowerCase());
- put("actionFilter", actionFilter.toString().toLowerCase());
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, DISTRIBUTEDTASK, CONNECTION.getProject(),
- AREA + "/deploymentgroups", Integer.toString(deploymentGroupId), null, ApiVersion.DISTRIBUTED_TASK, q, null, null);
-
- return MAPPER.mapJsonResponse(r, DeploymentGroup.class);
- }
-
- /**
- * Get a list of deployment groups by name or IDs.
- *
- * @return Deployment groups object {@link DeploymentGroups}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public DeploymentGroups getDeploymentGroups() throws AzDException {
- String r = send(RequestMethod.GET, CONNECTION, DISTRIBUTEDTASK, CONNECTION.getProject(),
- AREA + "/deploymentgroups", null, null, ApiVersion.DISTRIBUTED_TASK, null, null, null);
-
- return MAPPER.mapJsonResponse(r, DeploymentGroups.class);
- }
-
- /**
- * Get a list of deployment groups by name or IDs.
- *
- * @param top Maximum number of deployment groups to return. Default is 1000.
- * @return Deployment groups object {@link DeploymentGroups}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public DeploymentGroups getDeploymentGroups(int top) throws AzDException {
- var q = new HashMap() {{
- put("$top", top);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, DISTRIBUTEDTASK, CONNECTION.getProject(),
- AREA + "/deploymentgroups", null, null, ApiVersion.DISTRIBUTED_TASK, q, null, null);
-
- return MAPPER.mapJsonResponse(r, DeploymentGroups.class);
- }
-
- /**
- * Get a list of deployment groups by name or IDs.
- *
- * @param ids Array of Id of deployment groups.
- * @return Deployment groups object {@link DeploymentGroups}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public DeploymentGroups getDeploymentGroups(int[] ids) throws AzDException {
- var q = new HashMap() {{
- put("ids", intArrayToString(ids));
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, DISTRIBUTEDTASK, CONNECTION.getProject(),
- AREA + "/deploymentgroups", null, null, ApiVersion.DISTRIBUTED_TASK, q, null, null);
-
- return MAPPER.mapJsonResponse(r, DeploymentGroups.class);
- }
-
- /**
- * Get a list of deployment groups by name or IDs.
- *
- * @param name Name of the deployment group.
- * @return Deployment groups object {@link DeploymentGroups}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public DeploymentGroups getDeploymentGroups(String name) throws AzDException {
- var q = new HashMap() {{
- put("name", name);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, DISTRIBUTEDTASK, CONNECTION.getProject(),
- AREA + "/deploymentgroups", null, null, ApiVersion.DISTRIBUTED_TASK, q, null, null);
-
- return MAPPER.mapJsonResponse(r, DeploymentGroups.class);
- }
-
- /**
- * Get a list of deployment groups by name or IDs.
- *
- * @param expand Include these additional details in the returned objects. {@link DeploymentGroupExpands}
- * @return Deployment groups object {@link DeploymentGroups}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public DeploymentGroups getDeploymentGroups(DeploymentGroupExpands expand) throws AzDException {
- var q = new HashMap() {{
- put("$expand", expand.toString().toLowerCase());
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, DISTRIBUTEDTASK, CONNECTION.getProject(),
- AREA + "/deploymentgroups", null, null, ApiVersion.DISTRIBUTED_TASK, q, null, null);
-
- return MAPPER.mapJsonResponse(r, DeploymentGroups.class);
- }
-
- /**
- * Get a list of deployment groups by name or IDs.
- *
- * @param expand Include these additional details in the returned objects. {@link DeploymentGroupExpands}
- * @param top Maximum number of deployment groups to return. Default is 1000.
- * @param actionFilter Get only deployment groups on which this action can be performed. {@link DeploymentGroupActionFilter}
- * @param continuationToken Get deployment groups with names greater than this continuationToken lexicographically.
- * @param ids Comma separated list of IDs of the deployment groups.
- * @param name Name of the deployment group.
- * @return Deployment groups object {@link DeploymentGroups}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public DeploymentGroups getDeploymentGroups(DeploymentGroupExpands expand, int top, DeploymentGroupActionFilter actionFilter,
- String continuationToken, int[] ids, String name) throws AzDException {
- var q = new HashMap() {{
- put("$expand", expand.toString().toLowerCase());
- put("$top", top);
- put("actionFilter", actionFilter.toString().toLowerCase());
- put("continuationToken", continuationToken);
- put("ids", intArrayToString(ids));
- put("name", name);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, DISTRIBUTEDTASK, CONNECTION.getProject(),
- AREA + "/deploymentgroups", null, null, ApiVersion.DISTRIBUTED_TASK, q, null, null);
-
- return MAPPER.mapJsonResponse(r, DeploymentGroups.class);
- }
-
- /**
- * Update a deployment group.
- *
- * @param deploymentGroupId ID of the deployment group.
- * @param name Name of the deployment group.
- * @param description Description of the deployment group.
- * @return Deployment group object {@link DeploymentGroup}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public DeploymentGroup updateDeploymentGroup(int deploymentGroupId, String name, String description) throws AzDException {
- var requestBody = new HashMap() {{
- put("name", name);
- put("description", description);
- }};
-
- String r = send(RequestMethod.PATCH, CONNECTION, DISTRIBUTEDTASK, CONNECTION.getProject(),
- AREA + "/deploymentgroups", Integer.toString(deploymentGroupId), null, ApiVersion.DISTRIBUTED_TASK,
- null, requestBody, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, DeploymentGroup.class);
- }
-
- /**
- * Create an environment.
- *
- * @param name Name of the environment.
- * @param description Description of the environment.
- * @return Environment instance {@link EnvironmentInstance}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public EnvironmentInstance addEnvironment(String name, String description) throws AzDException {
- var requestBody = new HashMap() {{
- put("name", name);
- put("description", description);
- }};
-
- String r = send(RequestMethod.POST, CONNECTION, DISTRIBUTEDTASK, CONNECTION.getProject(),
- AREA + "/environments", null, null, ApiVersion.DISTRIBUTED_TASK, null, requestBody, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, EnvironmentInstance.class);
- }
-
- /**
- * Delete the specified environment.
- *
- * @param environmentId ID of the environment.
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public Void deleteEnvironment(int environmentId) throws AzDException {
- try {
- String r = send(RequestMethod.DELETE, CONNECTION, DISTRIBUTEDTASK, CONNECTION.getProject(),
- AREA + "/environments", Integer.toString(environmentId), null, ApiVersion.DISTRIBUTED_TASK, null, null, null);
-
- if (!r.isEmpty()) MAPPER.mapJsonResponse(r, Map.class);
- } catch (AzDException e) {
- throw e;
- }
- return null;
- }
-
- /**
- * Get an environment by its ID.
- *
- * @param environmentId ID of the environment.
- * @return Environment instance {@link EnvironmentInstance}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public EnvironmentInstance getEnvironment(int environmentId) throws AzDException {
- String r = send(RequestMethod.GET, CONNECTION, DISTRIBUTEDTASK, CONNECTION.getProject(),
- AREA + "/environments", Integer.toString(environmentId), null, ApiVersion.DISTRIBUTED_TASK,
- null, null, null);
-
- return MAPPER.mapJsonResponse(r, EnvironmentInstance.class);
- }
-
- /**
- * Get an environment by its ID.
- *
- * @param environmentId ID of the environment.
- * @param expands Include these additional details in the returned objects. {@link EnvironmentExpands}
- * @return Environment instance {@link EnvironmentInstance}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public EnvironmentInstance getEnvironment(int environmentId, EnvironmentExpands expands) throws AzDException {
- var q = new HashMap() {{
- put("expands", expands.toString().toLowerCase());
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, DISTRIBUTEDTASK, CONNECTION.getProject(),
- AREA + "/environments", Integer.toString(environmentId), null, ApiVersion.DISTRIBUTED_TASK, q, null, null);
-
- return MAPPER.mapJsonResponse(r, EnvironmentInstance.class);
- }
-
- /**
- * Get all environments.
- *
- * @return Environment instances array {@link EnvironmentInstances}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public EnvironmentInstances getEnvironments() throws AzDException {
- String r = send(RequestMethod.GET, CONNECTION, DISTRIBUTEDTASK, CONNECTION.getProject(),
- AREA + "/environments", null, null, ApiVersion.DISTRIBUTED_TASK, null, null, null);
-
- return MAPPER.mapJsonResponse(r, EnvironmentInstances.class);
- }
-
- /**
- * Get all environments.
- *
- * @param top Top environments to list
- * @return Environment instances array {@link EnvironmentInstances}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public EnvironmentInstances getEnvironments(int top) throws AzDException {
- var q = new HashMap() {{
- put("$top", top);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, DISTRIBUTEDTASK, CONNECTION.getProject(),
- AREA + "/environments", null, null, ApiVersion.DISTRIBUTED_TASK, q, null, null);
-
- return MAPPER.mapJsonResponse(r, EnvironmentInstances.class);
- }
-
- /**
- * Get all environments.
- *
- * @param name Name of the environment.
- * @return Environment instances array {@link EnvironmentInstances}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public EnvironmentInstances getEnvironments(String name) throws AzDException {
- var q = new HashMap() {{
- put("name", name);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, DISTRIBUTEDTASK, CONNECTION.getProject(),
- AREA + "/environments", null, null, ApiVersion.DISTRIBUTED_TASK, q, null, null);
-
- return MAPPER.mapJsonResponse(r, EnvironmentInstances.class);
- }
-
- /**
- * Get all environments.
- *
- * @param top Top environments to list.
- * @param continuationToken Get the list of environments paginated.
- * @param name Name of the environment.
- * @return Environment instances array {@link EnvironmentInstances}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public EnvironmentInstances getEnvironments(int top, String continuationToken, String name) throws AzDException {
- var q = new HashMap() {{
- put("$top", top);
- put("continuationToken", continuationToken);
- put("name", name);
- }};
-
- String r = send(RequestMethod.GET, CONNECTION, DISTRIBUTEDTASK, CONNECTION.getProject(),
- AREA + "/environments", null, null, ApiVersion.DISTRIBUTED_TASK, q, null, null);
-
- return MAPPER.mapJsonResponse(r, EnvironmentInstances.class);
- }
-
- /**
- * Update the specified environment.
- *
- * @param environmentId ID of the environment.
- * @param name Name of the environment.
- * @param description Description of the environment.
- * @return Environment instance {@link EnvironmentInstance}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public EnvironmentInstance updateEnvironment(int environmentId, String name, String description) throws AzDException {
- var requestBody = new HashMap() {{
- put("name", name);
- put("description", description);
- }};
-
- String r = send(RequestMethod.PATCH, CONNECTION, DISTRIBUTEDTASK, CONNECTION.getProject(),
- AREA + "/environments", Integer.toString(environmentId), null, ApiVersion.DISTRIBUTED_TASK,
- null, requestBody, CustomHeader.JSON_CONTENT_TYPE);
-
- return MAPPER.mapJsonResponse(r, EnvironmentInstance.class);
- }
-
- /**
- * Add a variable group.
- *
- * @param variableGroupDefinition Variable group definition {@link VariableGroupDefinition}
- * @return Variable group {@link VariableGroup}
- * @throws AzDException Default Api Exception handler.
- */
- @Override
- public VariableGroup addVariableGroup(VariableGroupDefinition variableGroupDefinition)
- throws AzDException {
- var ref = new VariableGroupProjectReference();
- ref.setName(variableGroupDefinition.getName());
- ref.setDescription(variableGroupDefinition.getDescription());
- ref.setProjectReference(variableGroupDefinition.getProjectReference());
-
- List