diff --git a/eng/code-quality-reports/src/main/resources/checkstyle/checkstyle-suppressions.xml b/eng/code-quality-reports/src/main/resources/checkstyle/checkstyle-suppressions.xml index 909932e441e6..e23b0fc4fdda 100755 --- a/eng/code-quality-reports/src/main/resources/checkstyle/checkstyle-suppressions.xml +++ b/eng/code-quality-reports/src/main/resources/checkstyle/checkstyle-suppressions.xml @@ -392,7 +392,7 @@ + files="com.azure.core.management.implementation.polling.PollOperation.java"/> diff --git a/sdk/core/azure-core-management/src/main/java/com/azure/core/management/annotations/AzureHost.java b/sdk/core/azure-core-management/src/main/java/com/azure/core/management/annotations/AzureHost.java deleted file mode 100644 index f65ef4c1ba73..000000000000 --- a/sdk/core/azure-core-management/src/main/java/com/azure/core/management/annotations/AzureHost.java +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.azure.core.management.annotations; - -import com.azure.core.annotation.Host; -import com.azure.core.management.AzureEnvironment; -import com.azure.core.management.AzureEnvironment.Endpoint; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.TYPE; - -/** - * An extension to {@link Host}, allowing endpoints - * of {@link AzureEnvironment} to be specified instead of string - * host names. This allows self adaptive base URLs based on the environment the - * client is running in. - * - * Example 1: Azure Resource Manager - * - * {@literal @}AzureHost(AzureEnvironment.Endpoint.RESOURCE_MANAGER) - * interface VirtualMachinesService { - * {@literal @}GET("subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft - * .Compute/virtualMachines/{vmName}") - * VirtualMachine getByResourceGroup(@PathParam("resourceGroupName") String rgName, @PathParam("vmName") String - * vmName, @PathParam("subscriptionId") String subscriptionId); - * } - * - * Example 2: Azure Key Vault - * - * {@literal @}AzureHost(AzureEnvironment.Endpoint.KEY_VAULT) - * interface KeyVaultService { - * {@literal @}GET("secrets/{secretName}") - * Secret getSecret(@HostParam String vaultName, @PathParam("secretName") String secretName); - * } - */ -@Target(value = {TYPE}) -@Retention(RetentionPolicy.RUNTIME) -public @interface AzureHost { - /** - * The endpoint that all REST APIs within the Swagger interface will send their requests to. - * @return The endpoint that all REST APIs within the Swagger interface will send their requests - * to. - */ - String value() default ""; - - /** - * The endpoint that all REST APIs within the Swagger interface will send their requests to. - * @return The endpoint that all REST APIs within the Swagger interface will send their requests - * to. - */ - AzureEnvironment.Endpoint endpoint() default Endpoint.RESOURCE_MANAGER; -} diff --git a/sdk/core/azure-core-management/src/main/java/com/azure/core/management/annotations/package-info.java b/sdk/core/azure-core-management/src/main/java/com/azure/core/management/annotations/package-info.java deleted file mode 100644 index cdac0bd6f9e4..000000000000 --- a/sdk/core/azure-core-management/src/main/java/com/azure/core/management/annotations/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -/** - * Package containing annotations used on Swagger generated interfaces that are specific to Azure ARM REST APIs. - */ -package com.azure.core.management.annotations; diff --git a/sdk/core/azure-core-management/src/main/java/com/azure/core/management/implementation/polling/PollerFactory.java b/sdk/core/azure-core-management/src/main/java/com/azure/core/management/implementation/polling/PollOperation.java similarity index 57% rename from sdk/core/azure-core-management/src/main/java/com/azure/core/management/implementation/polling/PollerFactory.java rename to sdk/core/azure-core-management/src/main/java/com/azure/core/management/implementation/polling/PollOperation.java index ddf5eaa6dbcb..f2a4bf6e7281 100644 --- a/sdk/core/azure-core-management/src/main/java/com/azure/core/management/implementation/polling/PollerFactory.java +++ b/sdk/core/azure-core-management/src/main/java/com/azure/core/management/implementation/polling/PollOperation.java @@ -7,142 +7,28 @@ import com.azure.core.http.HttpPipeline; import com.azure.core.http.HttpRequest; import com.azure.core.http.HttpResponse; -import com.azure.core.http.rest.Response; import com.azure.core.management.polling.PollResult; -import com.azure.core.util.FluxUtil; import com.azure.core.util.logging.ClientLogger; import com.azure.core.util.polling.LongRunningOperationStatus; import com.azure.core.util.polling.PollResponse; -import com.azure.core.util.polling.PollerFlux; import com.azure.core.util.polling.PollingContext; import com.azure.core.util.serializer.SerializerAdapter; import com.azure.core.util.serializer.SerializerEncoding; -import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.io.IOException; import java.lang.reflect.Type; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.time.Duration; -import java.util.Objects; import java.util.function.BiFunction; import java.util.function.Function; /** - * Factory to create PollerFlux for Azure resource manager (ARM) long-running-operation (LRO). + * Poll operation for Azure resource manager (ARM) long-running-operation (LRO). */ -public final class PollerFactory { - private static final ClientLogger LOGGER = new ClientLogger(PollerFactory.class); +public final class PollOperation { + private static final ClientLogger LOGGER = new ClientLogger(PollOperation.class); private static final LongRunningOperationStatus LRO_CANCELLED = LongRunningOperationStatus.fromString("Cancelled", true); - /** - * Creates a PollerFlux with default ARM LRO init operation. - * - * @param serializerAdapter the serializer for any encoding and decoding - * @param pipeline the HttpPipeline for making any Http request (e.g. poll) - * @param pollResultType the type of the poll result, if no result is expecting then this should be Void.class - * @param finalResultType the type of the final result, if no result is expecting then this should be Void.class - * @param defaultPollInterval the default poll interval to use if service does not return retry-after - * @param lroInitMono the Mono on subscribe send the service request to initiate the long-running-operation - * @param the type of poll result - * @param the type of final result - * @return PollerFlux - */ - public static PollerFlux, U> create( - SerializerAdapter serializerAdapter, - HttpPipeline pipeline, - Type pollResultType, - Type finalResultType, - Duration defaultPollInterval, - Mono>> lroInitMono) { - Objects.requireNonNull(serializerAdapter, "'serializerAdapter' cannot be null."); - Objects.requireNonNull(pipeline, "'pipeline' cannot be null."); - Objects.requireNonNull(pollResultType, "'pollResultType' cannot be null."); - Objects.requireNonNull(finalResultType, "'finalResultType' cannot be null."); - Objects.requireNonNull(defaultPollInterval, "'defaultPollInterval' cannot be null."); - Objects.requireNonNull(lroInitMono, "'lroInitMono' cannot be null."); - Function>, Mono>>> defaultLroInitOperation = - context -> lroInitMono.flatMap(response -> FluxUtil.collectBytesInByteBufferStream(response.getValue()) - .map(contentBytes -> { - String content = new String(contentBytes, StandardCharsets.UTF_8); - PollingState state = PollingState.create(serializerAdapter, - response.getRequest(), - response.getStatusCode(), - response.getHeaders(), - content); - state.store(context); - T result = deserialize(serializerAdapter, content, pollResultType); - return new PollResponse<>(state.getOperationStatus(), new PollResult<>(result)); - })); - return PollerFlux.create(defaultPollInterval, - defaultLroInitOperation, - pollFunction(serializerAdapter, pipeline, pollResultType), - cancelFunction(), - fetchResultFunction(serializerAdapter, pipeline, finalResultType)); - } - - /** - * Creates a PollerFlux. - * - * @param serializerAdapter the serializer for any encoding and decoding - * @param pipeline the HttpPipeline for making any Http request (e.g. poll) - * @param pollResultType the type of the poll result, if no result is expecting then this should be Void.class - * @param finalResultType the type of the final result, if no result is expecting then this should be Void.class - * @param defaultPollInterval the default poll interval to use if service does not return retry-after - * @param lroInitOperation the function upon invoking should initiate the long-running-operation - * @param the type of poll result - * @param the type of final result - * @return PollerFlux - */ - public static PollerFlux, U> create( - SerializerAdapter serializerAdapter, - HttpPipeline pipeline, - Type pollResultType, - Type finalResultType, - Duration defaultPollInterval, - Function>, Mono>> lroInitOperation) { - Objects.requireNonNull(serializerAdapter, "'serializerAdapter' cannot be null."); - Objects.requireNonNull(pipeline, "'pipeline' cannot be null."); - Objects.requireNonNull(pollResultType, "'pollResultType' cannot be null."); - Objects.requireNonNull(finalResultType, "'finalResultType' cannot be null."); - Objects.requireNonNull(defaultPollInterval, "'defaultPollInterval' cannot be null."); - Objects.requireNonNull(lroInitOperation, "'lroInitOperation' cannot be null."); - - return new PollerFlux<>(defaultPollInterval, - lroInitOperation, - pollFunction(serializerAdapter, pipeline, pollResultType), - cancelFunction(), - fetchResultFunction(serializerAdapter, pipeline, finalResultType)); - } - - /** - * Dehydrate a PollerFlux from a string. - * - * @param serializerAdapter the serializer for any encoding and decoding - * @param pipeline the HttpPipeline for making any Http request (e.g. poll) - * @param pollResultType the type of the poll result, if no result is expecting then this should be Void.class - * @param finalResultType the type of the final result, if no result is expecting then this should be Void.class - * @param defaultPollInterval the default poll interval to use if service does not return retry-after - * @param pollingStateStr the string to dehydrate PollerFlux from - * @param the type of poll result - * @param the type of final result - * @return PollerFlux - */ - public static PollerFlux, U> create(SerializerAdapter serializerAdapter, - HttpPipeline pipeline, - Type pollResultType, - Type finalResultType, - Duration defaultPollInterval, - String pollingStateStr) { - return create(serializerAdapter, pipeline, pollResultType, finalResultType, defaultPollInterval, - context -> { - PollingState.from(serializerAdapter, pollingStateStr).store(context); - return Mono.empty(); - }); - } - /** * Get a Function that polls provisioning state of ARM resource. * @@ -152,7 +38,7 @@ public static PollerFlux, U> create(SerializerAdapter seria * @param the type of poll result type * @return the ARM poll function */ - private static Function>, Mono>>> pollFunction( + public static Function>, Mono>>> pollFunction( SerializerAdapter serializerAdapter, HttpPipeline pipeline, Type pollResultType) { @@ -198,7 +84,7 @@ private static Function>, Mono the type of poll result type * @return cancel Function */ - private static + public static BiFunction>, PollResponse>, Mono>> cancelFunction() { return new BiFunction>, PollResponse>, Mono>>() { @Override @@ -219,7 +105,7 @@ public Mono> apply(PollingContext> context, * @param the poll result type * @return retrieve final LRO result Function */ - private static Function>, Mono> fetchResultFunction( + public static Function>, Mono> fetchResultFunction( SerializerAdapter serializerAdapter, HttpPipeline pipeline, Type finalResultType) { @@ -307,7 +193,7 @@ private static Mono doSinglePoll(HttpPipeline pipeline, PollingSta * @return decoded value */ @SuppressWarnings("unchecked") - private static U deserialize(SerializerAdapter serializerAdapter, String value, Type type) { + public static U deserialize(SerializerAdapter serializerAdapter, String value, Type type) { if (value == null || value.equalsIgnoreCase("")) { LOGGER.info("Ignoring decoding of null or empty value to:" + type.getTypeName()); return null; diff --git a/sdk/core/azure-core-management/src/main/java/com/azure/core/management/implementation/polling/PollingState.java b/sdk/core/azure-core-management/src/main/java/com/azure/core/management/implementation/polling/PollingState.java index 56281a8da6ff..33bce315b5bc 100644 --- a/sdk/core/azure-core-management/src/main/java/com/azure/core/management/implementation/polling/PollingState.java +++ b/sdk/core/azure-core-management/src/main/java/com/azure/core/management/implementation/polling/PollingState.java @@ -170,7 +170,7 @@ public void store(PollingContext context) { /** * @return the current status of the long-running-operation. */ - LongRunningOperationStatus getOperationStatus() { + public LongRunningOperationStatus getOperationStatus() { switch (this.pollingType) { case AZURE_ASYNC_OPERATION_POLL: return toLongRunningOperationStatus(this.azureAsyncOperationData.getProvisioningState()); diff --git a/sdk/core/azure-core-management/src/main/java/com/azure/core/management/polling/PollResult.java b/sdk/core/azure-core-management/src/main/java/com/azure/core/management/polling/PollResult.java index ca57afcbad15..42f1c5c00b7b 100644 --- a/sdk/core/azure-core-management/src/main/java/com/azure/core/management/polling/PollResult.java +++ b/sdk/core/azure-core-management/src/main/java/com/azure/core/management/polling/PollResult.java @@ -38,7 +38,7 @@ public PollResult(Error error) { * * @return the value */ - public T value() { + public T getValue() { return this.value; } @@ -47,7 +47,7 @@ public T value() { * * @return the error */ - public Error error() { + public Error getError() { return this.error; } diff --git a/sdk/core/azure-core-management/src/main/java/com/azure/core/management/polling/PollerFactory.java b/sdk/core/azure-core-management/src/main/java/com/azure/core/management/polling/PollerFactory.java new file mode 100644 index 000000000000..ec034ea1b634 --- /dev/null +++ b/sdk/core/azure-core-management/src/main/java/com/azure/core/management/polling/PollerFactory.java @@ -0,0 +1,135 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.core.management.polling; + +import com.azure.core.http.HttpPipeline; +import com.azure.core.http.rest.Response; +import com.azure.core.management.implementation.polling.PollOperation; +import com.azure.core.management.implementation.polling.PollingState; +import com.azure.core.util.FluxUtil; +import com.azure.core.util.polling.PollResponse; +import com.azure.core.util.polling.PollerFlux; +import com.azure.core.util.polling.PollingContext; +import com.azure.core.util.serializer.SerializerAdapter; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.lang.reflect.Type; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.time.Duration; +import java.util.Objects; +import java.util.function.Function; + +/** + * Factory to create PollerFlux for Azure resource manager (ARM) long-running-operation (LRO). + */ +public final class PollerFactory { + + /** + * Creates a PollerFlux with default ARM LRO init operation. + * + * @param serializerAdapter the serializer for any encoding and decoding + * @param pipeline the HttpPipeline for making any Http request (e.g. poll) + * @param pollResultType the type of the poll result, if no result is expecting then this should be Void.class + * @param finalResultType the type of the final result, if no result is expecting then this should be Void.class + * @param defaultPollInterval the default poll interval to use if service does not return retry-after + * @param lroInitMono the Mono on subscribe send the service request to initiate the long-running-operation + * @param the type of poll result + * @param the type of final result + * @return PollerFlux + */ + public static PollerFlux, U> create( + SerializerAdapter serializerAdapter, + HttpPipeline pipeline, + Type pollResultType, + Type finalResultType, + Duration defaultPollInterval, + Mono>> lroInitMono) { + Objects.requireNonNull(serializerAdapter, "'serializerAdapter' cannot be null."); + Objects.requireNonNull(pipeline, "'pipeline' cannot be null."); + Objects.requireNonNull(pollResultType, "'pollResultType' cannot be null."); + Objects.requireNonNull(finalResultType, "'finalResultType' cannot be null."); + Objects.requireNonNull(defaultPollInterval, "'defaultPollInterval' cannot be null."); + Objects.requireNonNull(lroInitMono, "'lroInitMono' cannot be null."); + Function>, Mono>>> defaultLroInitOperation = + context -> lroInitMono.flatMap(response -> FluxUtil.collectBytesInByteBufferStream(response.getValue()) + .map(contentBytes -> { + String content = new String(contentBytes, StandardCharsets.UTF_8); + PollingState state = PollingState.create(serializerAdapter, + response.getRequest(), + response.getStatusCode(), + response.getHeaders(), + content); + state.store(context); + T result = PollOperation.deserialize(serializerAdapter, content, pollResultType); + return new PollResponse<>(state.getOperationStatus(), new PollResult<>(result)); + })); + return PollerFlux.create(defaultPollInterval, + defaultLroInitOperation, + PollOperation.pollFunction(serializerAdapter, pipeline, pollResultType), + PollOperation.cancelFunction(), + PollOperation.fetchResultFunction(serializerAdapter, pipeline, finalResultType)); + } + + /** + * Creates a PollerFlux. + * + * @param serializerAdapter the serializer for any encoding and decoding + * @param pipeline the HttpPipeline for making any Http request (e.g. poll) + * @param pollResultType the type of the poll result, if no result is expecting then this should be Void.class + * @param finalResultType the type of the final result, if no result is expecting then this should be Void.class + * @param defaultPollInterval the default poll interval to use if service does not return retry-after + * @param lroInitOperation the function upon invoking should initiate the long-running-operation + * @param the type of poll result + * @param the type of final result + * @return PollerFlux + */ + public static PollerFlux, U> create( + SerializerAdapter serializerAdapter, + HttpPipeline pipeline, + Type pollResultType, + Type finalResultType, + Duration defaultPollInterval, + Function>, Mono>> lroInitOperation) { + Objects.requireNonNull(serializerAdapter, "'serializerAdapter' cannot be null."); + Objects.requireNonNull(pipeline, "'pipeline' cannot be null."); + Objects.requireNonNull(pollResultType, "'pollResultType' cannot be null."); + Objects.requireNonNull(finalResultType, "'finalResultType' cannot be null."); + Objects.requireNonNull(defaultPollInterval, "'defaultPollInterval' cannot be null."); + Objects.requireNonNull(lroInitOperation, "'lroInitOperation' cannot be null."); + + return new PollerFlux<>(defaultPollInterval, + lroInitOperation, + PollOperation.pollFunction(serializerAdapter, pipeline, pollResultType), + PollOperation.cancelFunction(), + PollOperation.fetchResultFunction(serializerAdapter, pipeline, finalResultType)); + } + + /** + * Dehydrate a PollerFlux from a string. + * + * @param serializerAdapter the serializer for any encoding and decoding + * @param pipeline the HttpPipeline for making any Http request (e.g. poll) + * @param pollResultType the type of the poll result, if no result is expecting then this should be Void.class + * @param finalResultType the type of the final result, if no result is expecting then this should be Void.class + * @param defaultPollInterval the default poll interval to use if service does not return retry-after + * @param pollingStateStr the string to dehydrate PollerFlux from + * @param the type of poll result + * @param the type of final result + * @return PollerFlux + */ + public static PollerFlux, U> create(SerializerAdapter serializerAdapter, + HttpPipeline pipeline, + Type pollResultType, + Type finalResultType, + Duration defaultPollInterval, + String pollingStateStr) { + return create(serializerAdapter, pipeline, pollResultType, finalResultType, defaultPollInterval, + context -> { + PollingState.from(serializerAdapter, pollingStateStr).store(context); + return Mono.empty(); + }); + } +} diff --git a/sdk/core/azure-core-management/src/main/java/module-info.java b/sdk/core/azure-core-management/src/main/java/module-info.java index ae7e13c33b27..c4cad3ac196e 100644 --- a/sdk/core/azure-core-management/src/main/java/module-info.java +++ b/sdk/core/azure-core-management/src/main/java/module-info.java @@ -5,7 +5,6 @@ requires transitive com.azure.core; exports com.azure.core.management; - exports com.azure.core.management.annotations; exports com.azure.core.management.polling; exports com.azure.core.management.serializer; exports com.azure.core.management.exception; diff --git a/sdk/core/azure-core-management/src/test/java/com/azure/core/management/implementation/polling/LROPollerTests.java b/sdk/core/azure-core-management/src/test/java/com/azure/core/management/implementation/polling/LROPollerTests.java index 2c7086cd77ff..e99b0e28f17c 100644 --- a/sdk/core/azure-core-management/src/test/java/com/azure/core/management/implementation/polling/LROPollerTests.java +++ b/sdk/core/azure-core-management/src/test/java/com/azure/core/management/implementation/polling/LROPollerTests.java @@ -17,6 +17,7 @@ import com.azure.core.http.rest.RestProxy; import com.azure.core.management.Resource; import com.azure.core.management.polling.PollResult; +import com.azure.core.management.polling.PollerFactory; import com.azure.core.management.serializer.AzureJacksonAdapter; import com.azure.core.util.FluxUtil; import com.azure.core.util.polling.AsyncPollResponse; @@ -145,20 +146,20 @@ public String getName() { lroFlux.doOnNext(response -> { PollResult pollResult = response.getValue(); Assertions.assertNotNull(pollResult); - Assertions.assertNotNull(pollResult.value()); + Assertions.assertNotNull(pollResult.getValue()); onNextCallCount[0]++; if (onNextCallCount[0] == 1) { Assertions.assertEquals(response.getStatus(), LongRunningOperationStatus.IN_PROGRESS); - Assertions.assertNull(pollResult.value().getResourceId()); + Assertions.assertNull(pollResult.getValue().getResourceId()); } else if (onNextCallCount[0] == 2) { Assertions.assertEquals(response.getStatus(), LongRunningOperationStatus.IN_PROGRESS); - Assertions.assertNull(pollResult.value().getResourceId()); + Assertions.assertNull(pollResult.getValue().getResourceId()); } else if (onNextCallCount[0] == 3) { Assertions.assertEquals(response.getStatus(), LongRunningOperationStatus.SUCCESSFULLY_COMPLETED); - Assertions.assertNotNull(pollResult.value().getResourceId()); + Assertions.assertNotNull(pollResult.getValue().getResourceId()); } else { throw new IllegalStateException("Poller emitted more than expected value."); } @@ -225,9 +226,9 @@ public String getName() { AsyncPollResponse, Resource> asyncPollResponse = lroFlux.doOnNext(response -> { PollResult pollResult = response.getValue(); Assertions.assertNotNull(pollResult); - Assertions.assertNotNull(pollResult.value()); + Assertions.assertNotNull(pollResult.getValue()); Assertions.assertEquals(LongRunningOperationStatus.SUCCESSFULLY_COMPLETED, response.getStatus()); - Assertions.assertNotNull(pollResult.value().id()); + Assertions.assertNotNull(pollResult.getValue().id()); }).blockLast(); Assertions.assertNotNull(asyncPollResponse);