From 044900e486baea04fb1b271792d28f8589b2990d Mon Sep 17 00:00:00 2001 From: Alexandre Gattiker Date: Fri, 3 Jun 2022 17:07:13 +0200 Subject: [PATCH 01/13] Feature/1364/284 clock (#286) --- .../core/CoreServicesExtension.java | 2 ++ .../DefaultServiceExtensionContext.java | 17 ++--------- .../contract/ContractServiceExtension.java | 20 +++++++++---- .../AbstractContractNegotiationManager.java | 9 ++++++ ...onsumerContractNegotiationManagerImpl.java | 7 ++--- ...roviderContractNegotiationManagerImpl.java | 7 ++--- .../ContractValidationServiceImpl.java | 10 ++++--- .../ContractValidationServiceImplTest.java | 20 +++++++++---- .../transfer/core/CoreTransferExtension.java | 6 +++- .../transfer/TransferProcessManagerImpl.java | 7 ++++- .../TransferProcessSendRetryManager.java | 5 ++-- ...sferProcessManagerImplIntegrationTest.java | 2 ++ .../TransferProcessManagerImplTest.java | 5 ++-- .../TransferProcessSendRetryManagerTest.java | 7 ++--- ...ntractNegotiationStoreIntegrationTest.java | 10 ++++--- .../azure/cosmos/LeaseableCosmosDocument.java | 11 ++++--- .../cosmos/LeaseableCosmosDocumentTest.java | 22 +++++++------- ...osTransferProcessStoreIntegrationTest.java | 20 +++++++------ .../DataPlaneAzureDataFactoryExtension.java | 4 +-- .../sync/DataPlaneTransferSyncExtension.java | 10 +++++-- ...laneTransferProxyReferenceServiceImpl.java | 8 +++-- .../validation/ContractValidationRule.java | 7 +++-- .../ExpirationDateValidationRule.java | 10 +++++-- ...TransferProxyReferenceServiceImplTest.java | 8 +++-- .../ContractValidationRuleTest.java | 10 +++++-- .../iam/did/IdentityDidCoreExtension.java | 6 +++- .../did/store/InMemoryDidDocumentStore.java | 11 ++++--- .../store/InMemoryDidDocumentStoreTest.java | 3 +- .../VerifiableCredentialFactory.java | 24 +++++++-------- .../VerifiableCredentialFactoryTest.java | 17 ++++++----- .../DecentralizedIdentityService.java | 8 +++-- ...DecentralizedIdentityServiceExtension.java | 8 +++-- .../DecentralizedIdentityServiceTest.java | 14 +++++---- .../crawler/CrawlerContext.java | 14 +++++++++ .../crawler/CrawlerExtension.java | 4 +++ .../crawler/CrawlerJob.java | 20 ++++++++----- .../iam/mock/IamMockExtension.java | 2 +- .../iam/mock/MockIdentityService.java | 8 +++-- .../iam/oauth2/core/Oauth2Extension.java | 8 +++-- .../oauth2/core/jwt/DefaultJwtDecorator.java | 11 +++---- .../core/rule/Oauth2ValidationRule.java | 13 ++++---- .../Oauth2ValidationRulesRegistryImpl.java | 6 ++-- .../core/identity/Oauth2ServiceImplTest.java | 16 ++++++---- .../core/jwt/DefaultJwtDecoratorTest.java | 17 +++++------ .../core/jwt/Oauth2ValidationRuleTest.java | 7 +++-- .../SqlContractNegotiationStoreExtension.java | 7 ++++- .../store/SqlContractNegotiationStore.java | 12 ++++---- .../SqlContractNegotiationStoreTest.java | 5 ++-- .../sql/lease/SqlLease.java | 5 ++-- .../sql/lease/SqlLeaseContext.java | 10 ++++--- .../sql/lease/SqlLeaseContextBuilder.java | 11 ++++--- .../sql/lease/SqlLeaseContextTest.java | 7 +++-- .../sql/lease/LeaseUtil.java | 5 ++-- .../SqlTransferProcessStoreExtension.java | 6 +++- .../store/SqlTransferProcessStore.java | 11 +++---- .../store/SqlTransferProcessStoreTest.java | 5 ++-- .../TransferSimulationExtension.java | 2 +- .../sample042/CheckTimeoutCommandHandler.java | 8 +++-- .../samples/sample042/WatchdogExtension.java | 2 +- .../negotiation/ContractNegotiation.java | 30 +++++++++---------- .../spi/system/ServiceExtensionContext.java | 21 +++++++++++-- .../domain/transfer/TransferProcess.java | 25 ++++++++++------ .../domain/transfer/TransferProcessTest.java | 13 -------- 63 files changed, 401 insertions(+), 245 deletions(-) diff --git a/core/base/src/main/java/org/eclipse/dataspaceconnector/core/CoreServicesExtension.java b/core/base/src/main/java/org/eclipse/dataspaceconnector/core/CoreServicesExtension.java index 6df5b9a7ea6..9742720318e 100644 --- a/core/base/src/main/java/org/eclipse/dataspaceconnector/core/CoreServicesExtension.java +++ b/core/base/src/main/java/org/eclipse/dataspaceconnector/core/CoreServicesExtension.java @@ -53,6 +53,7 @@ import org.eclipse.dataspaceconnector.spi.types.TypeManager; import java.security.PrivateKey; +import java.time.Clock; import java.time.Duration; import java.time.temporal.ChronoUnit; import java.util.concurrent.ExecutorService; @@ -65,6 +66,7 @@ HealthCheckService.class, Monitor.class, TypeManager.class, + Clock.class, Telemetry.class }) public class CoreServicesExtension implements ServiceExtension { diff --git a/core/boot/src/main/java/org/eclipse/dataspaceconnector/boot/system/DefaultServiceExtensionContext.java b/core/boot/src/main/java/org/eclipse/dataspaceconnector/boot/system/DefaultServiceExtensionContext.java index 400e4f221af..0fe07b27ca7 100644 --- a/core/boot/src/main/java/org/eclipse/dataspaceconnector/boot/system/DefaultServiceExtensionContext.java +++ b/core/boot/src/main/java/org/eclipse/dataspaceconnector/boot/system/DefaultServiceExtensionContext.java @@ -24,6 +24,7 @@ import org.eclipse.dataspaceconnector.spi.telemetry.Telemetry; import org.eclipse.dataspaceconnector.spi.types.TypeManager; +import java.time.Clock; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -47,6 +48,7 @@ public DefaultServiceExtensionContext(TypeManager typeManager, Monitor monitor, registerService(TypeManager.class, typeManager); registerService(Monitor.class, monitor); registerService(Telemetry.class, telemetry); + registerService(Clock.class, Clock.systemUTC()); } @Override @@ -54,21 +56,6 @@ public String getConnectorId() { return connectorId; } - @Override - public Monitor getMonitor() { - return getService(Monitor.class); - } - - @Override - public Telemetry getTelemetry() { - return getService(Telemetry.class); - } - - @Override - public TypeManager getTypeManager() { - return getService(TypeManager.class); - } - @Override public boolean hasService(Class type) { return services.containsKey(type); diff --git a/core/contract/src/main/java/org/eclipse/dataspaceconnector/contract/ContractServiceExtension.java b/core/contract/src/main/java/org/eclipse/dataspaceconnector/contract/ContractServiceExtension.java index 9c1119f0dc9..2fee6e8c1bb 100644 --- a/core/contract/src/main/java/org/eclipse/dataspaceconnector/contract/ContractServiceExtension.java +++ b/core/contract/src/main/java/org/eclipse/dataspaceconnector/contract/ContractServiceExtension.java @@ -52,9 +52,12 @@ import org.eclipse.dataspaceconnector.spi.system.Provides; import org.eclipse.dataspaceconnector.spi.system.ServiceExtension; import org.eclipse.dataspaceconnector.spi.system.ServiceExtensionContext; +import org.eclipse.dataspaceconnector.spi.telemetry.Telemetry; import org.eclipse.dataspaceconnector.spi.types.domain.contract.negotiation.ContractNegotiation; import org.eclipse.dataspaceconnector.spi.types.domain.contract.negotiation.command.ContractNegotiationCommand; +import java.time.Clock; + @Provides({ ContractOfferService.class, ContractValidationService.class, ConsumerContractNegotiationManager.class, PolicyArchive.class, ProviderContractNegotiationManager.class @@ -63,7 +66,6 @@ public class ContractServiceExtension implements ServiceExtension { private static final long DEFAULT_ITERATION_WAIT = 5000; // millis - private Monitor monitor; private ConsumerContractNegotiationManagerImpl consumerNegotiationManager; private ProviderContractNegotiationManagerImpl providerNegotiationManager; @@ -97,6 +99,15 @@ public class ContractServiceExtension implements ServiceExtension { @Inject private PolicyStore policyStore; + @Inject + private Monitor monitor; + + @Inject + private Telemetry telemetry; + + @Inject + private Clock clock; + @Override public String name() { return "Core Contract Service"; @@ -104,8 +115,6 @@ public String name() { @Override public void initialize(ServiceExtensionContext context) { - monitor = context.getMonitor(); - registerTypes(context); registerServices(context); } @@ -134,7 +143,7 @@ private void registerServices(ServiceExtensionContext context) { var contractOfferService = new ContractOfferServiceImpl(agentService, definitionService, assetIndex, policyStore); context.registerService(ContractOfferService.class, contractOfferService); - var validationService = new ContractValidationServiceImpl(agentService, definitionService, assetIndex, policyStore); + var validationService = new ContractValidationServiceImpl(agentService, definitionService, assetIndex, policyStore, clock); context.registerService(ContractValidationService.class, validationService); var waitStrategy = context.hasService(NegotiationWaitStrategy.class) ? context.getService(NegotiationWaitStrategy.class) : new ExponentialWaitStrategy(DEFAULT_ITERATION_WAIT); @@ -142,7 +151,6 @@ private void registerServices(ServiceExtensionContext context) { CommandQueue commandQueue = new BoundedCommandQueue<>(10); CommandRunner commandRunner = new CommandRunner<>(commandHandlerRegistry, monitor); - var telemetry = context.getTelemetry(); var observable = new ContractNegotiationObservableImpl(); context.registerService(ContractNegotiationObservable.class, observable); @@ -156,6 +164,7 @@ private void registerServices(ServiceExtensionContext context) { .commandQueue(commandQueue) .commandRunner(commandRunner) .observable(observable) + .clock(clock) .telemetry(telemetry) .executorInstrumentation(context.getService(ExecutorInstrumentation.class)) .store(store) @@ -171,6 +180,7 @@ private void registerServices(ServiceExtensionContext context) { .commandQueue(commandQueue) .commandRunner(commandRunner) .observable(observable) + .clock(clock) .telemetry(telemetry) .executorInstrumentation(context.getService(ExecutorInstrumentation.class)) .store(store) diff --git a/core/contract/src/main/java/org/eclipse/dataspaceconnector/contract/negotiation/AbstractContractNegotiationManager.java b/core/contract/src/main/java/org/eclipse/dataspaceconnector/contract/negotiation/AbstractContractNegotiationManager.java index f4eb2999839..d58fd7f1f9f 100644 --- a/core/contract/src/main/java/org/eclipse/dataspaceconnector/contract/negotiation/AbstractContractNegotiationManager.java +++ b/core/contract/src/main/java/org/eclipse/dataspaceconnector/contract/negotiation/AbstractContractNegotiationManager.java @@ -28,6 +28,7 @@ import org.eclipse.dataspaceconnector.spi.telemetry.Telemetry; import org.eclipse.dataspaceconnector.spi.types.domain.contract.negotiation.command.ContractNegotiationCommand; +import java.time.Clock; import java.util.Objects; public abstract class AbstractContractNegotiationManager { @@ -40,6 +41,7 @@ public abstract class AbstractContractNegotiationManager { protected CommandRunner commandRunner; protected CommandProcessor commandProcessor; protected Monitor monitor; + protected Clock clock; protected Telemetry telemetry; protected ExecutorInstrumentation executorInstrumentation; protected int batchSize = 5; @@ -52,6 +54,7 @@ public static class Builder { protected Builder(T manager) { this.manager = manager; + this.manager.clock = Clock.systemUTC(); // default implementation this.manager.telemetry = new Telemetry(); // default noop implementation this.manager.executorInstrumentation = ExecutorInstrumentation.noop(); // default noop implementation } @@ -91,6 +94,11 @@ public Builder commandRunner(CommandRunner comman return this; } + public Builder clock(Clock clock) { + manager.clock = clock; + return this; + } + public Builder telemetry(Telemetry telemetry) { manager.telemetry = telemetry; return this; @@ -123,6 +131,7 @@ public T build() { Objects.requireNonNull(manager.commandQueue, "commandQueue"); Objects.requireNonNull(manager.commandRunner, "commandRunner"); Objects.requireNonNull(manager.observable, "observable"); + Objects.requireNonNull(manager.clock, "clock"); Objects.requireNonNull(manager.telemetry, "telemetry"); Objects.requireNonNull(manager.executorInstrumentation, "executorInstrumentation"); Objects.requireNonNull(manager.negotiationStore, "store"); diff --git a/core/contract/src/main/java/org/eclipse/dataspaceconnector/contract/negotiation/ConsumerContractNegotiationManagerImpl.java b/core/contract/src/main/java/org/eclipse/dataspaceconnector/contract/negotiation/ConsumerContractNegotiationManagerImpl.java index a576a07cf35..eb24d2a042b 100644 --- a/core/contract/src/main/java/org/eclipse/dataspaceconnector/contract/negotiation/ConsumerContractNegotiationManagerImpl.java +++ b/core/contract/src/main/java/org/eclipse/dataspaceconnector/contract/negotiation/ConsumerContractNegotiationManagerImpl.java @@ -37,7 +37,6 @@ import org.eclipse.dataspaceconnector.spi.types.domain.contract.offer.ContractOffer; import org.jetbrains.annotations.NotNull; -import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Objects; import java.util.UUID; @@ -395,9 +394,9 @@ private boolean processConsumerApproving(ContractNegotiation negotiation) { var policy = lastOffer.getPolicy(); var agreement = ContractAgreement.Builder.newInstance() .id(ContractId.createContractId(definitionId)) - .contractStartDate(Instant.now().getEpochSecond()) - .contractEndDate(Instant.now().plus(365, ChronoUnit.DAYS).getEpochSecond()) // TODO Make configurable (issue #722) - .contractSigningDate(Instant.now().getEpochSecond()) + .contractStartDate(clock.instant().getEpochSecond()) + .contractEndDate(clock.instant().plus(365, ChronoUnit.DAYS).getEpochSecond()) // TODO Make configurable (issue #722) + .contractSigningDate(clock.instant().getEpochSecond()) .providerAgentId(String.valueOf(lastOffer.getProvider())) .consumerAgentId(String.valueOf(lastOffer.getConsumer())) .policyId(policy.getUid()) diff --git a/core/contract/src/main/java/org/eclipse/dataspaceconnector/contract/negotiation/ProviderContractNegotiationManagerImpl.java b/core/contract/src/main/java/org/eclipse/dataspaceconnector/contract/negotiation/ProviderContractNegotiationManagerImpl.java index 07f93cf5813..ff113e1ff57 100644 --- a/core/contract/src/main/java/org/eclipse/dataspaceconnector/contract/negotiation/ProviderContractNegotiationManagerImpl.java +++ b/core/contract/src/main/java/org/eclipse/dataspaceconnector/contract/negotiation/ProviderContractNegotiationManagerImpl.java @@ -37,7 +37,6 @@ import org.eclipse.dataspaceconnector.spi.types.domain.contract.offer.ContractOffer; import org.jetbrains.annotations.NotNull; -import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.UUID; import java.util.function.BiConsumer; @@ -386,9 +385,9 @@ private boolean processConfirming(ContractNegotiation negotiation) { //TODO move to own service agreement = ContractAgreement.Builder.newInstance() .id(ContractId.createContractId(definitionId)) - .contractStartDate(Instant.now().getEpochSecond()) - .contractEndDate(Instant.now().plus(365, ChronoUnit.DAYS).getEpochSecond()) // TODO Make configurable (issue #722) - .contractSigningDate(Instant.now().getEpochSecond()) + .contractStartDate(clock.instant().getEpochSecond()) + .contractEndDate(clock.instant().plus(365, ChronoUnit.DAYS).getEpochSecond()) // TODO Make configurable (issue #722) + .contractSigningDate(clock.instant().getEpochSecond()) .providerAgentId(String.valueOf(lastOffer.getProvider())) .consumerAgentId(String.valueOf(lastOffer.getConsumer())) .policyId(policy.getUid()) diff --git a/core/contract/src/main/java/org/eclipse/dataspaceconnector/contract/validation/ContractValidationServiceImpl.java b/core/contract/src/main/java/org/eclipse/dataspaceconnector/contract/validation/ContractValidationServiceImpl.java index aa96c85f804..e52a2d79822 100644 --- a/core/contract/src/main/java/org/eclipse/dataspaceconnector/contract/validation/ContractValidationServiceImpl.java +++ b/core/contract/src/main/java/org/eclipse/dataspaceconnector/contract/validation/ContractValidationServiceImpl.java @@ -31,7 +31,7 @@ import org.eclipse.dataspaceconnector.spi.types.domain.contract.offer.ContractOffer; import org.jetbrains.annotations.NotNull; -import java.time.Instant; +import java.time.Clock; import java.util.ArrayList; import static java.lang.String.format; @@ -47,12 +47,14 @@ public class ContractValidationServiceImpl implements ContractValidationService private final ContractDefinitionService contractDefinitionService; private final AssetIndex assetIndex; private final PolicyStore policyStore; + private final Clock clock; - public ContractValidationServiceImpl(ParticipantAgentService agentService, ContractDefinitionService contractDefinitionService, AssetIndex assetIndex, PolicyStore policyStore) { + public ContractValidationServiceImpl(ParticipantAgentService agentService, ContractDefinitionService contractDefinitionService, AssetIndex assetIndex, PolicyStore policyStore, Clock clock) { this.agentService = agentService; this.contractDefinitionService = contractDefinitionService; this.assetIndex = assetIndex; this.policyStore = policyStore; + this.clock = clock; } @Override @@ -143,11 +145,11 @@ private ArrayList createCriteria(ContractOffer offer, ContractDefinit } private boolean isExpired(ContractAgreement contractAgreement) { - return contractAgreement.getContractEndDate() < Instant.now().getEpochSecond(); + return contractAgreement.getContractEndDate() * 1000L < clock.millis(); } private boolean isStarted(ContractAgreement contractAgreement) { - return contractAgreement.getContractStartDate() <= Instant.now().getEpochSecond(); + return contractAgreement.getContractStartDate() * 1000L <= clock.millis(); } private boolean isMandatoryAttributeMissing(ContractOffer offer) { diff --git a/core/contract/src/test/java/org/eclipse/dataspaceconnector/contract/validation/ContractValidationServiceImplTest.java b/core/contract/src/test/java/org/eclipse/dataspaceconnector/contract/validation/ContractValidationServiceImplTest.java index c34178b8649..4a7cf80b2cb 100644 --- a/core/contract/src/test/java/org/eclipse/dataspaceconnector/contract/validation/ContractValidationServiceImplTest.java +++ b/core/contract/src/test/java/org/eclipse/dataspaceconnector/contract/validation/ContractValidationServiceImplTest.java @@ -16,6 +16,7 @@ package org.eclipse.dataspaceconnector.contract.validation; +import com.github.javafaker.Faker; import org.eclipse.dataspaceconnector.policy.model.Policy; import org.eclipse.dataspaceconnector.spi.agent.ParticipantAgent; import org.eclipse.dataspaceconnector.spi.agent.ParticipantAgentService; @@ -33,13 +34,17 @@ import org.junit.jupiter.api.Test; import java.net.URI; +import java.time.Clock; import java.time.Instant; import java.time.temporal.ChronoUnit; +import java.util.Date; import java.util.UUID; import java.util.stream.Stream; +import static java.time.Instant.EPOCH; import static java.time.Instant.MAX; import static java.time.Instant.MIN; +import static java.time.ZoneOffset.UTC; import static java.util.Collections.emptyMap; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -51,15 +56,19 @@ class ContractValidationServiceImplTest { + private static final Faker FAKER = new Faker(); + private final Instant now = Instant.now(); + private final ParticipantAgentService agentService = mock(ParticipantAgentService.class); private final ContractDefinitionService definitionService = mock(ContractDefinitionService.class); private final AssetIndex assetIndex = mock(AssetIndex.class); private final PolicyStore policyStore = mock(PolicyStore.class); + private final Clock clock = Clock.fixed(now, UTC); private ContractValidationServiceImpl validationService; @BeforeEach void setUp() { - validationService = new ContractValidationServiceImpl(agentService, definitionService, assetIndex, policyStore); + validationService = new ContractValidationServiceImpl(agentService, definitionService, assetIndex, policyStore, clock); } @Test @@ -119,9 +128,9 @@ void verifyContractAgreementValidation() { .consumerAgentId("consumer") .policyId("policy") .assetId(UUID.randomUUID().toString()) - .contractStartDate(Instant.now().getEpochSecond()) - .contractEndDate(Instant.now().plus(1, ChronoUnit.DAYS).getEpochSecond()) - .contractSigningDate(Instant.now().getEpochSecond()) + .contractStartDate(now.getEpochSecond()) + .contractEndDate(now.plus(1, ChronoUnit.DAYS).getEpochSecond()) + .contractSigningDate(now.getEpochSecond()) .id("1:2").build(); assertThat(validationService.validate(claimToken, agreement)).isTrue(); @@ -131,8 +140,9 @@ void verifyContractAgreementValidation() { @Test void verifyContractAgreementExpired() { + var past = FAKER.date().between(Date.from(EPOCH), Date.from(now)).toInstant().getEpochSecond(); var isValid = - validateAgreementDate(MIN.getEpochSecond(), MIN.getEpochSecond(), Instant.now().getEpochSecond() - 1); + validateAgreementDate(MIN.getEpochSecond(), MIN.getEpochSecond(), past); assertThat(isValid).isFalse(); } diff --git a/core/transfer/src/main/java/org/eclipse/dataspaceconnector/transfer/core/CoreTransferExtension.java b/core/transfer/src/main/java/org/eclipse/dataspaceconnector/transfer/core/CoreTransferExtension.java index 513afe8ba2c..a3a130f42bd 100644 --- a/core/transfer/src/main/java/org/eclipse/dataspaceconnector/transfer/core/CoreTransferExtension.java +++ b/core/transfer/src/main/java/org/eclipse/dataspaceconnector/transfer/core/CoreTransferExtension.java @@ -59,6 +59,8 @@ import org.eclipse.dataspaceconnector.transfer.core.transfer.TransferProcessManagerImpl; import org.eclipse.dataspaceconnector.transfer.core.transfer.TransferProcessSendRetryManager; +import java.time.Clock; + /** * Provides core data transfer services to the system. */ @@ -141,7 +143,8 @@ public void initialize(ServiceExtensionContext context) { var retryLimit = context.getSetting(TRANSFER_SEND_RETRY_LIMIT, 7); var retryBaseDelay = context.getSetting(TRANSFER_SEND_RETRY_BASE_DELAY_MS, 100L); - var sendRetryManager = new TransferProcessSendRetryManager(monitor, () -> new ExponentialWaitStrategy(retryBaseDelay), retryLimit); + Clock clock = context.getClock(); + var sendRetryManager = new TransferProcessSendRetryManager(monitor, () -> new ExponentialWaitStrategy(retryBaseDelay), clock, retryLimit); processManager = TransferProcessManagerImpl.Builder.newInstance() .waitStrategy(waitStrategy) @@ -154,6 +157,7 @@ public void initialize(ServiceExtensionContext context) { .telemetry(telemetry) .executorInstrumentation(context.getService(ExecutorInstrumentation.class)) .vault(vault) + .clock(clock) .typeManager(typeManager) .commandQueue(commandQueue) .commandRunner(new CommandRunner<>(registry, monitor)) diff --git a/core/transfer/src/main/java/org/eclipse/dataspaceconnector/transfer/core/transfer/TransferProcessManagerImpl.java b/core/transfer/src/main/java/org/eclipse/dataspaceconnector/transfer/core/transfer/TransferProcessManagerImpl.java index f8ab9d4fb8e..c6ebcfa749d 100644 --- a/core/transfer/src/main/java/org/eclipse/dataspaceconnector/transfer/core/transfer/TransferProcessManagerImpl.java +++ b/core/transfer/src/main/java/org/eclipse/dataspaceconnector/transfer/core/transfer/TransferProcessManagerImpl.java @@ -115,7 +115,7 @@ public class TransferProcessManagerImpl implements TransferProcessManager, Provi private DataAddressResolver addressResolver; private PolicyArchive policyArchive; private SendRetryManager sendRetryManager; - protected Clock clock = Clock.systemUTC(); + private Clock clock; private TransferProcessManagerImpl() { } @@ -712,6 +712,11 @@ public Builder executorInstrumentation(ExecutorInstrumentation executorInstrumen return this; } + public Builder clock(Clock clock) { + manager.clock = clock; + return this; + } + public Builder vault(Vault vault) { manager.vault = vault; return this; diff --git a/core/transfer/src/main/java/org/eclipse/dataspaceconnector/transfer/core/transfer/TransferProcessSendRetryManager.java b/core/transfer/src/main/java/org/eclipse/dataspaceconnector/transfer/core/transfer/TransferProcessSendRetryManager.java index 2876d3f4913..6ba8ae7d561 100644 --- a/core/transfer/src/main/java/org/eclipse/dataspaceconnector/transfer/core/transfer/TransferProcessSendRetryManager.java +++ b/core/transfer/src/main/java/org/eclipse/dataspaceconnector/transfer/core/transfer/TransferProcessSendRetryManager.java @@ -32,11 +32,12 @@ public class TransferProcessSendRetryManager implements SendRetryManager delayStrategySupplier; private final int retryLimit; - protected Clock clock = Clock.systemUTC(); + private final Clock clock; - public TransferProcessSendRetryManager(Monitor monitor, Supplier delayStrategySupplier, int retryLimit) { + public TransferProcessSendRetryManager(Monitor monitor, Supplier delayStrategySupplier, Clock clock, int retryLimit) { this.monitor = monitor; this.delayStrategySupplier = delayStrategySupplier; + this.clock = clock; this.retryLimit = retryLimit; } diff --git a/core/transfer/src/test/java/org/eclipse/dataspaceconnector/transfer/core/transfer/TransferProcessManagerImplIntegrationTest.java b/core/transfer/src/test/java/org/eclipse/dataspaceconnector/transfer/core/transfer/TransferProcessManagerImplIntegrationTest.java index 3d9c62a0fc7..0f43cbcf941 100644 --- a/core/transfer/src/test/java/org/eclipse/dataspaceconnector/transfer/core/transfer/TransferProcessManagerImplIntegrationTest.java +++ b/core/transfer/src/test/java/org/eclipse/dataspaceconnector/transfer/core/transfer/TransferProcessManagerImplIntegrationTest.java @@ -45,6 +45,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.time.Clock; import java.util.List; import java.util.UUID; import java.util.concurrent.CountDownLatch; @@ -89,6 +90,7 @@ void setup() { .dispatcherRegistry(mock(RemoteMessageDispatcherRegistry.class)) .manifestGenerator(manifestGenerator) .monitor(mock(Monitor.class)) + .clock(Clock.systemUTC()) .commandQueue(mock(CommandQueue.class)) .commandRunner(mock(CommandRunner.class)) .typeManager(new TypeManager()) diff --git a/core/transfer/src/test/java/org/eclipse/dataspaceconnector/transfer/core/transfer/TransferProcessManagerImplTest.java b/core/transfer/src/test/java/org/eclipse/dataspaceconnector/transfer/core/transfer/TransferProcessManagerImplTest.java index 7cc346d1e4f..2cc03682946 100644 --- a/core/transfer/src/test/java/org/eclipse/dataspaceconnector/transfer/core/transfer/TransferProcessManagerImplTest.java +++ b/core/transfer/src/test/java/org/eclipse/dataspaceconnector/transfer/core/transfer/TransferProcessManagerImplTest.java @@ -107,6 +107,8 @@ class TransferProcessManagerImplTest { private static final int TRANSFER_MANAGER_BATCHSIZE = 10; private static final String PROVISIONED_RESOURCE_ID = "1"; + private final long currentTime = 1343411; + private final ProvisionManager provisionManager = mock(ProvisionManager.class); private final RemoteMessageDispatcherRegistry dispatcherRegistry = mock(RemoteMessageDispatcherRegistry.class); private final StatusCheckerRegistry statusCheckerRegistry = mock(StatusCheckerRegistry.class); @@ -134,6 +136,7 @@ void setup() { .commandQueue(mock(CommandQueue.class)) .commandRunner(mock(CommandRunner.class)) .typeManager(new TypeManager()) + .clock(Clock.fixed(Instant.ofEpochMilli(currentTime), UTC)) .statusCheckerRegistry(statusCheckerRegistry) .observable(mock(TransferProcessObservable.class)) .transferProcessStore(transferProcessStore) @@ -166,8 +169,6 @@ void verifyCreatedTimestamp() { when(transferProcessStore.processIdForTransferId("1")).thenReturn(null, "2"); DataRequest dataRequest = DataRequest.Builder.newInstance().id("1").destinationType("test").build(); - var currentTime = 1343411; - manager.clock = Clock.fixed(Instant.ofEpochMilli(currentTime), UTC); manager.start(); manager.initiateProviderRequest(dataRequest); manager.stop(); diff --git a/core/transfer/src/test/java/org/eclipse/dataspaceconnector/transfer/core/transfer/TransferProcessSendRetryManagerTest.java b/core/transfer/src/test/java/org/eclipse/dataspaceconnector/transfer/core/transfer/TransferProcessSendRetryManagerTest.java index 33580e74e07..ef615f43913 100644 --- a/core/transfer/src/test/java/org/eclipse/dataspaceconnector/transfer/core/transfer/TransferProcessSendRetryManagerTest.java +++ b/core/transfer/src/test/java/org/eclipse/dataspaceconnector/transfer/core/transfer/TransferProcessSendRetryManagerTest.java @@ -26,11 +26,9 @@ import org.junit.jupiter.params.provider.ValueSource; import java.time.Clock; -import java.time.Instant; import java.util.UUID; import java.util.stream.Stream; -import static java.time.ZoneOffset.UTC; import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.dataspaceconnector.spi.types.domain.transfer.TransferProcessStates.REQUESTING; import static org.junit.jupiter.params.provider.Arguments.arguments; @@ -46,8 +44,9 @@ class TransferProcessSendRetryManagerTest { final WaitStrategy delayStrategy = mock(WaitStrategy.class); final int sendRetryLimit = faker.number().numberBetween(5, 10); + final Clock clock = mock(Clock.class); final TransferProcessSendRetryManager sendRetryManager = - new TransferProcessSendRetryManager(monitor, () -> delayStrategy, sendRetryLimit); + new TransferProcessSendRetryManager(monitor, () -> delayStrategy, clock, sendRetryLimit); @ParameterizedTest @MethodSource("delayArgs") @@ -68,7 +67,7 @@ void shouldDelay(long stateTimestamp, long currentTime, long retryDelay, boolean return retryDelay; }).thenThrow(new RuntimeException("should call only once")); - sendRetryManager.clock = Clock.fixed(Instant.ofEpochMilli(currentTime), UTC); + when(clock.millis()).thenReturn(currentTime); assertThat(sendRetryManager.shouldDelay(process)) .isEqualTo(shouldDelay); diff --git a/extensions/azure/cosmos/contract-negotiation-store-cosmos/src/test/java/org/eclipse/dataspaceconnector/contract/negotiation/store/CosmosContractNegotiationStoreIntegrationTest.java b/extensions/azure/cosmos/contract-negotiation-store-cosmos/src/test/java/org/eclipse/dataspaceconnector/contract/negotiation/store/CosmosContractNegotiationStoreIntegrationTest.java index 461074819eb..32eef636463 100644 --- a/extensions/azure/cosmos/contract-negotiation-store-cosmos/src/test/java/org/eclipse/dataspaceconnector/contract/negotiation/store/CosmosContractNegotiationStoreIntegrationTest.java +++ b/extensions/azure/cosmos/contract-negotiation-store-cosmos/src/test/java/org/eclipse/dataspaceconnector/contract/negotiation/store/CosmosContractNegotiationStoreIntegrationTest.java @@ -44,6 +44,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.time.Clock; import java.time.Duration; import java.time.temporal.ChronoUnit; import java.util.Comparator; @@ -67,6 +68,7 @@ class CosmosContractNegotiationStoreIntegrationTest { private static final String TEST_ID = UUID.randomUUID().toString(); private static final String DATABASE_NAME = "connector-itest-" + TEST_ID; private static final String CONTAINER_PREFIX = "ContractNegotiationStore-"; + private final Clock clock = Clock.systemUTC(); private static CosmosContainer container; private static CosmosDatabase database; private final String partitionKey = CONNECTOR_ID; @@ -210,7 +212,7 @@ void save_exists_shouldUpdate() { void save_leasedByOther_shouldRaiseException() { var negotiation = generateNegotiation("test-id", ContractNegotiationStates.CONFIRMED); var item = new ContractNegotiationDocument(negotiation, partitionKey); - item.acquireLease("someone-else"); + item.acquireLease("someone-else", clock); container.createItem(item); negotiation.transitionError("test-error"); @@ -222,7 +224,7 @@ void save_leasedByOther_shouldRaiseException() { void delete_leasedByOther_shouldRaiseException() { var negotiation = generateNegotiation("test-id", ContractNegotiationStates.CONFIRMED); var item = new ContractNegotiationDocument(negotiation, partitionKey); - item.acquireLease("someone-else"); + item.acquireLease("someone-else", clock); container.createItem(item); assertThatThrownBy(() -> store.delete(negotiation.getId())).isInstanceOf(EdcException.class).hasRootCauseInstanceOf(BadRequestException.class); @@ -275,7 +277,7 @@ void nextForState_onlyReturnsFreeItems() { var n3 = generateNegotiation(state); var doc3 = new ContractNegotiationDocument(n3, partitionKey); - doc3.acquireLease("another-connector"); + doc3.acquireLease("another-connector", clock); container.createItem(doc3); var result = store.nextForState(state.code(), 10); @@ -306,7 +308,7 @@ void nextForState_leasedByAnotherExpired() { var n = generateNegotiation(state); var doc = new ContractNegotiationDocument(n, partitionKey); Duration leaseDuration = Duration.ofSeconds(10); // give it some time to compensate for TOF delays - doc.acquireLease("another-connector", leaseDuration); + doc.acquireLease("another-connector", clock, leaseDuration); container.createItem(doc); // before the lease expired diff --git a/extensions/azure/cosmos/cosmos-common/src/main/java/org/eclipse/dataspaceconnector/azure/cosmos/LeaseableCosmosDocument.java b/extensions/azure/cosmos/cosmos-common/src/main/java/org/eclipse/dataspaceconnector/azure/cosmos/LeaseableCosmosDocument.java index 66ed98a942f..83803920ff6 100644 --- a/extensions/azure/cosmos/cosmos-common/src/main/java/org/eclipse/dataspaceconnector/azure/cosmos/LeaseableCosmosDocument.java +++ b/extensions/azure/cosmos/cosmos-common/src/main/java/org/eclipse/dataspaceconnector/azure/cosmos/LeaseableCosmosDocument.java @@ -17,6 +17,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import org.eclipse.dataspaceconnector.spi.persistence.Lease; +import java.time.Clock; import java.time.Duration; import java.time.Instant; @@ -61,22 +62,24 @@ public void breakLease(String identifier) { * Tries to lock down the document to avoid concurrent modification. No database modification takes place yet. * * @param leaseBy The ID of the connector that attempts acquiring the lease. + * @param clock Clock used to get current time * @throws IllegalStateException if the {@link LeaseableCosmosDocument} has been leased before by a different connector */ - public void acquireLease(String leaseBy) { - acquireLease(leaseBy, Duration.ofSeconds(60)); + public void acquireLease(String leaseBy, Clock clock) { + acquireLease(leaseBy, clock, Duration.ofSeconds(60)); } /** * Tries to lock down the TransferProcess to avoid concurrent modification. No database modification takes place yet * * @param leaseBy The ID of the connector that attempts acquiring the lease. + * @param clock Clock used to get current time * @param leaseDuration How long the lease should be valid * @throws IllegalStateException if the {@link LeaseableCosmosDocument} has been leased before by a different connector */ - public void acquireLease(String leaseBy, Duration leaseDuration) { + public void acquireLease(String leaseBy, Clock clock, Duration leaseDuration) { if (lease == null || lease.getLeasedBy().equals(leaseBy)) { - lease = new Lease(leaseBy, Instant.now().toEpochMilli(), leaseDuration.toMillis()); + lease = new Lease(leaseBy, clock.millis(), leaseDuration.toMillis()); } else { var startDate = Instant.ofEpochMilli(lease.getLeasedAt()); var endDate = startDate.plusSeconds(lease.getLeaseDuration()); diff --git a/extensions/azure/cosmos/cosmos-common/src/test/java/org/eclipse/dataspaceconnector/azure/cosmos/LeaseableCosmosDocumentTest.java b/extensions/azure/cosmos/cosmos-common/src/test/java/org/eclipse/dataspaceconnector/azure/cosmos/LeaseableCosmosDocumentTest.java index b7f8979e06b..4275fd8a3c2 100644 --- a/extensions/azure/cosmos/cosmos-common/src/test/java/org/eclipse/dataspaceconnector/azure/cosmos/LeaseableCosmosDocumentTest.java +++ b/extensions/azure/cosmos/cosmos-common/src/test/java/org/eclipse/dataspaceconnector/azure/cosmos/LeaseableCosmosDocumentTest.java @@ -16,6 +16,7 @@ import org.junit.jupiter.api.Test; +import java.time.Clock; import java.time.Duration; import static org.assertj.core.api.Assertions.assertThat; @@ -23,6 +24,7 @@ class LeaseableCosmosDocumentTest { + private final Clock clock = Clock.systemUTC(); @Test void getLease() { @@ -34,7 +36,7 @@ void getLease() { void breakLease() { var doc = new TestDocument("foo", "testpartitionkey"); - doc.acquireLease("me"); + doc.acquireLease("me", clock); doc.breakLease("me"); assertThat(doc.getLease()).isNull(); @@ -52,7 +54,7 @@ void breakLease_whenNotLeased() { @Test void breakLease_whenNotLeasedBySelf() { var doc = new TestDocument("foo", "testpartitionkey"); - doc.acquireLease("me"); + doc.acquireLease("me", clock); assertThatThrownBy(() -> doc.breakLease("not-me")).isInstanceOf(IllegalStateException.class); } @@ -61,9 +63,9 @@ void breakLease_whenNotLeasedBySelf() { void acquireLease() { var doc = new TestDocument("foo", "testpartitionkey"); - doc.acquireLease("me"); + doc.acquireLease("me", clock); assertThat(doc.getLease()).isNotNull(); - assertThat(doc.getLease().getLeasedBy()).isEqualTo("me"); + assertThat(doc.getLease().getLeasedBy()).isEqualTo("me", clock); assertThat(doc.getLease().getLeaseDuration()).isEqualTo(60_000L); assertThat(doc.getLease().getLeasedAt()).isGreaterThan(0); } @@ -72,9 +74,9 @@ void acquireLease() { void acquireLease_withDuration() { var doc = new TestDocument("foo", "testpartitionkey"); - doc.acquireLease("me", Duration.ofSeconds(2)); + doc.acquireLease("me", clock, Duration.ofSeconds(2)); assertThat(doc.getLease()).isNotNull(); - assertThat(doc.getLease().getLeasedBy()).isEqualTo("me"); + assertThat(doc.getLease().getLeasedBy()).isEqualTo("me", clock); assertThat(doc.getLease().getLeaseDuration()).isEqualTo(2_000L); assertThat(doc.getLease().getLeasedAt()).isGreaterThan(0); } @@ -82,15 +84,15 @@ void acquireLease_withDuration() { @Test void acquireLease_whenAlreadyAcquired() { var doc = new TestDocument("foo", "testpartitionkey"); - doc.acquireLease("me"); - doc.acquireLease("me"); + doc.acquireLease("me", clock); + doc.acquireLease("me", clock); assertThat(doc.getLease()).isNotNull(); } @Test void acquireLease_whenAlreadyAcquired_byOther() { var doc = new TestDocument("foo", "testpartitionkey"); - doc.acquireLease("me"); - assertThatThrownBy(() -> doc.acquireLease("not-me")).isInstanceOf(IllegalStateException.class); + doc.acquireLease("me", clock); + assertThatThrownBy(() -> doc.acquireLease("not-me", clock)).isInstanceOf(IllegalStateException.class); } } \ No newline at end of file diff --git a/extensions/azure/cosmos/transfer-process-store-cosmos/src/test/java/org/eclipse/dataspaceconnector/transfer/store/cosmos/CosmosTransferProcessStoreIntegrationTest.java b/extensions/azure/cosmos/transfer-process-store-cosmos/src/test/java/org/eclipse/dataspaceconnector/transfer/store/cosmos/CosmosTransferProcessStoreIntegrationTest.java index bbd7fce7236..56b497f9694 100644 --- a/extensions/azure/cosmos/transfer-process-store-cosmos/src/test/java/org/eclipse/dataspaceconnector/transfer/store/cosmos/CosmosTransferProcessStoreIntegrationTest.java +++ b/extensions/azure/cosmos/transfer-process-store-cosmos/src/test/java/org/eclipse/dataspaceconnector/transfer/store/cosmos/CosmosTransferProcessStoreIntegrationTest.java @@ -42,6 +42,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.time.Clock; import java.time.Duration; import java.time.temporal.ChronoUnit; import java.util.Arrays; @@ -65,6 +66,7 @@ class CosmosTransferProcessStoreIntegrationTest { private static final String CONTAINER_PREFIX = "container_"; private static CosmosContainer container; private static CosmosDatabase database; + private final Clock clock = Clock.systemUTC(); private final String partitionKey = "testpartition"; private final String connectorId = "test-connector"; private CosmosTransferProcessStore store; @@ -170,7 +172,7 @@ void nextForState_leaseByAnotherHolderExpired() { var tp = createTransferProcess(id1, TransferProcessStates.INITIAL); TransferProcessDocument item = new TransferProcessDocument(tp, partitionKey); Duration leaseDuration = Duration.ofSeconds(10); - item.acquireLease("another-connector", leaseDuration); + item.acquireLease("another-connector", clock, leaseDuration); container.upsertItem(item); List processesBeforeLeaseBreak = store.nextForState(TransferProcessStates.INITIAL.code(), 10); @@ -197,7 +199,7 @@ void nextForState_shouldOnlyReturnFreeItems() { store.create(tp); store.create(tp2); TransferProcessDocument item = readDocument(id2); - item.acquireLease("test-leaser"); + item.acquireLease("test-leaser", clock); container.upsertItem(item); //act - one should be ignored @@ -210,7 +212,7 @@ void nextForState_shouldOnlyReturnFreeItems() { void nextForState_selfCannotLeaseAgain() { var tp1 = createTransferProcess("process1", TransferProcessStates.INITIAL); var doc = new TransferProcessDocument(tp1, partitionKey); - doc.acquireLease(connectorId); + doc.acquireLease(connectorId, clock); var originalTimestamp = doc.getLease().getLeasedAt(); container.upsertItem(doc); @@ -233,9 +235,9 @@ void nextForState_noFreeItem_shouldReturnEmpty() { var tp2 = createTransferProcess(id2, TransferProcessStates.INITIAL); var d1 = new TransferProcessDocument(tp, partitionKey); - d1.acquireLease("another-connector"); + d1.acquireLease("another-connector", clock); var d2 = new TransferProcessDocument(tp2, partitionKey); - d2.acquireLease("a-third-connector"); + d2.acquireLease("a-third-connector", clock); container.upsertItem(d1); container.upsertItem(d2); @@ -417,7 +419,7 @@ void update_leasedBySelf() { var doc = new TransferProcessDocument(tp, partitionKey); container.upsertItem(doc).getItem(); - doc.acquireLease(connectorId); + doc.acquireLease(connectorId, clock); container.upsertItem(doc); tp.transitionProvisioning(ResourceManifest.Builder.newInstance().build()); @@ -434,7 +436,7 @@ void update_leasedByOther_shouldThrowException() { var doc = new TransferProcessDocument(tp, partitionKey); container.upsertItem(doc).getItem(); - doc.acquireLease("another-connector"); + doc.acquireLease("another-connector", clock); container.upsertItem(doc); //act @@ -461,7 +463,7 @@ void delete_isLeased_shouldThrowException() { final String processId = "test-process-id"; var tp = createTransferProcess(processId); var doc = new TransferProcessDocument(tp, partitionKey); - doc.acquireLease("some-other-connector"); + doc.acquireLease("some-other-connector", clock); container.upsertItem(doc); assertThatThrownBy(() -> store.delete(processId)).isInstanceOf(EdcException.class).hasRootCauseInstanceOf(BadRequestException.class); @@ -472,7 +474,7 @@ void delete_isLeasedBySelf() { final String processId = "test-process-id"; var tp = createTransferProcess(processId); var doc = new TransferProcessDocument(tp, partitionKey); - doc.acquireLease(connectorId); + doc.acquireLease(connectorId, clock); container.upsertItem(doc); store.delete(processId); diff --git a/extensions/azure/data-plane/data-factory/src/main/java/org/eclipse/dataspaceconnector/azure/dataplane/azuredatafactory/DataPlaneAzureDataFactoryExtension.java b/extensions/azure/data-plane/data-factory/src/main/java/org/eclipse/dataspaceconnector/azure/dataplane/azuredatafactory/DataPlaneAzureDataFactoryExtension.java index 8da99104f49..28cb1875626 100644 --- a/extensions/azure/data-plane/data-factory/src/main/java/org/eclipse/dataspaceconnector/azure/dataplane/azuredatafactory/DataPlaneAzureDataFactoryExtension.java +++ b/extensions/azure/data-plane/data-factory/src/main/java/org/eclipse/dataspaceconnector/azure/dataplane/azuredatafactory/DataPlaneAzureDataFactoryExtension.java @@ -61,8 +61,8 @@ public class DataPlaneAzureDataFactoryExtension implements ServiceExtension { @Inject private BlobStoreApi blobStoreApi; - @Inject(required = false) - private final Clock clock = Clock.systemUTC(); + @Inject + private Clock clock; @Override public String name() { diff --git a/extensions/data-plane-transfer/data-plane-transfer-sync/src/main/java/org/eclipse/dataspaceconnector/transfer/dataplane/sync/DataPlaneTransferSyncExtension.java b/extensions/data-plane-transfer/data-plane-transfer-sync/src/main/java/org/eclipse/dataspaceconnector/transfer/dataplane/sync/DataPlaneTransferSyncExtension.java index 8372f090626..ba4571b38c0 100644 --- a/extensions/data-plane-transfer/data-plane-transfer-sync/src/main/java/org/eclipse/dataspaceconnector/transfer/dataplane/sync/DataPlaneTransferSyncExtension.java +++ b/extensions/data-plane-transfer/data-plane-transfer-sync/src/main/java/org/eclipse/dataspaceconnector/transfer/dataplane/sync/DataPlaneTransferSyncExtension.java @@ -42,6 +42,7 @@ import java.security.KeyPair; import java.security.PrivateKey; import java.security.PublicKey; +import java.time.Clock; import java.util.Objects; import static org.eclipse.dataspaceconnector.transfer.dataplane.sync.DataPlaneTransferSyncConfig.DATA_PROXY_ENDPOINT; @@ -72,6 +73,9 @@ public class DataPlaneTransferSyncExtension implements ServiceExtension { @Inject private Vault vault; + @Inject + private Clock clock; + @Inject private PrivateKeyResolver privateKeyResolver; @@ -105,7 +109,7 @@ public void initialize(ServiceExtensionContext context) { private DataPlaneTransferProxyReferenceService createProxyReferenceService(ServiceExtensionContext context, PrivateKey privateKey, DataEncrypter encrypter) { var tokenValiditySeconds = context.getSetting(DATA_PROXY_TOKEN_VALIDITY_SECONDS, DEFAULT_DATA_PROXY_TOKEN_VALIDITY_SECONDS); var tokenGenerationService = new TokenGenerationServiceImpl(privateKey); - return new DataPlaneTransferProxyReferenceServiceImpl(tokenGenerationService, context.getTypeManager(), tokenValiditySeconds, encrypter); + return new DataPlaneTransferProxyReferenceServiceImpl(tokenGenerationService, context.getTypeManager(), tokenValiditySeconds, encrypter, clock); } /** @@ -113,8 +117,8 @@ private DataPlaneTransferProxyReferenceService createProxyReferenceService(Servi */ private DataPlaneTransferTokenValidationApiController createTokenValidationApiController(Monitor monitor, PublicKey publicKey, DataEncrypter encrypter) { var registry = new TokenValidationRulesRegistryImpl(); - registry.addRule(new ContractValidationRule(contractNegotiationStore)); - registry.addRule(new ExpirationDateValidationRule()); + registry.addRule(new ContractValidationRule(contractNegotiationStore, clock)); + registry.addRule(new ExpirationDateValidationRule(clock)); var tokenValidationService = new TokenValidationServiceImpl(id -> publicKey, registry); return new DataPlaneTransferTokenValidationApiController(monitor, tokenValidationService, encrypter); } diff --git a/extensions/data-plane-transfer/data-plane-transfer-sync/src/main/java/org/eclipse/dataspaceconnector/transfer/dataplane/sync/proxy/DataPlaneTransferProxyReferenceServiceImpl.java b/extensions/data-plane-transfer/data-plane-transfer-sync/src/main/java/org/eclipse/dataspaceconnector/transfer/dataplane/sync/proxy/DataPlaneTransferProxyReferenceServiceImpl.java index cd43d113b6f..706e8eb4bad 100644 --- a/extensions/data-plane-transfer/data-plane-transfer-sync/src/main/java/org/eclipse/dataspaceconnector/transfer/dataplane/sync/proxy/DataPlaneTransferProxyReferenceServiceImpl.java +++ b/extensions/data-plane-transfer/data-plane-transfer-sync/src/main/java/org/eclipse/dataspaceconnector/transfer/dataplane/sync/proxy/DataPlaneTransferProxyReferenceServiceImpl.java @@ -24,7 +24,7 @@ import org.eclipse.dataspaceconnector.transfer.dataplane.spi.security.DataEncrypter; import org.jetbrains.annotations.NotNull; -import java.time.Instant; +import java.time.Clock; import java.util.Date; import java.util.HashMap; @@ -36,12 +36,14 @@ public class DataPlaneTransferProxyReferenceServiceImpl implements DataPlaneTran private final TypeManager typeManager; private final long tokenValiditySeconds; private final DataEncrypter dataEncrypter; + private final Clock clock; - public DataPlaneTransferProxyReferenceServiceImpl(TokenGenerationService tokenGenerationService, TypeManager typeManager, long tokenValiditySeconds, DataEncrypter dataEncrypter) { + public DataPlaneTransferProxyReferenceServiceImpl(TokenGenerationService tokenGenerationService, TypeManager typeManager, long tokenValiditySeconds, DataEncrypter dataEncrypter, Clock clock) { this.tokenGenerationService = tokenGenerationService; this.typeManager = typeManager; this.tokenValiditySeconds = tokenValiditySeconds; this.dataEncrypter = dataEncrypter; + this.clock = clock; } /** @@ -51,7 +53,7 @@ public DataPlaneTransferProxyReferenceServiceImpl(TokenGenerationService tokenGe @Override public Result createProxyReference(@NotNull DataPlaneTransferProxyCreationRequest request) { var encryptedDataAddress = dataEncrypter.encrypt(typeManager.writeValueAsString(request.getContentAddress())); - var decorator = new DataPlaneProxyTokenDecorator(Date.from(Instant.now().plusSeconds(tokenValiditySeconds)), request.getContractId(), encryptedDataAddress); + var decorator = new DataPlaneProxyTokenDecorator(Date.from(clock.instant().plusSeconds(tokenValiditySeconds)), request.getContractId(), encryptedDataAddress); var tokenGenerationResult = tokenGenerationService.generate(decorator); if (tokenGenerationResult.failed()) { return Result.failure(tokenGenerationResult.getFailureMessages()); diff --git a/extensions/data-plane-transfer/data-plane-transfer-sync/src/main/java/org/eclipse/dataspaceconnector/transfer/dataplane/sync/validation/ContractValidationRule.java b/extensions/data-plane-transfer/data-plane-transfer-sync/src/main/java/org/eclipse/dataspaceconnector/transfer/dataplane/sync/validation/ContractValidationRule.java index 4fd66b09c30..f90a0d41da9 100644 --- a/extensions/data-plane-transfer/data-plane-transfer-sync/src/main/java/org/eclipse/dataspaceconnector/transfer/dataplane/sync/validation/ContractValidationRule.java +++ b/extensions/data-plane-transfer/data-plane-transfer-sync/src/main/java/org/eclipse/dataspaceconnector/transfer/dataplane/sync/validation/ContractValidationRule.java @@ -23,6 +23,7 @@ import org.jetbrains.annotations.Nullable; import java.text.ParseException; +import java.time.Clock; import java.time.Instant; import java.util.Map; @@ -34,9 +35,11 @@ public class ContractValidationRule implements TokenValidationRule { private final ContractNegotiationStore contractNegotiationStore; + private final Clock clock; - public ContractValidationRule(ContractNegotiationStore contractNegotiationStore) { + public ContractValidationRule(ContractNegotiationStore contractNegotiationStore, Clock clock) { this.contractNegotiationStore = contractNegotiationStore; + this.clock = clock; } @Override @@ -57,7 +60,7 @@ public Result checkRule(@NotNull SignedJWT toVerify, @Nullable Map checkRule(@NotNull SignedJWT toVerify, @Nullable Map additional) { try { @@ -39,7 +45,7 @@ public Result checkRule(@NotNull SignedJWT toVerify, @Nullable Map> memoryDb; - public InMemoryDidDocumentStore() { - memoryDb = new CopyOnWriteArrayList<>(); + public InMemoryDidDocumentStore(Clock clock) { + this.clock = clock; + this.memoryDb = new CopyOnWriteArrayList<>(); } @Override @@ -83,8 +86,8 @@ public DidDocument forId(String did) { return result.map(didDocumentEntity -> didDocumentEntity.payload).orElse(null); } - private static class Entity implements Comparable> { - private final Instant createTime = Instant.now(); + private class Entity implements Comparable> { + private final Instant createTime = clock.instant(); private final T payload; Entity(T payload) { diff --git a/extensions/iam/decentralized-identity/identity-did-core/src/test/java/org/eclipse/dataspaceconnector/iam/did/store/InMemoryDidDocumentStoreTest.java b/extensions/iam/decentralized-identity/identity-did-core/src/test/java/org/eclipse/dataspaceconnector/iam/did/store/InMemoryDidDocumentStoreTest.java index c468546fa23..134a8273cb5 100644 --- a/extensions/iam/decentralized-identity/identity-did-core/src/test/java/org/eclipse/dataspaceconnector/iam/did/store/InMemoryDidDocumentStoreTest.java +++ b/extensions/iam/decentralized-identity/identity-did-core/src/test/java/org/eclipse/dataspaceconnector/iam/did/store/InMemoryDidDocumentStoreTest.java @@ -23,6 +23,7 @@ import org.junit.jupiter.api.Test; import java.security.SecureRandom; +import java.time.Clock; import java.util.Base64; import java.util.Collections; import java.util.Random; @@ -35,7 +36,7 @@ class InMemoryDidDocumentStoreTest { @BeforeEach void setUp() { - store = new InMemoryDidDocumentStore(); + store = new InMemoryDidDocumentStore(Clock.systemUTC()); } @Test diff --git a/extensions/iam/decentralized-identity/identity-did-crypto/src/main/java/org/eclipse/dataspaceconnector/iam/did/crypto/credentials/VerifiableCredentialFactory.java b/extensions/iam/decentralized-identity/identity-did-crypto/src/main/java/org/eclipse/dataspaceconnector/iam/did/crypto/credentials/VerifiableCredentialFactory.java index 182d7858d43..4c913c92e80 100644 --- a/extensions/iam/decentralized-identity/identity-did-crypto/src/main/java/org/eclipse/dataspaceconnector/iam/did/crypto/credentials/VerifiableCredentialFactory.java +++ b/extensions/iam/decentralized-identity/identity-did-crypto/src/main/java/org/eclipse/dataspaceconnector/iam/did/crypto/credentials/VerifiableCredentialFactory.java @@ -29,7 +29,7 @@ import org.eclipse.dataspaceconnector.iam.did.spi.key.PublicKeyWrapper; import java.text.ParseException; -import java.time.Instant; +import java.time.Clock; import java.time.temporal.ChronoUnit; import java.util.Comparator; import java.util.Date; @@ -55,12 +55,13 @@ public class VerifiableCredentialFactory { * @param privateKeyPemContent The contents of a private key stored in PEM format. * @param claims a list of key-value-pairs that contain claims * @param issuer the "owner" of the VC, in most cases this will be the connector ID. The VC will store this in the "iss" claim + * @param clock clock used to get current time * @return a {@code SignedJWT} that is signed with the private key and contains all claims listed */ - public static SignedJWT create(String privateKeyPemContent, Map claims, String issuer) { + public static SignedJWT create(String privateKeyPemContent, Map claims, String issuer, Clock clock) { try { var key = ECKey.parseFromPEMEncodedObjects(privateKeyPemContent); - return create((ECKey) key, claims, issuer); + return create((ECKey) key, claims, issuer, clock); } catch (JOSEException e) { throw new CryptoException(e); } @@ -73,10 +74,11 @@ public static SignedJWT create(String privateKeyPemContent, Map * @param privateKey A Private Key represented as {@link ECKey}. * @param claims a list of key-value-pairs that contain claims * @param issuer the "owner" of the VC, in most cases this will be the DID ID. The VC will store this in the "iss" claim + * @param clock clock used to get current time * @return a {@code SignedJWT} that is signed with the private key and contains all claims listed */ - public static SignedJWT create(ECKey privateKey, Map claims, String issuer) { - return create(new EcPrivateKeyWrapper(privateKey), claims, issuer); + public static SignedJWT create(ECKey privateKey, Map claims, String issuer, Clock clock) { + return create(new EcPrivateKeyWrapper(privateKey), claims, issuer, clock); } /** @@ -86,15 +88,16 @@ public static SignedJWT create(ECKey privateKey, Map claims, Str * @param privateKey A Private Key represented as {@link PrivateKeyWrapper}. * @param claims a list of key-value-pairs that contain claims * @param issuer the "owner" of the VC, in most cases this will be the DID ID. The VC will store this in the "iss" claim + * @param clock clock used to get current time * @return a {@code SignedJWT} that is signed with the private key and contains all claims listed */ - public static SignedJWT create(PrivateKeyWrapper privateKey, Map claims, String issuer) { + public static SignedJWT create(PrivateKeyWrapper privateKey, Map claims, String issuer, Clock clock) { var claimssetBuilder = new JWTClaimsSet.Builder(); claims.forEach(claimssetBuilder::claim); var claimsSet = claimssetBuilder.issuer(issuer) .subject("verifiable-credential") - .expirationTime(Date.from(Instant.now().plus(10, ChronoUnit.MINUTES))) + .expirationTime(Date.from(clock.instant().plus(10, ChronoUnit.MINUTES))) .jwtID(UUID.randomUUID().toString()) .build(); @@ -175,11 +178,4 @@ public static SignedJWT parse(String jwtString) { throw new CryptoException(e); } } - - /** - * A helper method to construct the name of the secret in the vault, which contains the VC. - */ - public static String getVaultSecretName(String issuer) { - return issuer + "-vc"; - } } diff --git a/extensions/iam/decentralized-identity/identity-did-crypto/src/test/java/org/eclipse/dataspaceconnector/iam/did/crypto/credentials/VerifiableCredentialFactoryTest.java b/extensions/iam/decentralized-identity/identity-did-crypto/src/test/java/org/eclipse/dataspaceconnector/iam/did/crypto/credentials/VerifiableCredentialFactoryTest.java index ecc516eba74..785421b17dd 100644 --- a/extensions/iam/decentralized-identity/identity-did-crypto/src/test/java/org/eclipse/dataspaceconnector/iam/did/crypto/credentials/VerifiableCredentialFactoryTest.java +++ b/extensions/iam/decentralized-identity/identity-did-crypto/src/test/java/org/eclipse/dataspaceconnector/iam/did/crypto/credentials/VerifiableCredentialFactoryTest.java @@ -21,15 +21,20 @@ import org.junit.jupiter.api.Test; import java.text.ParseException; +import java.time.Clock; import java.time.Instant; -import java.time.temporal.ChronoUnit; import java.util.Map; +import static java.time.ZoneOffset.UTC; +import static java.time.temporal.ChronoUnit.MINUTES; +import static java.time.temporal.ChronoUnit.SECONDS; import static org.assertj.core.api.Assertions.assertThat; class VerifiableCredentialFactoryTest { + private final Instant now = Instant.now(); + private final Clock clock = Clock.fixed(now, UTC); private ECKey privateKey; @BeforeEach @@ -42,20 +47,18 @@ void setup() throws JOSEException { @Test void createVerifiableCredential() throws ParseException { - var vc = VerifiableCredentialFactory.create(privateKey, Map.of("did-url", "someUrl"), "test-connector"); + var vc = VerifiableCredentialFactory.create(privateKey, Map.of("did-url", "someUrl"), "test-connector", clock); assertThat(vc).isNotNull(); assertThat(vc.getJWTClaimsSet().getClaim("did-url")).isEqualTo("someUrl"); assertThat(vc.getJWTClaimsSet().getClaim("iss")).isEqualTo("test-connector"); assertThat(vc.getJWTClaimsSet().getClaim("sub")).isEqualTo("verifiable-credential"); - assertThat(vc.getJWTClaimsSet().getExpirationTime()).isNotNull() - .isAfter(Instant.now()) - .isBefore(Instant.now().plus(11, ChronoUnit.MINUTES)); + assertThat(vc.getJWTClaimsSet().getExpirationTime()).isEqualTo(now.plus(10, MINUTES).truncatedTo(SECONDS)); } @Test void ensureSerialization() throws ParseException { - var vc = VerifiableCredentialFactory.create(privateKey, Map.of("did-url", "someUrl"), "test-connector"); + var vc = VerifiableCredentialFactory.create(privateKey, Map.of("did-url", "someUrl"), "test-connector", clock); assertThat(vc).isNotNull(); String jwtString = vc.serialize(); @@ -70,7 +73,7 @@ void ensureSerialization() throws ParseException { @Test void verifyJwt() throws JOSEException { - var vc = VerifiableCredentialFactory.create(privateKey, Map.of("did-url", "someUrl"), "test-connector"); + var vc = VerifiableCredentialFactory.create(privateKey, Map.of("did-url", "someUrl"), "test-connector", clock); String jwtString = vc.serialize(); //deserialize diff --git a/extensions/iam/decentralized-identity/identity-did-service/src/main/java/org/eclipse/dataspaceconnector/identity/DecentralizedIdentityService.java b/extensions/iam/decentralized-identity/identity-did-service/src/main/java/org/eclipse/dataspaceconnector/identity/DecentralizedIdentityService.java index f57ef83fbb1..ee683bf122f 100644 --- a/extensions/iam/decentralized-identity/identity-did-service/src/main/java/org/eclipse/dataspaceconnector/identity/DecentralizedIdentityService.java +++ b/extensions/iam/decentralized-identity/identity-did-service/src/main/java/org/eclipse/dataspaceconnector/identity/DecentralizedIdentityService.java @@ -34,7 +34,7 @@ import org.jetbrains.annotations.NotNull; import java.text.ParseException; -import java.util.Date; +import java.time.Clock; import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; @@ -44,12 +44,14 @@ public class DecentralizedIdentityService implements IdentityService { private final DidResolverRegistry resolverRegistry; private final CredentialsVerifier credentialsVerifier; private final Monitor monitor; + private final Clock clock; - public DecentralizedIdentityService(Supplier vcProvider, DidResolverRegistry resolverRegistry, CredentialsVerifier credentialsVerifier, Monitor monitor) { + public DecentralizedIdentityService(Supplier vcProvider, DidResolverRegistry resolverRegistry, CredentialsVerifier credentialsVerifier, Monitor monitor, Clock clock) { verifiableCredentialProvider = vcProvider; this.resolverRegistry = resolverRegistry; this.credentialsVerifier = credentialsVerifier; this.monitor = monitor; + this.clock = clock; } @Override @@ -57,7 +59,7 @@ public Result obtainClientCredentials(String scope) { var jwt = verifiableCredentialProvider.get(); var token = jwt.serialize(); - var expiration = new Date().getTime() + TimeUnit.MINUTES.toMillis(10); + var expiration = clock.millis() + TimeUnit.MINUTES.toMillis(10); return Result.success(TokenRepresentation.Builder.newInstance().token(token).expiresIn(expiration).build()); } diff --git a/extensions/iam/decentralized-identity/identity-did-service/src/main/java/org/eclipse/dataspaceconnector/identity/DecentralizedIdentityServiceExtension.java b/extensions/iam/decentralized-identity/identity-did-service/src/main/java/org/eclipse/dataspaceconnector/identity/DecentralizedIdentityServiceExtension.java index b4accc50be0..135c6b21d6e 100644 --- a/extensions/iam/decentralized-identity/identity-did-service/src/main/java/org/eclipse/dataspaceconnector/identity/DecentralizedIdentityServiceExtension.java +++ b/extensions/iam/decentralized-identity/identity-did-service/src/main/java/org/eclipse/dataspaceconnector/identity/DecentralizedIdentityServiceExtension.java @@ -27,6 +27,7 @@ import org.eclipse.dataspaceconnector.spi.system.ServiceExtension; import org.eclipse.dataspaceconnector.spi.system.ServiceExtensionContext; +import java.time.Clock; import java.util.Map; import java.util.Objects; import java.util.function.Supplier; @@ -46,6 +47,9 @@ public class DecentralizedIdentityServiceExtension implements ServiceExtension { @Inject private PrivateKeyResolver privateKeyResolver; + @Inject + private Clock clock; + @Override public String name() { return "Distributed Identity Service"; @@ -54,7 +58,7 @@ public String name() { @Override public void initialize(ServiceExtensionContext context) { var vcProvider = createSupplier(context); - var identityService = new DecentralizedIdentityService(vcProvider, resolverRegistry, credentialsVerifier, context.getMonitor()); + var identityService = new DecentralizedIdentityService(vcProvider, resolverRegistry, credentialsVerifier, context.getMonitor(), context.getClock()); context.registerService(IdentityService.class, identityService); } @@ -77,7 +81,7 @@ Supplier createSupplier(ServiceExtensionContext context) { // we cannot store the VerifiableCredential in the Vault, because it has an expiry date // the Issuer claim must contain the DID URL - return VerifiableCredentialFactory.create(privateKeyString, Map.of(VerifiableCredentialFactory.OWNER_CLAIM, connectorName), didUrl); + return VerifiableCredentialFactory.create(privateKeyString, Map.of(VerifiableCredentialFactory.OWNER_CLAIM, connectorName), didUrl, clock); }; } } diff --git a/extensions/iam/decentralized-identity/identity-did-service/src/test/java/org/eclipse/dataspaceconnector/identity/DecentralizedIdentityServiceTest.java b/extensions/iam/decentralized-identity/identity-did-service/src/test/java/org/eclipse/dataspaceconnector/identity/DecentralizedIdentityServiceTest.java index 98e4af639bd..caf0137784a 100644 --- a/extensions/iam/decentralized-identity/identity-did-service/src/test/java/org/eclipse/dataspaceconnector/identity/DecentralizedIdentityServiceTest.java +++ b/extensions/iam/decentralized-identity/identity-did-service/src/test/java/org/eclipse/dataspaceconnector/identity/DecentralizedIdentityServiceTest.java @@ -42,11 +42,14 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.time.Clock; +import java.time.Duration; +import java.time.Instant; import java.util.Date; import java.util.Map; -import java.util.concurrent.TimeUnit; import java.util.function.Supplier; +import static java.time.ZoneOffset.UTC; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; @@ -57,6 +60,8 @@ */ abstract class DecentralizedIdentityServiceTest { + private final Instant now = Instant.now(); + private final Clock clock = Clock.fixed(now, UTC); private DecentralizedIdentityService identityService; private PrivateKeyWrapper privateKey; private PublicKeyWrapper publicKey; @@ -84,11 +89,10 @@ void verifyObtainClientCredentials() throws Exception { void verifyJwtToken() throws Exception { var signer = privateKey.signer(); - var expiration = new Date().getTime() + TimeUnit.MINUTES.toMillis(10); var claimsSet = new JWTClaimsSet.Builder() .subject("foo") .issuer("did:ion:123abc") - .expirationTime(new Date(expiration)) + .expirationTime(Date.from(now.plus(Duration.ofMinutes(10)))) .build(); var jwt = new SignedJWT(new JWSHeader.Builder(getHeaderAlgorithm()).keyID("primary").build(), claimsSet); @@ -114,8 +118,8 @@ void setUp() throws Exception { DidResolverRegistry didResolver = new TestResolverRegistry(hubUrlDid, keyPair); CredentialsVerifier verifier = (document, url) -> Result.success(Map.of("region", "eu")); - Supplier signedJwtSupplier = () -> VerifiableCredentialFactory.create(privateKey, Map.of("region", "us"), "test-issuer"); - identityService = new DecentralizedIdentityService(signedJwtSupplier, didResolver, verifier, mock(Monitor.class)); + Supplier signedJwtSupplier = () -> VerifiableCredentialFactory.create(privateKey, Map.of("region", "us"), "test-issuer", clock); + identityService = new DecentralizedIdentityService(signedJwtSupplier, didResolver, verifier, mock(Monitor.class), Clock.systemUTC()); } diff --git a/extensions/iam/decentralized-identity/registration-service/src/main/java/org/eclipse/dataspaceconnector/iam/registrationservice/crawler/CrawlerContext.java b/extensions/iam/decentralized-identity/registration-service/src/main/java/org/eclipse/dataspaceconnector/iam/registrationservice/crawler/CrawlerContext.java index d0a158231b8..ce2f1225c27 100644 --- a/extensions/iam/decentralized-identity/registration-service/src/main/java/org/eclipse/dataspaceconnector/iam/registrationservice/crawler/CrawlerContext.java +++ b/extensions/iam/decentralized-identity/registration-service/src/main/java/org/eclipse/dataspaceconnector/iam/registrationservice/crawler/CrawlerContext.java @@ -20,6 +20,8 @@ import org.eclipse.dataspaceconnector.spi.monitor.Monitor; import org.eclipse.dataspaceconnector.spi.types.TypeManager; +import java.time.Clock; + /** * Stores parameters (such as the DID Type) and necessary objects (such as the IonClient or the DidStore) * for the crawler, so it is essentially a Holder which is passed through to the {@link CrawlerJob} by Quartz @@ -33,6 +35,7 @@ public class CrawlerContext { private String didTypes; private DidResolverRegistry resolverRegistry; private TypeManager typeManager; + private Clock clock; public DidStore getDidStore() { return didStore; @@ -62,6 +65,10 @@ public TypeManager getTypeManager() { return typeManager; } + public Clock getClock() { + return clock; + } + public static final class Builder { private DidStore didStore; private Monitor monitor; @@ -70,6 +77,7 @@ public static final class Builder { private String didTypes; private DidResolverRegistry resolverRegistry; private TypeManager typeManager; + private Clock clock; private Builder() { } @@ -113,12 +121,18 @@ public Builder typeManager(TypeManager typeManager) { return this; } + public Builder clock(Clock clock) { + this.clock = clock; + return this; + } + public CrawlerContext build() { CrawlerContext crawlerConfig = new CrawlerContext(); crawlerConfig.didTypes = didTypes; crawlerConfig.ionHost = ionHost; crawlerConfig.publisher = publisher; crawlerConfig.typeManager = typeManager; + crawlerConfig.clock = clock; crawlerConfig.didStore = didStore; crawlerConfig.monitor = monitor; crawlerConfig.resolverRegistry = resolverRegistry; diff --git a/extensions/iam/decentralized-identity/registration-service/src/main/java/org/eclipse/dataspaceconnector/iam/registrationservice/crawler/CrawlerExtension.java b/extensions/iam/decentralized-identity/registration-service/src/main/java/org/eclipse/dataspaceconnector/iam/registrationservice/crawler/CrawlerExtension.java index d91fae30e89..f7365fc25f4 100644 --- a/extensions/iam/decentralized-identity/registration-service/src/main/java/org/eclipse/dataspaceconnector/iam/registrationservice/crawler/CrawlerExtension.java +++ b/extensions/iam/decentralized-identity/registration-service/src/main/java/org/eclipse/dataspaceconnector/iam/registrationservice/crawler/CrawlerExtension.java @@ -31,6 +31,7 @@ import org.quartz.Trigger; import org.quartz.impl.StdSchedulerFactory; +import java.time.Clock; import java.util.Map; import static org.quartz.JobBuilder.newJob; @@ -53,6 +54,8 @@ public class CrawlerExtension implements ServiceExtension { private DidResolverRegistry resolverRegistry; @Inject private Vault vault; + @Inject + private Clock clock; @Override public void initialize(ServiceExtensionContext context) { @@ -99,6 +102,7 @@ private void scheduleCrawler(int intervalMinutes, ServiceExtensionContext contex .ionHost(context.getSetting(ION_URL_SETTING, "http://gx-ion-node.westeurope.cloudapp.azure.com:3000/")) .monitor(context.getMonitor()) .typeManager(context.getTypeManager()) + .clock(clock) .publisher(publisher) .didTypes(context.getSetting(ION_CRAWLER_TYPE_SETTING, "aW9u")) .resolverRegistry(resolverRegistry) diff --git a/extensions/iam/decentralized-identity/registration-service/src/main/java/org/eclipse/dataspaceconnector/iam/registrationservice/crawler/CrawlerJob.java b/extensions/iam/decentralized-identity/registration-service/src/main/java/org/eclipse/dataspaceconnector/iam/registrationservice/crawler/CrawlerJob.java index a001df256d6..0534718d3dc 100644 --- a/extensions/iam/decentralized-identity/registration-service/src/main/java/org/eclipse/dataspaceconnector/iam/registrationservice/crawler/CrawlerJob.java +++ b/extensions/iam/decentralized-identity/registration-service/src/main/java/org/eclipse/dataspaceconnector/iam/registrationservice/crawler/CrawlerJob.java @@ -28,8 +28,8 @@ import org.quartz.JobExecutionContext; import java.io.IOException; +import java.time.Clock; import java.time.Duration; -import java.time.Instant; import java.util.List; import java.util.Objects; import java.util.concurrent.CompletableFuture; @@ -38,12 +38,17 @@ import static java.lang.String.format; -// has to be "public", otherwise quartz won't be able to access is public class CrawlerJob implements Job { private static final String DIDS_PATH = "dids"; private String ionApiUrl; + /** + * Public no-argument constructor required by Quartz. + */ + public CrawlerJob() { + } + @Override public void execute(JobExecutionContext context) { JobDataMap jobDataMap = context.getJobDetail().getJobDataMap(); @@ -54,7 +59,8 @@ public void execute(JobExecutionContext context) { monitor.info("CrawlerJob: browsing ION to obtain GaiaX DIDs"); - var start = Instant.now(); + var clock = cc.getClock(); + var start = clock.instant(); var newDidFutures = getDidDocumentsFromBlockchainAsync(cc); List newDids = newDidFutures.parallelStream() @@ -64,7 +70,7 @@ public void execute(JobExecutionContext context) { .map(Result::getContent) .collect(Collectors.toList()); - monitor.info("CrawlerJob: Found " + newDids.size() + " new DIDs on ION, took " + (Duration.between(start, Instant.now()).toString() + monitor.info("CrawlerJob: Found " + newDids.size() + " new DIDs on ION, took " + (Duration.between(start, clock.instant()).toString() .substring(2) .replaceAll("(\\d[HMS])(?!$)", "$1 ") .toLowerCase())); @@ -87,7 +93,7 @@ private List>> getDidDocumentsFromBlockcha * queries the ION Core API that maps Bitcoin transactions to IPFS CoreIndexFiles which have a "type" field equal to * the {@code type} parameter and returns the resulting DID suffixes (=IDs). * - * @param type The type to look up. Should be "Z3hp" for GaiaX + * @param type The type to look up. Should be "Z3hp" for GaiaX * @param typeManager the type manager * @return A list of DID IDs in the form {@code did:ion:.....} */ @@ -122,7 +128,7 @@ private List getDidSuffixesForType(String type, TypeManager typeManager) /** * Attempts to resolve a DID from ION * - * @param didId The canonical ID (="suffix", "short form URI") of the DID. Must be in the form "did:ion:..." + * @param didId The canonical ID (="suffix", "short form URI") of the DID. Must be in the form "did:ion:..." * @param resolverRegistry The resolver registry * @return A {@link DidDocument} if found, {@code null} otherwise */ @@ -137,7 +143,7 @@ private Result resolveDid(String didId, DidResolverRegistry resolve /** * Attempts to resolve a DID from ION asynchronously. Basically a wrapper around {@link CrawlerJob#resolveDid(String, DidResolverRegistry)} * - * @param didId The canonical ID (="suffix", "short form URI") of the DID. Must be in the form "did:ion:..." + * @param didId The canonical ID (="suffix", "short form URI") of the DID. Must be in the form "did:ion:..." * @param resolverRegistry An ION implementation * @return A {@code CompletableFuture} if found, {@code null} otherwise */ diff --git a/extensions/iam/iam-mock/src/main/java/org/eclipse/dataspaceconnector/iam/mock/IamMockExtension.java b/extensions/iam/iam-mock/src/main/java/org/eclipse/dataspaceconnector/iam/mock/IamMockExtension.java index 9badb753d13..a1cef2a1511 100644 --- a/extensions/iam/iam-mock/src/main/java/org/eclipse/dataspaceconnector/iam/mock/IamMockExtension.java +++ b/extensions/iam/iam-mock/src/main/java/org/eclipse/dataspaceconnector/iam/mock/IamMockExtension.java @@ -33,6 +33,6 @@ public String name() { @Override public void initialize(ServiceExtensionContext context) { var region = context.getSetting("edc.mock.region", "eu"); - context.registerService(IdentityService.class, new MockIdentityService(region)); + context.registerService(IdentityService.class, new MockIdentityService(context.getClock(), region)); } } diff --git a/extensions/iam/iam-mock/src/main/java/org/eclipse/dataspaceconnector/iam/mock/MockIdentityService.java b/extensions/iam/iam-mock/src/main/java/org/eclipse/dataspaceconnector/iam/mock/MockIdentityService.java index a9f9a6ee55b..8c973a2feb7 100644 --- a/extensions/iam/iam-mock/src/main/java/org/eclipse/dataspaceconnector/iam/mock/MockIdentityService.java +++ b/extensions/iam/iam-mock/src/main/java/org/eclipse/dataspaceconnector/iam/mock/MockIdentityService.java @@ -20,12 +20,14 @@ import org.eclipse.dataspaceconnector.spi.iam.TokenRepresentation; import org.eclipse.dataspaceconnector.spi.result.Result; -import java.time.Instant; +import java.time.Clock; public class MockIdentityService implements IdentityService { private final String region; + private final Clock clock; - public MockIdentityService(String region) { + public MockIdentityService(Clock clock, String region) { + this.clock = clock; this.region = region; } @@ -33,7 +35,7 @@ public MockIdentityService(String region) { public Result obtainClientCredentials(String scope) { TokenRepresentation tokenRepresentation = TokenRepresentation.Builder.newInstance() .token("mock-" + region) - .expiresIn(Instant.now().plusSeconds(10_0000).toEpochMilli()) + .expiresIn(clock.instant().plusSeconds(10_0000).toEpochMilli()) .build(); return Result.success(tokenRepresentation); } diff --git a/extensions/iam/oauth2/oauth2-core/src/main/java/org/eclipse/dataspaceconnector/iam/oauth2/core/Oauth2Extension.java b/extensions/iam/oauth2/oauth2-core/src/main/java/org/eclipse/dataspaceconnector/iam/oauth2/core/Oauth2Extension.java index cc353b044d8..1a45919f1e1 100644 --- a/extensions/iam/oauth2/oauth2-core/src/main/java/org/eclipse/dataspaceconnector/iam/oauth2/core/Oauth2Extension.java +++ b/extensions/iam/oauth2/oauth2-core/src/main/java/org/eclipse/dataspaceconnector/iam/oauth2/core/Oauth2Extension.java @@ -38,6 +38,7 @@ import java.security.PrivateKey; import java.security.cert.CertificateEncodingException; +import java.time.Clock; import java.util.concurrent.TimeUnit; /** @@ -83,6 +84,9 @@ public class Oauth2Extension implements ServiceExtension { @Inject private CertificateResolver certificateResolver; + @Inject + private Clock clock; + @Override public String name() { return "OAuth2"; @@ -97,12 +101,12 @@ public void initialize(ServiceExtensionContext context) { var configuration = createConfig(context); - var defaultDecorator = new DefaultJwtDecorator(configuration.getProviderAudience(), configuration.getClientId(), getEncodedClientCertificate(configuration), TOKEN_EXPIRATION); + var defaultDecorator = new DefaultJwtDecorator(configuration.getProviderAudience(), configuration.getClientId(), getEncodedClientCertificate(configuration), context.getClock(), TOKEN_EXPIRATION); var jwtDecoratorRegistry = new Oauth2JwtDecoratorRegistryRegistryImpl(); jwtDecoratorRegistry.register(defaultDecorator); context.registerService(Oauth2JwtDecoratorRegistry.class, jwtDecoratorRegistry); - var validationRulesRegistry = new Oauth2ValidationRulesRegistryImpl(configuration); + var validationRulesRegistry = new Oauth2ValidationRulesRegistryImpl(configuration, clock); context.registerService(Oauth2ValidationRulesRegistry.class, validationRulesRegistry); var tokenValidationService = new TokenValidationServiceImpl(configuration.getIdentityProviderKeyResolver(), validationRulesRegistry); diff --git a/extensions/iam/oauth2/oauth2-core/src/main/java/org/eclipse/dataspaceconnector/iam/oauth2/core/jwt/DefaultJwtDecorator.java b/extensions/iam/oauth2/oauth2-core/src/main/java/org/eclipse/dataspaceconnector/iam/oauth2/core/jwt/DefaultJwtDecorator.java index e4e8fd54778..cc928a24f62 100644 --- a/extensions/iam/oauth2/oauth2-core/src/main/java/org/eclipse/dataspaceconnector/iam/oauth2/core/jwt/DefaultJwtDecorator.java +++ b/extensions/iam/oauth2/oauth2-core/src/main/java/org/eclipse/dataspaceconnector/iam/oauth2/core/jwt/DefaultJwtDecorator.java @@ -19,7 +19,7 @@ import com.nimbusds.jwt.JWTClaimsSet; import org.eclipse.dataspaceconnector.common.token.JwtDecorator; -import java.time.Instant; +import java.time.Clock; import java.util.Date; import java.util.UUID; @@ -30,12 +30,14 @@ public class DefaultJwtDecorator implements JwtDecorator { private final String audience; private final String clientId; private final byte[] encodedCertificate; + private final Clock clock; private final long expiration; - public DefaultJwtDecorator(String audience, String clientId, byte[] encodedCertificate, long expiration) { + public DefaultJwtDecorator(String audience, String clientId, byte[] encodedCertificate, Clock clock, long expiration) { this.audience = audience; this.clientId = clientId; this.encodedCertificate = encodedCertificate; + this.clock = clock; this.expiration = expiration; } @@ -46,8 +48,7 @@ public void decorate(JWSHeader.Builder header, JWTClaimsSet.Builder claimsSet) { .issuer(clientId) .subject(clientId) .jwtID(UUID.randomUUID().toString()) - .notBeforeTime(new Date()) - .issueTime(new Date()) - .expirationTime(Date.from(Instant.now().plusSeconds(expiration))); + .issueTime(Date.from(clock.instant())) + .expirationTime(Date.from(clock.instant().plusSeconds(expiration))); } } diff --git a/extensions/iam/oauth2/oauth2-core/src/main/java/org/eclipse/dataspaceconnector/iam/oauth2/core/rule/Oauth2ValidationRule.java b/extensions/iam/oauth2/oauth2-core/src/main/java/org/eclipse/dataspaceconnector/iam/oauth2/core/rule/Oauth2ValidationRule.java index f4721247003..e7ca7fd1ddd 100644 --- a/extensions/iam/oauth2/oauth2-core/src/main/java/org/eclipse/dataspaceconnector/iam/oauth2/core/rule/Oauth2ValidationRule.java +++ b/extensions/iam/oauth2/oauth2-core/src/main/java/org/eclipse/dataspaceconnector/iam/oauth2/core/rule/Oauth2ValidationRule.java @@ -23,6 +23,7 @@ import org.jetbrains.annotations.Nullable; import java.text.ParseException; +import java.time.Clock; import java.time.Instant; import java.time.ZonedDateTime; import java.util.ArrayList; @@ -34,9 +35,11 @@ public class Oauth2ValidationRule implements TokenValidationRule { private final Oauth2Configuration configuration; + private final Clock clock; - public Oauth2ValidationRule(Oauth2Configuration configuration) { + public Oauth2ValidationRule(Oauth2Configuration configuration, Clock clock) { this.configuration = configuration; + this.clock = clock; } /** @@ -58,8 +61,8 @@ public Result checkRule(SignedJWT toVerify, @Nullable Map checkRule(SignedJWT toVerify, @Nullable Map checkRule(SignedJWT toVerify, @Nullable Map assertDatesAreClose((Date) issueDate, Date.from(now))) - .hasEntrySatisfying("nbf", notBefore -> assertDatesAreClose((Date) notBefore, Date.from(now))) - .hasEntrySatisfying("exp", expiration -> assertDatesAreClose((Date) expiration, Date.from(now.plusSeconds(TOKEN_EXPIRATION)))); + .hasEntrySatisfying("iat", issueDate -> assertDateIs((Date) issueDate, now)) + .hasEntrySatisfying("exp", expiration -> assertDateIs((Date) expiration, now.plusSeconds(TOKEN_EXPIRATION))); } - private static void assertDatesAreClose(Date date1, Date date2) { - assertThat(date1).isCloseTo(date2, DELTA_MILLISECONDS); + private static void assertDateIs(Date date1, Instant date2) { + assertThat(date1).isEqualTo(Date.from(date2)); } } \ No newline at end of file diff --git a/extensions/iam/oauth2/oauth2-core/src/test/java/org/eclipse/dataspaceconnector/iam/oauth2/core/jwt/Oauth2ValidationRuleTest.java b/extensions/iam/oauth2/oauth2-core/src/test/java/org/eclipse/dataspaceconnector/iam/oauth2/core/jwt/Oauth2ValidationRuleTest.java index b1fdcea8810..714e9c2c41c 100644 --- a/extensions/iam/oauth2/oauth2-core/src/test/java/org/eclipse/dataspaceconnector/iam/oauth2/core/jwt/Oauth2ValidationRuleTest.java +++ b/extensions/iam/oauth2/oauth2-core/src/test/java/org/eclipse/dataspaceconnector/iam/oauth2/core/jwt/Oauth2ValidationRuleTest.java @@ -24,22 +24,25 @@ import org.junit.jupiter.api.Test; import java.sql.Date; +import java.time.Clock; import java.time.Instant; import java.time.temporal.ChronoUnit; +import static java.time.ZoneOffset.UTC; import static org.assertj.core.api.Assertions.assertThat; class Oauth2ValidationRuleTest { public static final String TEST_AUDIENCE = "test-audience"; private final Instant now = Instant.now().truncatedTo(ChronoUnit.SECONDS); + private final Clock clock = Clock.fixed(now, UTC); private Oauth2ValidationRule rule; private JWSHeader jwsHeader; @BeforeEach public void setUp() { var configuration = Oauth2Configuration.Builder.newInstance().providerAudience("test-audience").build(); - rule = new Oauth2ValidationRule(configuration); + rule = new Oauth2ValidationRule(configuration, clock); jwsHeader = new JWSHeader.Builder(JWSAlgorithm.RS256).build(); } @@ -147,7 +150,7 @@ void validationOkWhenLeewayOnNotBefore() { .providerAudience(TEST_AUDIENCE) .notBeforeValidationLeeway(20) .build(); - rule = new Oauth2ValidationRule(configuration); + rule = new Oauth2ValidationRule(configuration, clock); var jwt = new SignedJWT(jwsHeader, claims); var result = rule.checkRule(jwt); diff --git a/extensions/sql/contract-negotiation-store-sql/src/main/java/org/eclipse/dataspaceconnector/sql/contractnegotiation/SqlContractNegotiationStoreExtension.java b/extensions/sql/contract-negotiation-store-sql/src/main/java/org/eclipse/dataspaceconnector/sql/contractnegotiation/SqlContractNegotiationStoreExtension.java index 51ae2c400e7..9f4b1fe5314 100644 --- a/extensions/sql/contract-negotiation-store-sql/src/main/java/org/eclipse/dataspaceconnector/sql/contractnegotiation/SqlContractNegotiationStoreExtension.java +++ b/extensions/sql/contract-negotiation-store-sql/src/main/java/org/eclipse/dataspaceconnector/sql/contractnegotiation/SqlContractNegotiationStoreExtension.java @@ -25,6 +25,8 @@ import org.eclipse.dataspaceconnector.sql.contractnegotiation.store.PostgresStatements; import org.eclipse.dataspaceconnector.sql.contractnegotiation.store.SqlContractNegotiationStore; +import java.time.Clock; + @Provides({ ContractNegotiationStore.class }) public class SqlContractNegotiationStoreExtension implements ServiceExtension { @@ -37,12 +39,15 @@ public class SqlContractNegotiationStoreExtension implements ServiceExtension { @Inject private TransactionContext trxContext; + @Inject + private Clock clock; + @Inject(required = false) private ContractNegotiationStatements statements; @Override public void initialize(ServiceExtensionContext context) { - var sqlStore = new SqlContractNegotiationStore(dataSourceRegistry, getDataSourceName(context), trxContext, context.getTypeManager(), getStatementImpl(), context.getConnectorId()); + var sqlStore = new SqlContractNegotiationStore(dataSourceRegistry, getDataSourceName(context), trxContext, context.getTypeManager(), getStatementImpl(), context.getConnectorId(), clock); context.registerService(ContractNegotiationStore.class, sqlStore); } diff --git a/extensions/sql/contract-negotiation-store-sql/src/main/java/org/eclipse/dataspaceconnector/sql/contractnegotiation/store/SqlContractNegotiationStore.java b/extensions/sql/contract-negotiation-store-sql/src/main/java/org/eclipse/dataspaceconnector/sql/contractnegotiation/store/SqlContractNegotiationStore.java index 22836de3f71..e337359d01a 100644 --- a/extensions/sql/contract-negotiation-store-sql/src/main/java/org/eclipse/dataspaceconnector/sql/contractnegotiation/store/SqlContractNegotiationStore.java +++ b/extensions/sql/contract-negotiation-store-sql/src/main/java/org/eclipse/dataspaceconnector/sql/contractnegotiation/store/SqlContractNegotiationStore.java @@ -28,14 +28,14 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.sql.DataSource; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; -import java.time.Instant; +import java.time.Clock; import java.util.List; import java.util.Objects; import java.util.stream.Stream; -import javax.sql.DataSource; import static java.lang.String.format; import static java.util.Optional.ofNullable; @@ -52,14 +52,16 @@ public class SqlContractNegotiationStore implements ContractNegotiationStore { private final TransactionContext transactionContext; private final ContractNegotiationStatements statements; private final SqlLeaseContextBuilder leaseContext; + private final Clock clock; - public SqlContractNegotiationStore(DataSourceRegistry dataSourceRegistry, String dataSourceName, TransactionContext transactionContext, TypeManager manager, ContractNegotiationStatements statements, String connectorId) { + public SqlContractNegotiationStore(DataSourceRegistry dataSourceRegistry, String dataSourceName, TransactionContext transactionContext, TypeManager manager, ContractNegotiationStatements statements, String connectorId, Clock clock) { typeManager = manager; this.dataSourceRegistry = dataSourceRegistry; this.dataSourceName = dataSourceName; this.transactionContext = transactionContext; this.statements = statements; - leaseContext = SqlLeaseContextBuilder.with(transactionContext, connectorId, statements); + this.clock = clock; + leaseContext = SqlLeaseContextBuilder.with(transactionContext, connectorId, statements, clock); } @Override @@ -196,7 +198,7 @@ public void delete(String negotiationId) { return transactionContext.execute(() -> { try (var connection = getConnection()) { var stmt = statements.getNextForStateTemplate(); - var negotiations = executeQuery(connection, this::mapContractNegotiation, stmt, state, Instant.now().toEpochMilli(), max); + var negotiations = executeQuery(connection, this::mapContractNegotiation, stmt, state, clock.millis(), max); negotiations.forEach(cn -> leaseContext.withConnection(connection).acquireLease(cn.getId())); return negotiations; diff --git a/extensions/sql/contract-negotiation-store-sql/src/test/java/org/eclipse/dataspaceconnector/sql/contractnegotiation/store/SqlContractNegotiationStoreTest.java b/extensions/sql/contract-negotiation-store-sql/src/test/java/org/eclipse/dataspaceconnector/sql/contractnegotiation/store/SqlContractNegotiationStoreTest.java index 2f2533a21e2..2c16109fead 100644 --- a/extensions/sql/contract-negotiation-store-sql/src/test/java/org/eclipse/dataspaceconnector/sql/contractnegotiation/store/SqlContractNegotiationStoreTest.java +++ b/extensions/sql/contract-negotiation-store-sql/src/test/java/org/eclipse/dataspaceconnector/sql/contractnegotiation/store/SqlContractNegotiationStoreTest.java @@ -37,6 +37,7 @@ import java.nio.file.Paths; import java.sql.Connection; import java.sql.SQLException; +import java.time.Clock; import java.time.Duration; import java.util.Objects; import java.util.UUID; @@ -85,12 +86,12 @@ void setUp() throws SQLException, IOException { TypeManager manager = new TypeManager(); manager.registerTypes(PolicyRegistrationTypes.TYPES.toArray(Class[]::new)); - store = new SqlContractNegotiationStore(dataSourceRegistry, DATASOURCE_NAME, txManager, manager, statements, CONNECTOR_NAME); + store = new SqlContractNegotiationStore(dataSourceRegistry, DATASOURCE_NAME, txManager, manager, statements, CONNECTOR_NAME, Clock.systemUTC()); var schema = Files.readString(Paths.get("./docs/schema.sql")); txManager.execute(() -> SqlQueryExecutor.executeQuery(connection, schema)); - leaseUtil = new LeaseUtil(txManager, this::getConnection, statements); + leaseUtil = new LeaseUtil(txManager, this::getConnection, statements, Clock.systemUTC()); } @AfterEach diff --git a/extensions/sql/lease-sql/src/main/java/org/eclipse/dataspaceconnector/sql/lease/SqlLease.java b/extensions/sql/lease-sql/src/main/java/org/eclipse/dataspaceconnector/sql/lease/SqlLease.java index 4e850dd57ef..f65d1215801 100644 --- a/extensions/sql/lease-sql/src/main/java/org/eclipse/dataspaceconnector/sql/lease/SqlLease.java +++ b/extensions/sql/lease-sql/src/main/java/org/eclipse/dataspaceconnector/sql/lease/SqlLease.java @@ -16,6 +16,7 @@ import org.eclipse.dataspaceconnector.spi.persistence.Lease; +import java.time.Clock; import java.time.Instant; /** @@ -36,7 +37,7 @@ public void setLeaseId(String leaseId) { this.leaseId = leaseId; } - public boolean isExpired() { - return getLeasedAt() + getLeaseDuration() < Instant.now().toEpochMilli(); + public boolean isExpired(Clock clock) { + return getLeasedAt() + getLeaseDuration() < clock.millis(); } } diff --git a/extensions/sql/lease-sql/src/main/java/org/eclipse/dataspaceconnector/sql/lease/SqlLeaseContext.java b/extensions/sql/lease-sql/src/main/java/org/eclipse/dataspaceconnector/sql/lease/SqlLeaseContext.java index 4452195191a..9142e2bc1dc 100644 --- a/extensions/sql/lease-sql/src/main/java/org/eclipse/dataspaceconnector/sql/lease/SqlLeaseContext.java +++ b/extensions/sql/lease-sql/src/main/java/org/eclipse/dataspaceconnector/sql/lease/SqlLeaseContext.java @@ -22,8 +22,8 @@ import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; +import java.time.Clock; import java.time.Duration; -import java.time.Instant; import java.util.Objects; import java.util.UUID; @@ -40,13 +40,15 @@ public class SqlLeaseContext implements LeaseContext { private final LeaseStatements statements; private final String leaseHolder; private final Connection connection; + private final Clock clock; private final Duration leaseDuration; - SqlLeaseContext(TransactionContext trxContext, LeaseStatements statements, String leaseHolder, Duration leaseDuration, Connection connection) { + SqlLeaseContext(TransactionContext trxContext, LeaseStatements statements, String leaseHolder, Clock clock, Duration leaseDuration, Connection connection) { this.trxContext = trxContext; this.statements = statements; this.leaseHolder = leaseHolder; + this.clock = clock; this.leaseDuration = leaseDuration; this.connection = connection; } @@ -71,11 +73,11 @@ public void breakLease(String entityId) { @Override public void acquireLease(String entityId) { trxContext.execute(() -> { - var now = Instant.now().toEpochMilli(); + var now = clock.millis(); var lease = getLease(entityId); - if (lease != null && !lease.isExpired()) { + if (lease != null && !lease.isExpired(clock)) { throw new IllegalStateException("Entity is currently leased!"); } diff --git a/extensions/sql/lease-sql/src/main/java/org/eclipse/dataspaceconnector/sql/lease/SqlLeaseContextBuilder.java b/extensions/sql/lease-sql/src/main/java/org/eclipse/dataspaceconnector/sql/lease/SqlLeaseContextBuilder.java index b356b16d21c..6f44b12503b 100644 --- a/extensions/sql/lease-sql/src/main/java/org/eclipse/dataspaceconnector/sql/lease/SqlLeaseContextBuilder.java +++ b/extensions/sql/lease-sql/src/main/java/org/eclipse/dataspaceconnector/sql/lease/SqlLeaseContextBuilder.java @@ -17,6 +17,7 @@ import org.eclipse.dataspaceconnector.spi.transaction.TransactionContext; import java.sql.Connection; +import java.time.Clock; import java.time.Duration; import java.util.Objects; @@ -41,20 +42,22 @@ public class SqlLeaseContextBuilder { private final TransactionContext trxContext; private final LeaseStatements statements; + private final Clock clock; private String leaseHolder; private Duration leaseDuration; - private SqlLeaseContextBuilder(TransactionContext trxContext, LeaseStatements statements, String leaseHolder) { + private SqlLeaseContextBuilder(TransactionContext trxContext, LeaseStatements statements, String leaseHolder, Clock clock) { this.trxContext = trxContext; this.statements = statements; this.leaseHolder = leaseHolder; + this.clock = clock; } - public static SqlLeaseContextBuilder with(TransactionContext trxContext, String leaseHolder, LeaseStatements statements) { + public static SqlLeaseContextBuilder with(TransactionContext trxContext, String leaseHolder, LeaseStatements statements, Clock clock) { Objects.requireNonNull(trxContext, "trxContext"); Objects.requireNonNull(leaseHolder, "leaseHolder"); Objects.requireNonNull(statements, "statements"); - return new SqlLeaseContextBuilder(trxContext, statements, leaseHolder); + return new SqlLeaseContextBuilder(trxContext, statements, leaseHolder, clock); } /** @@ -79,6 +82,6 @@ public SqlLeaseContextBuilder forTime(Duration duration) { */ public SqlLeaseContext withConnection(Connection connection) { Objects.requireNonNull(connection, "connection"); - return new SqlLeaseContext(trxContext, statements, leaseHolder, leaseDuration, connection); + return new SqlLeaseContext(trxContext, statements, leaseHolder, clock, leaseDuration, connection); } } diff --git a/extensions/sql/lease-sql/src/test/java/org/eclipse/dataspaceconnector/sql/lease/SqlLeaseContextTest.java b/extensions/sql/lease-sql/src/test/java/org/eclipse/dataspaceconnector/sql/lease/SqlLeaseContextTest.java index 4958aeab79e..577ffae4677 100644 --- a/extensions/sql/lease-sql/src/test/java/org/eclipse/dataspaceconnector/sql/lease/SqlLeaseContextTest.java +++ b/extensions/sql/lease-sql/src/test/java/org/eclipse/dataspaceconnector/sql/lease/SqlLeaseContextTest.java @@ -28,9 +28,11 @@ import java.nio.charset.StandardCharsets; import java.sql.Connection; import java.sql.SQLException; +import java.time.Clock; import java.time.Instant; import java.util.Objects; +import static java.time.ZoneOffset.UTC; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.eclipse.dataspaceconnector.sql.SqlQueryExecutor.executeQuery; @@ -41,6 +43,7 @@ class SqlLeaseContextTest { private static final String DATASOURCE_NAME = "lease-test"; private static final String LEASE_HOLDER = "test-leaser"; + private Instant now = Instant.now(); private SqlLeaseContext leaseContext; private Connection connection; private TransactionContext transactionContext; @@ -66,7 +69,7 @@ void setUp() throws SQLException { throw new RuntimeException(e); } var statements = new TestEntityLeaseStatements(); - builder = SqlLeaseContextBuilder.with(transactionContext, LEASE_HOLDER, statements); + builder = SqlLeaseContextBuilder.with(transactionContext, LEASE_HOLDER, statements, Clock.fixed(now, UTC)); leaseContext = builder.withConnection(connection); } @@ -109,7 +112,7 @@ void acquireLease() { var leaseAssert = assertThat(leaseContext.getLease(id)); leaseAssert.extracting(SqlLease::getLeaseId).isNotNull(); leaseAssert.extracting(SqlLease::getLeasedBy).isEqualTo(LEASE_HOLDER); - leaseAssert.extracting(SqlLease::getLeasedAt).matches(l -> l <= Instant.now().toEpochMilli()); + leaseAssert.extracting(SqlLease::getLeasedAt).matches(l -> l <= now.toEpochMilli()); leaseAssert.extracting(SqlLease::getLeaseDuration).isEqualTo(60_000L); } diff --git a/extensions/sql/lease-sql/src/testFixtures/java/org/eclipse/dataspaceconnector/sql/lease/LeaseUtil.java b/extensions/sql/lease-sql/src/testFixtures/java/org/eclipse/dataspaceconnector/sql/lease/LeaseUtil.java index 3d7a8881ef6..57d57234594 100644 --- a/extensions/sql/lease-sql/src/testFixtures/java/org/eclipse/dataspaceconnector/sql/lease/LeaseUtil.java +++ b/extensions/sql/lease-sql/src/testFixtures/java/org/eclipse/dataspaceconnector/sql/lease/LeaseUtil.java @@ -18,6 +18,7 @@ import java.sql.Connection; import java.sql.SQLException; +import java.time.Clock; import java.time.Duration; import java.util.function.Supplier; @@ -30,9 +31,9 @@ public class LeaseUtil { private final SqlLeaseContextBuilder leaseContextBuilder; private final Supplier connectionSupplier; - public LeaseUtil(TransactionContext context, Supplier connectionSupplier, LeaseStatements statements) { + public LeaseUtil(TransactionContext context, Supplier connectionSupplier, LeaseStatements statements, Clock clock) { this.connectionSupplier = connectionSupplier; - leaseContextBuilder = SqlLeaseContextBuilder.with(context, "test", statements); + leaseContextBuilder = SqlLeaseContextBuilder.with(context, "test", statements, clock); } public void leaseEntity(String tpId, String leaseHolder) { diff --git a/extensions/sql/transfer-process-store-sql/src/main/java/org/eclipse/dataspaceconnector/sql/transferprocess/SqlTransferProcessStoreExtension.java b/extensions/sql/transfer-process-store-sql/src/main/java/org/eclipse/dataspaceconnector/sql/transferprocess/SqlTransferProcessStoreExtension.java index 4a49d4a0d37..be4ad8b1cab 100644 --- a/extensions/sql/transfer-process-store-sql/src/main/java/org/eclipse/dataspaceconnector/sql/transferprocess/SqlTransferProcessStoreExtension.java +++ b/extensions/sql/transfer-process-store-sql/src/main/java/org/eclipse/dataspaceconnector/sql/transferprocess/SqlTransferProcessStoreExtension.java @@ -26,6 +26,8 @@ import org.eclipse.dataspaceconnector.sql.transferprocess.store.SqlTransferProcessStore; import org.eclipse.dataspaceconnector.sql.transferprocess.store.TransferProcessStoreStatements; +import java.time.Clock; + @Provides(TransferProcessStore.class) public class SqlTransferProcessStoreExtension implements ServiceExtension { @@ -37,13 +39,15 @@ public class SqlTransferProcessStoreExtension implements ServiceExtension { private DataSourceRegistry dataSourceRegistry; @Inject private TransactionContext trxContext; + @Inject + private Clock clock; @Inject(required = false) private TransferProcessStoreStatements statements; @Override public void initialize(ServiceExtensionContext context) { - var store = new SqlTransferProcessStore(dataSourceRegistry, getDataSourceName(context), trxContext, context.getTypeManager().getMapper(), getStatementImpl(), context.getConnectorId()); + var store = new SqlTransferProcessStore(dataSourceRegistry, getDataSourceName(context), trxContext, context.getTypeManager().getMapper(), getStatementImpl(), context.getConnectorId(), clock); context.registerService(TransferProcessStore.class, store); } diff --git a/extensions/sql/transfer-process-store-sql/src/main/java/org/eclipse/dataspaceconnector/sql/transferprocess/store/SqlTransferProcessStore.java b/extensions/sql/transfer-process-store-sql/src/main/java/org/eclipse/dataspaceconnector/sql/transferprocess/store/SqlTransferProcessStore.java index c557c4d4177..83378e9fa63 100644 --- a/extensions/sql/transfer-process-store-sql/src/main/java/org/eclipse/dataspaceconnector/sql/transferprocess/store/SqlTransferProcessStore.java +++ b/extensions/sql/transfer-process-store-sql/src/main/java/org/eclipse/dataspaceconnector/sql/transferprocess/store/SqlTransferProcessStore.java @@ -36,7 +36,7 @@ import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; -import java.time.Instant; +import java.time.Clock; import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; @@ -53,22 +53,23 @@ public class SqlTransferProcessStore implements TransferProcessStore { private final TransferProcessStoreStatements statements; private final String leaseHolderName; private final SqlLeaseContextBuilder leaseContext; + private final Clock clock; - public SqlTransferProcessStore(DataSourceRegistry dataSourceRegistry, String datasourceName, TransactionContext transactionContext, ObjectMapper objectMapper, TransferProcessStoreStatements statements, String leaseHolderName) { - + public SqlTransferProcessStore(DataSourceRegistry dataSourceRegistry, String datasourceName, TransactionContext transactionContext, ObjectMapper objectMapper, TransferProcessStoreStatements statements, String leaseHolderName, Clock clock) { this.dataSourceRegistry = dataSourceRegistry; this.datasourceName = datasourceName; this.transactionContext = transactionContext; this.objectMapper = objectMapper; this.statements = statements; this.leaseHolderName = leaseHolderName; - leaseContext = SqlLeaseContextBuilder.with(transactionContext, leaseHolderName, statements); + this.clock = clock; + leaseContext = SqlLeaseContextBuilder.with(transactionContext, leaseHolderName, statements, clock); } @Override public @NotNull List nextForState(int state, int max) { var list = new ArrayList(); - var now = Instant.now().toEpochMilli(); + var now = clock.millis(); transactionContext.execute(() -> { try (var conn = getConnection()) { var stmt = statements.getNextForStateTemplate(); diff --git a/extensions/sql/transfer-process-store-sql/src/test/java/org/eclipse/dataspaceconnector/sql/transferprocess/store/SqlTransferProcessStoreTest.java b/extensions/sql/transfer-process-store-sql/src/test/java/org/eclipse/dataspaceconnector/sql/transferprocess/store/SqlTransferProcessStoreTest.java index fc834812598..769e71aced6 100644 --- a/extensions/sql/transfer-process-store-sql/src/test/java/org/eclipse/dataspaceconnector/sql/transferprocess/store/SqlTransferProcessStoreTest.java +++ b/extensions/sql/transfer-process-store-sql/src/test/java/org/eclipse/dataspaceconnector/sql/transferprocess/store/SqlTransferProcessStoreTest.java @@ -34,6 +34,7 @@ import java.nio.file.Paths; import java.sql.Connection; import java.sql.SQLException; +import java.time.Clock; import java.time.Duration; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -77,12 +78,12 @@ void setUp() throws SQLException, IOException { when(datasourceMock.getConnection()).thenReturn(connection); when(dataSourceRegistry.resolve(DATASOURCE_NAME)).thenReturn(datasourceMock); var statements = new PostgresStatements(); - store = new SqlTransferProcessStore(dataSourceRegistry, DATASOURCE_NAME, transactionContext, new ObjectMapper(), statements, CONNECTOR_NAME); + store = new SqlTransferProcessStore(dataSourceRegistry, DATASOURCE_NAME, transactionContext, new ObjectMapper(), statements, CONNECTOR_NAME, Clock.systemUTC()); var schema = Files.readString(Paths.get("./docs/schema.sql")); transactionContext.execute(() -> SqlQueryExecutor.executeQuery(connection, schema)); - leaseUtil = new LeaseUtil(transactionContext, this::getConnection, statements); + leaseUtil = new LeaseUtil(transactionContext, this::getConnection, statements, Clock.systemUTC()); } diff --git a/samples/04.2-modify-transferprocess/simulator/src/main/java/org/eclipse/dataspaceconnector/samples/sample042/TransferSimulationExtension.java b/samples/04.2-modify-transferprocess/simulator/src/main/java/org/eclipse/dataspaceconnector/samples/sample042/TransferSimulationExtension.java index 14beed1d288..e3e55c1c3b1 100644 --- a/samples/04.2-modify-transferprocess/simulator/src/main/java/org/eclipse/dataspaceconnector/samples/sample042/TransferSimulationExtension.java +++ b/samples/04.2-modify-transferprocess/simulator/src/main/java/org/eclipse/dataspaceconnector/samples/sample042/TransferSimulationExtension.java @@ -51,7 +51,7 @@ public void run() { .id("tp-sample-04.2") .dataRequest(getRequest()) .state(TransferProcessStates.IN_PROGRESS.code()) - .stateTimestamp(System.currentTimeMillis() - ALMOST_TEN_MINUTES) + .stateTimestamp(context.getClock().millis() - ALMOST_TEN_MINUTES) .build(); tp.addProvisionedResource(createDummyResource()); diff --git a/samples/04.2-modify-transferprocess/watchdog/src/main/java/org/eclipse/dataspaceconnector/samples/sample042/CheckTimeoutCommandHandler.java b/samples/04.2-modify-transferprocess/watchdog/src/main/java/org/eclipse/dataspaceconnector/samples/sample042/CheckTimeoutCommandHandler.java index 7b68fb466ea..bc61b2dbb6a 100644 --- a/samples/04.2-modify-transferprocess/watchdog/src/main/java/org/eclipse/dataspaceconnector/samples/sample042/CheckTimeoutCommandHandler.java +++ b/samples/04.2-modify-transferprocess/watchdog/src/main/java/org/eclipse/dataspaceconnector/samples/sample042/CheckTimeoutCommandHandler.java @@ -18,18 +18,20 @@ import org.eclipse.dataspaceconnector.spi.monitor.Monitor; import org.eclipse.dataspaceconnector.spi.transfer.store.TransferProcessStore; +import java.time.Clock; import java.time.Duration; import static java.lang.String.format; -import static java.time.Instant.now; import static java.time.Instant.ofEpochMilli; public class CheckTimeoutCommandHandler implements CommandHandler { private final TransferProcessStore store; private final Monitor monitor; + private final Clock clock; - public CheckTimeoutCommandHandler(TransferProcessStore store, Monitor monitor) { + public CheckTimeoutCommandHandler(TransferProcessStore store, Clock clock, Monitor monitor) { this.store = store; + this.clock = clock; this.monitor = monitor; } @@ -52,7 +54,7 @@ public Class getType() { } private boolean isExpired(long stateTimestamp, Duration maxAge) { - return ofEpochMilli(stateTimestamp).isBefore(now().minus(maxAge)); + return ofEpochMilli(stateTimestamp).isBefore(clock.instant().minus(maxAge)); } } diff --git a/samples/04.2-modify-transferprocess/watchdog/src/main/java/org/eclipse/dataspaceconnector/samples/sample042/WatchdogExtension.java b/samples/04.2-modify-transferprocess/watchdog/src/main/java/org/eclipse/dataspaceconnector/samples/sample042/WatchdogExtension.java index eb6d5a1bd23..100892f3104 100644 --- a/samples/04.2-modify-transferprocess/watchdog/src/main/java/org/eclipse/dataspaceconnector/samples/sample042/WatchdogExtension.java +++ b/samples/04.2-modify-transferprocess/watchdog/src/main/java/org/eclipse/dataspaceconnector/samples/sample042/WatchdogExtension.java @@ -35,7 +35,7 @@ public class WatchdogExtension implements ServiceExtension { @Override public void initialize(ServiceExtensionContext context) { - commandHandlerRegistry.register(new CheckTimeoutCommandHandler(store, context.getMonitor())); + commandHandlerRegistry.register(new CheckTimeoutCommandHandler(store, context.getClock(), context.getMonitor())); wd = new Watchdog(manager, context.getMonitor()); } diff --git a/spi/contract-spi/src/main/java/org/eclipse/dataspaceconnector/spi/types/domain/contract/negotiation/ContractNegotiation.java b/spi/contract-spi/src/main/java/org/eclipse/dataspaceconnector/spi/types/domain/contract/negotiation/ContractNegotiation.java index 263efaba748..edec0dd5061 100644 --- a/spi/contract-spi/src/main/java/org/eclipse/dataspaceconnector/spi/types/domain/contract/negotiation/ContractNegotiation.java +++ b/spi/contract-spi/src/main/java/org/eclipse/dataspaceconnector/spi/types/domain/contract/negotiation/ContractNegotiation.java @@ -26,7 +26,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.time.Instant; +import java.time.Clock; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -79,6 +79,7 @@ public class ContractNegotiation implements TraceCarrier { private ContractAgreement contractAgreement; private List contractOffers = new ArrayList<>(); private Map traceContext = new HashMap<>(); + private Clock clock = Clock.systemUTC(); public Type getType() { return type; @@ -336,17 +337,6 @@ public void transitionError(@Nullable String errorDetail) { updateStateTimestamp(); } - /** - * Reset to an arbitrary state. - * - * @param state The desired state. - */ - public void rollbackState(ContractNegotiationStates state) { - this.state = state.code(); - stateCount = 1; - updateStateTimestamp(); - } - /** * Create a copy of this negotiation. * @@ -354,16 +344,19 @@ public void rollbackState(ContractNegotiationStates state) { */ public ContractNegotiation copy() { return Builder.newInstance().id(id).correlationId(correlationId).counterPartyId(counterPartyId) + .clock(clock) .counterPartyAddress(counterPartyAddress).protocol(protocol).type(type).state(state).stateCount(stateCount) .stateTimestamp(stateTimestamp).errorDetail(errorDetail).contractAgreement(contractAgreement) .contractOffers(contractOffers).traceContext(traceContext).build(); } /** - * Sets the state timestamp to the current time. + * Sets the state timestamp to the clock time. + * + * @see Builder#clock(Clock) */ public void updateStateTimestamp() { - stateTimestamp = Instant.now().toEpochMilli(); + stateTimestamp = clock.millis(); } @Override @@ -377,13 +370,14 @@ public boolean equals(Object o) { ContractNegotiation that = (ContractNegotiation) o; return state == that.state && stateCount == that.stateCount && stateTimestamp == that.stateTimestamp && Objects.equals(id, that.id) && Objects.equals(correlationId, that.correlationId) && Objects.equals(counterPartyId, that.counterPartyId) && + Objects.equals(clock, that.clock) && Objects.equals(protocol, that.protocol) && Objects.equals(traceContext, that.traceContext) && type == that.type && Objects.equals(contractAgreement, that.contractAgreement) && Objects.equals(contractOffers, that.contractOffers); } @Override public int hashCode() { - return Objects.hash(id, correlationId, counterPartyId, protocol, traceContext, type, state, stateCount, stateTimestamp, contractAgreement, contractOffers); + return Objects.hash(id, correlationId, counterPartyId, clock, protocol, traceContext, type, state, stateCount, stateTimestamp, contractAgreement, contractOffers); } private void checkState(int... legalStates) { @@ -457,6 +451,11 @@ public Builder stateTimestamp(long stateTimestamp) { return this; } + public Builder clock(Clock clock) { + negotiation.clock = clock; + return this; + } + public Builder counterPartyId(String id) { negotiation.counterPartyId = id; return this; @@ -505,6 +504,7 @@ public Builder traceContext(Map traceContext) { public ContractNegotiation build() { Objects.requireNonNull(negotiation.id); + Objects.requireNonNull(negotiation.clock); Objects.requireNonNull(negotiation.counterPartyId); Objects.requireNonNull(negotiation.counterPartyAddress); Objects.requireNonNull(negotiation.protocol); diff --git a/spi/core-spi/src/main/java/org/eclipse/dataspaceconnector/spi/system/ServiceExtensionContext.java b/spi/core-spi/src/main/java/org/eclipse/dataspaceconnector/spi/system/ServiceExtensionContext.java index 801685546f7..c1a70103739 100644 --- a/spi/core-spi/src/main/java/org/eclipse/dataspaceconnector/spi/system/ServiceExtensionContext.java +++ b/spi/core-spi/src/main/java/org/eclipse/dataspaceconnector/spi/system/ServiceExtensionContext.java @@ -19,6 +19,8 @@ import org.eclipse.dataspaceconnector.spi.telemetry.Telemetry; import org.eclipse.dataspaceconnector.spi.types.TypeManager; +import java.time.Clock; + /** * Context provided to extensions when they are initialized. */ @@ -33,17 +35,30 @@ public interface ServiceExtensionContext extends SettingResolver { /** * Returns the system monitor. */ - Monitor getMonitor(); + default Monitor getMonitor() { + return getService(Monitor.class); + } /** * Returns the system telemetry object. */ - Telemetry getTelemetry(); + default Telemetry getTelemetry() { + return getService(Telemetry.class); + } /** * Returns the type manager. */ - TypeManager getTypeManager(); + default TypeManager getTypeManager() { + return getService(TypeManager.class); + } + + /** + * Returns the {@link Clock} to retrieve the current time, which can be mocked in unit tests. + */ + default Clock getClock() { + return getService(Clock.class); + } /** * Returns true if the service type is registered. diff --git a/spi/transfer-spi/src/main/java/org/eclipse/dataspaceconnector/spi/types/domain/transfer/TransferProcess.java b/spi/transfer-spi/src/main/java/org/eclipse/dataspaceconnector/spi/types/domain/transfer/TransferProcess.java index 2dc24ece05b..b9b3d162252 100644 --- a/spi/transfer-spi/src/main/java/org/eclipse/dataspaceconnector/spi/types/domain/transfer/TransferProcess.java +++ b/spi/transfer-spi/src/main/java/org/eclipse/dataspaceconnector/spi/types/domain/transfer/TransferProcess.java @@ -26,6 +26,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.time.Clock; import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; @@ -111,6 +112,7 @@ public class TransferProcess implements TraceCarrier { private ResourceManifest resourceManifest; private ProvisionedResourceSet provisionedResourceSet; private List deprovisionedResources = new ArrayList<>(); + private Clock clock = Clock.systemUTC(); private TransferProcess() { } @@ -326,13 +328,6 @@ public void transitionError(@Nullable String errorDetail) { updateStateTimestamp(); } - - public void rollbackState(TransferProcessStates state) { - this.state = state.code(); - stateCount = 1; - updateStateTimestamp(); - } - public TransferProcess copy() { return Builder.newInstance() .id(id) @@ -347,6 +342,7 @@ public TransferProcess copy() { .type(type) .createdTimestamp(createdTimestamp) .errorDetail(errorDetail) + .clock(clock) .build(); } @@ -380,8 +376,13 @@ public String toString() { '}'; } + /** + * Sets the state timestamp to the clock time. + * + * @see Builder#clock(Clock) + */ public void updateStateTimestamp() { - stateTimestamp = Instant.now().toEpochMilli(); + stateTimestamp = clock.millis(); } private void transition(TransferProcessStates end, TransferProcessStates... starts) { @@ -425,6 +426,11 @@ public Builder type(Type type) { return this; } + public Builder clock(Clock clock) { + process.clock = clock; + return this; + } + public Builder createdTimestamp(long value) { process.createdTimestamp = value; return this; @@ -482,8 +488,9 @@ public Builder traceContext(Map traceContext) { public TransferProcess build() { Objects.requireNonNull(process.id, "id"); + Objects.requireNonNull(process.clock, "clock"); if (process.state == UNSAVED.code() && process.stateTimestamp == 0) { - process.stateTimestamp = Instant.now().toEpochMilli(); + process.stateTimestamp = process.clock.millis(); } if (process.resourceManifest != null) { process.resourceManifest.setTransferProcessId(process.id); diff --git a/spi/transfer-spi/src/test/java/org/eclipse/dataspaceconnector/spi/types/domain/transfer/TransferProcessTest.java b/spi/transfer-spi/src/test/java/org/eclipse/dataspaceconnector/spi/types/domain/transfer/TransferProcessTest.java index 44c41a23a02..2cd4204d312 100644 --- a/spi/transfer-spi/src/test/java/org/eclipse/dataspaceconnector/spi/types/domain/transfer/TransferProcessTest.java +++ b/spi/transfer-spi/src/test/java/org/eclipse/dataspaceconnector/spi/types/domain/transfer/TransferProcessTest.java @@ -29,7 +29,6 @@ import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.eclipse.dataspaceconnector.spi.types.domain.transfer.TransferProcessStates.INITIAL; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -123,18 +122,6 @@ void verifyProviderTransitions() { process.transitionEnded(); } - @Test - void verifyTransitionRollback() { - var process = TransferProcess.Builder.newInstance().id(UUID.randomUUID().toString()).build(); - process.transitionInitial(); - process.transitionProvisioning(ResourceManifest.Builder.newInstance().build()); - - process.rollbackState(INITIAL); - - assertEquals(INITIAL.code(), process.getState()); - assertEquals(1, process.getStateCount()); - } - @Test void verifyProvisioningComplete() { var builder = TransferProcess.Builder.newInstance().id(UUID.randomUUID().toString()); From ff4da1d4f987c11b887c3784c8d824520cef9b38 Mon Sep 17 00:00:00 2001 From: Alexandre Gattiker Date: Tue, 7 Jun 2022 15:01:55 +0200 Subject: [PATCH 02/13] Checkstyle --- .../iam/registrationservice/crawler/CrawlerJob.java | 1 - .../contractnegotiation/store/SqlContractNegotiationStore.java | 2 +- .../java/org/eclipse/dataspaceconnector/sql/lease/SqlLease.java | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/extensions/iam/decentralized-identity/registration-service/src/main/java/org/eclipse/dataspaceconnector/iam/registrationservice/crawler/CrawlerJob.java b/extensions/iam/decentralized-identity/registration-service/src/main/java/org/eclipse/dataspaceconnector/iam/registrationservice/crawler/CrawlerJob.java index 0534718d3dc..9ec35cfc67c 100644 --- a/extensions/iam/decentralized-identity/registration-service/src/main/java/org/eclipse/dataspaceconnector/iam/registrationservice/crawler/CrawlerJob.java +++ b/extensions/iam/decentralized-identity/registration-service/src/main/java/org/eclipse/dataspaceconnector/iam/registrationservice/crawler/CrawlerJob.java @@ -28,7 +28,6 @@ import org.quartz.JobExecutionContext; import java.io.IOException; -import java.time.Clock; import java.time.Duration; import java.util.List; import java.util.Objects; diff --git a/extensions/sql/contract-negotiation-store-sql/src/main/java/org/eclipse/dataspaceconnector/sql/contractnegotiation/store/SqlContractNegotiationStore.java b/extensions/sql/contract-negotiation-store-sql/src/main/java/org/eclipse/dataspaceconnector/sql/contractnegotiation/store/SqlContractNegotiationStore.java index 2ec4184f975..11d9243d7f4 100644 --- a/extensions/sql/contract-negotiation-store-sql/src/main/java/org/eclipse/dataspaceconnector/sql/contractnegotiation/store/SqlContractNegotiationStore.java +++ b/extensions/sql/contract-negotiation-store-sql/src/main/java/org/eclipse/dataspaceconnector/sql/contractnegotiation/store/SqlContractNegotiationStore.java @@ -28,7 +28,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.sql.DataSource; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; @@ -36,6 +35,7 @@ import java.util.List; import java.util.Objects; import java.util.stream.Stream; +import javax.sql.DataSource; import static java.lang.String.format; import static java.util.Optional.ofNullable; diff --git a/extensions/sql/lease-sql/src/main/java/org/eclipse/dataspaceconnector/sql/lease/SqlLease.java b/extensions/sql/lease-sql/src/main/java/org/eclipse/dataspaceconnector/sql/lease/SqlLease.java index f65d1215801..a3b9c1a1e4a 100644 --- a/extensions/sql/lease-sql/src/main/java/org/eclipse/dataspaceconnector/sql/lease/SqlLease.java +++ b/extensions/sql/lease-sql/src/main/java/org/eclipse/dataspaceconnector/sql/lease/SqlLease.java @@ -17,7 +17,6 @@ import org.eclipse.dataspaceconnector.spi.persistence.Lease; import java.time.Clock; -import java.time.Instant; /** * SQL-based implementation of a {@linkplain Lease}. Adds the {@code leaseId} property for use with RDBMS (PK, index,...) From d565627a0a679da2646b3519dde67c4ca4e518ae Mon Sep 17 00:00:00 2001 From: Alexandre Gattiker Date: Tue, 7 Jun 2022 15:02:29 +0200 Subject: [PATCH 03/13] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a564bac4748..a958fe616da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ in the detailed section referring to by linking pull requests or issues. * Add signing/publishing config (#1147) * Verify OpenAPI definitions (#1312) * Documentation for CosmosDB (#1334) +* Shared clock service (#1416) #### Changed From 7a9fa0854cbaac33fa074cea06a92644bd387d87 Mon Sep 17 00:00:00 2001 From: Alexandre Gattiker Date: Wed, 8 Jun 2022 10:36:25 +0200 Subject: [PATCH 04/13] Moved default clock to DefaultServicesExtension --- .../core/defaults/DefaultServicesExtension.java | 6 ++++++ .../boot/system/DefaultServiceExtensionContext.java | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/core/base/src/main/java/org/eclipse/dataspaceconnector/core/defaults/DefaultServicesExtension.java b/core/base/src/main/java/org/eclipse/dataspaceconnector/core/defaults/DefaultServicesExtension.java index 58b2a7a3086..55f2c82bc3b 100644 --- a/core/base/src/main/java/org/eclipse/dataspaceconnector/core/defaults/DefaultServicesExtension.java +++ b/core/base/src/main/java/org/eclipse/dataspaceconnector/core/defaults/DefaultServicesExtension.java @@ -31,6 +31,7 @@ import org.eclipse.dataspaceconnector.spi.system.ServiceExtension; import org.eclipse.dataspaceconnector.spi.transfer.store.TransferProcessStore; +import java.time.Clock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** @@ -86,6 +87,11 @@ public PolicyDefinitionStore defaultPolicyStore() { return new InMemoryPolicyDefinitionStore(new LockManager(new ReentrantReadWriteLock(true))); } + @Provider(isDefault = true) + public Clock defaultClock() { + return Clock.systemUTC(); + } + private ContractDefinitionStore getContractDefinitionStore() { if (contractDefinitionStore == null) { contractDefinitionStore = new InMemoryContractDefinitionStore(); diff --git a/core/boot/src/main/java/org/eclipse/dataspaceconnector/boot/system/DefaultServiceExtensionContext.java b/core/boot/src/main/java/org/eclipse/dataspaceconnector/boot/system/DefaultServiceExtensionContext.java index 0fe07b27ca7..17b97aa4023 100644 --- a/core/boot/src/main/java/org/eclipse/dataspaceconnector/boot/system/DefaultServiceExtensionContext.java +++ b/core/boot/src/main/java/org/eclipse/dataspaceconnector/boot/system/DefaultServiceExtensionContext.java @@ -48,7 +48,6 @@ public DefaultServiceExtensionContext(TypeManager typeManager, Monitor monitor, registerService(TypeManager.class, typeManager); registerService(Monitor.class, monitor); registerService(Telemetry.class, telemetry); - registerService(Clock.class, Clock.systemUTC()); } @Override From 3798770127c69d168008c5532a4ed19d717d281a Mon Sep 17 00:00:00 2001 From: Alexandre Gattiker Date: Wed, 8 Jun 2022 10:44:42 +0200 Subject: [PATCH 05/13] Update DefaultServiceExtensionContext.java --- .../boot/system/DefaultServiceExtensionContext.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/boot/src/main/java/org/eclipse/dataspaceconnector/boot/system/DefaultServiceExtensionContext.java b/core/boot/src/main/java/org/eclipse/dataspaceconnector/boot/system/DefaultServiceExtensionContext.java index 17b97aa4023..f5c5dd05ca9 100644 --- a/core/boot/src/main/java/org/eclipse/dataspaceconnector/boot/system/DefaultServiceExtensionContext.java +++ b/core/boot/src/main/java/org/eclipse/dataspaceconnector/boot/system/DefaultServiceExtensionContext.java @@ -24,7 +24,6 @@ import org.eclipse.dataspaceconnector.spi.telemetry.Telemetry; import org.eclipse.dataspaceconnector.spi.types.TypeManager; -import java.time.Clock; import java.util.HashMap; import java.util.List; import java.util.Map; From af4613bd1efacf56d195bbd87cd9e005c5dbb117 Mon Sep 17 00:00:00 2001 From: Alexandre Gattiker Date: Wed, 8 Jun 2022 11:35:57 +0200 Subject: [PATCH 06/13] Update SqlContractNegotiationStoreExtensionTest.java --- .../SqlContractNegotiationStoreExtensionTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/extensions/sql/contract-negotiation-store-sql/src/test/java/org/eclipse/dataspaceconnector/sql/contractnegotiation/SqlContractNegotiationStoreExtensionTest.java b/extensions/sql/contract-negotiation-store-sql/src/test/java/org/eclipse/dataspaceconnector/sql/contractnegotiation/SqlContractNegotiationStoreExtensionTest.java index 2f4c19b082d..5f4a5f7ab71 100644 --- a/extensions/sql/contract-negotiation-store-sql/src/test/java/org/eclipse/dataspaceconnector/sql/contractnegotiation/SqlContractNegotiationStoreExtensionTest.java +++ b/extensions/sql/contract-negotiation-store-sql/src/test/java/org/eclipse/dataspaceconnector/sql/contractnegotiation/SqlContractNegotiationStoreExtensionTest.java @@ -28,6 +28,8 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import java.time.Clock; + import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.mock; @@ -41,6 +43,7 @@ class SqlContractNegotiationStoreExtensionTest { void initialize(ServiceExtensionContext context, ObjectFactory factory) { context.registerService(DataSourceRegistry.class, mock(DataSourceRegistry.class)); context.registerService(TransactionContext.class, mock(TransactionContext.class)); + context.registerService(Clock.class, Clock.systemUTC()); extension = factory.constructInstance(SqlContractNegotiationStoreExtension.class); @@ -55,6 +58,7 @@ void initialize(ServiceExtensionContext context, ObjectFactory factory) { void initialize_withCustomSqlDialect(ServiceExtensionContext context, ObjectFactory factory) { context.registerService(DataSourceRegistry.class, mock(DataSourceRegistry.class)); context.registerService(TransactionContext.class, mock(TransactionContext.class)); + context.registerService(Clock.class, Clock.systemUTC()); var customSqlDialect = mock(ContractNegotiationStatements.class); context.registerService(ContractNegotiationStatements.class, customSqlDialect); From 1ebb12fb403f1ff59969e9140405cc85801d7b56 Mon Sep 17 00:00:00 2001 From: Alexandre Gattiker Date: Wed, 8 Jun 2022 20:54:31 +0200 Subject: [PATCH 07/13] Update AbstractMultipartDispatcherIntegrationTest.java --- .../client/AbstractMultipartDispatcherIntegrationTest.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/data-protocols/ids/ids-api-multipart-dispatcher-v1/src/test/java/org/eclipse/dataspaceconnector/ids/api/multipart/client/AbstractMultipartDispatcherIntegrationTest.java b/data-protocols/ids/ids-api-multipart-dispatcher-v1/src/test/java/org/eclipse/dataspaceconnector/ids/api/multipart/client/AbstractMultipartDispatcherIntegrationTest.java index 46cd1c7b81c..57accee811d 100644 --- a/data-protocols/ids/ids-api-multipart-dispatcher-v1/src/test/java/org/eclipse/dataspaceconnector/ids/api/multipart/client/AbstractMultipartDispatcherIntegrationTest.java +++ b/data-protocols/ids/ids-api-multipart-dispatcher-v1/src/test/java/org/eclipse/dataspaceconnector/ids/api/multipart/client/AbstractMultipartDispatcherIntegrationTest.java @@ -28,11 +28,14 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; +import java.time.Clock; +import java.time.Instant; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; +import static java.time.ZoneOffset.UTC; import static org.eclipse.dataspaceconnector.common.testfixtures.TestUtils.getFreePort; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; @@ -52,6 +55,7 @@ abstract class AbstractMultipartDispatcherIntegrationTest { } protected IdentityService identityService; + protected Instant now = Instant.now(); @AfterEach void after() { @@ -82,6 +86,7 @@ protected void before(EdcExtension extension) { extension.registerSystemExtension(ServiceExtension.class, new IdsApiMultipartDispatcherV1IntegrationTestServiceExtension(ASSETS, identityService)); + extension.registerServiceMock(Clock.class, Clock.fixed(now, UTC)); } protected void addAsset(Asset asset) { From 4f382ba6444e4d6ebe8c484d36315e704fc72dfb Mon Sep 17 00:00:00 2001 From: Alexandre Gattiker Date: Thu, 9 Jun 2022 07:19:50 +0200 Subject: [PATCH 08/13] Revert "Update AbstractMultipartDispatcherIntegrationTest.java" This reverts commit 1ebb12fb403f1ff59969e9140405cc85801d7b56. --- .../client/AbstractMultipartDispatcherIntegrationTest.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/data-protocols/ids/ids-api-multipart-dispatcher-v1/src/test/java/org/eclipse/dataspaceconnector/ids/api/multipart/client/AbstractMultipartDispatcherIntegrationTest.java b/data-protocols/ids/ids-api-multipart-dispatcher-v1/src/test/java/org/eclipse/dataspaceconnector/ids/api/multipart/client/AbstractMultipartDispatcherIntegrationTest.java index 57accee811d..46cd1c7b81c 100644 --- a/data-protocols/ids/ids-api-multipart-dispatcher-v1/src/test/java/org/eclipse/dataspaceconnector/ids/api/multipart/client/AbstractMultipartDispatcherIntegrationTest.java +++ b/data-protocols/ids/ids-api-multipart-dispatcher-v1/src/test/java/org/eclipse/dataspaceconnector/ids/api/multipart/client/AbstractMultipartDispatcherIntegrationTest.java @@ -28,14 +28,11 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; -import java.time.Clock; -import java.time.Instant; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; -import static java.time.ZoneOffset.UTC; import static org.eclipse.dataspaceconnector.common.testfixtures.TestUtils.getFreePort; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; @@ -55,7 +52,6 @@ abstract class AbstractMultipartDispatcherIntegrationTest { } protected IdentityService identityService; - protected Instant now = Instant.now(); @AfterEach void after() { @@ -86,7 +82,6 @@ protected void before(EdcExtension extension) { extension.registerSystemExtension(ServiceExtension.class, new IdsApiMultipartDispatcherV1IntegrationTestServiceExtension(ASSETS, identityService)); - extension.registerServiceMock(Clock.class, Clock.fixed(now, UTC)); } protected void addAsset(Asset asset) { From 625f3c503c1fcdde025b1eda1d7abcf60ed30f50 Mon Sep 17 00:00:00 2001 From: Alexandre Gattiker Date: Thu, 9 Jun 2022 07:19:58 +0200 Subject: [PATCH 09/13] Revert "Update SqlContractNegotiationStoreExtensionTest.java" This reverts commit af4613bd1efacf56d195bbd87cd9e005c5dbb117. --- .../SqlContractNegotiationStoreExtensionTest.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/extensions/sql/contract-negotiation-store-sql/src/test/java/org/eclipse/dataspaceconnector/sql/contractnegotiation/SqlContractNegotiationStoreExtensionTest.java b/extensions/sql/contract-negotiation-store-sql/src/test/java/org/eclipse/dataspaceconnector/sql/contractnegotiation/SqlContractNegotiationStoreExtensionTest.java index 5f4a5f7ab71..2f4c19b082d 100644 --- a/extensions/sql/contract-negotiation-store-sql/src/test/java/org/eclipse/dataspaceconnector/sql/contractnegotiation/SqlContractNegotiationStoreExtensionTest.java +++ b/extensions/sql/contract-negotiation-store-sql/src/test/java/org/eclipse/dataspaceconnector/sql/contractnegotiation/SqlContractNegotiationStoreExtensionTest.java @@ -28,8 +28,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import java.time.Clock; - import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.mock; @@ -43,7 +41,6 @@ class SqlContractNegotiationStoreExtensionTest { void initialize(ServiceExtensionContext context, ObjectFactory factory) { context.registerService(DataSourceRegistry.class, mock(DataSourceRegistry.class)); context.registerService(TransactionContext.class, mock(TransactionContext.class)); - context.registerService(Clock.class, Clock.systemUTC()); extension = factory.constructInstance(SqlContractNegotiationStoreExtension.class); @@ -58,7 +55,6 @@ void initialize(ServiceExtensionContext context, ObjectFactory factory) { void initialize_withCustomSqlDialect(ServiceExtensionContext context, ObjectFactory factory) { context.registerService(DataSourceRegistry.class, mock(DataSourceRegistry.class)); context.registerService(TransactionContext.class, mock(TransactionContext.class)); - context.registerService(Clock.class, Clock.systemUTC()); var customSqlDialect = mock(ContractNegotiationStatements.class); context.registerService(ContractNegotiationStatements.class, customSqlDialect); From 0bc8a3beb6d93cb0a80b28bf16a3322186e0604b Mon Sep 17 00:00:00 2001 From: Alexandre Gattiker Date: Thu, 9 Jun 2022 07:20:04 +0200 Subject: [PATCH 10/13] Revert "Update DefaultServiceExtensionContext.java" This reverts commit 3798770127c69d168008c5532a4ed19d717d281a. --- .../boot/system/DefaultServiceExtensionContext.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/boot/src/main/java/org/eclipse/dataspaceconnector/boot/system/DefaultServiceExtensionContext.java b/core/boot/src/main/java/org/eclipse/dataspaceconnector/boot/system/DefaultServiceExtensionContext.java index f5c5dd05ca9..17b97aa4023 100644 --- a/core/boot/src/main/java/org/eclipse/dataspaceconnector/boot/system/DefaultServiceExtensionContext.java +++ b/core/boot/src/main/java/org/eclipse/dataspaceconnector/boot/system/DefaultServiceExtensionContext.java @@ -24,6 +24,7 @@ import org.eclipse.dataspaceconnector.spi.telemetry.Telemetry; import org.eclipse.dataspaceconnector.spi.types.TypeManager; +import java.time.Clock; import java.util.HashMap; import java.util.List; import java.util.Map; From e218c47cfb6f4f8e1dbb5202cc1aaa29ac2415ce Mon Sep 17 00:00:00 2001 From: Alexandre Gattiker Date: Thu, 9 Jun 2022 07:20:11 +0200 Subject: [PATCH 11/13] Revert "Moved default clock to DefaultServicesExtension" This reverts commit 7a9fa0854cbaac33fa074cea06a92644bd387d87. --- .../core/defaults/DefaultServicesExtension.java | 6 ------ .../boot/system/DefaultServiceExtensionContext.java | 1 + .../negotiation/ContractNegotiationIntegrationTest.java | 1 - 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/core/base/src/main/java/org/eclipse/dataspaceconnector/core/defaults/DefaultServicesExtension.java b/core/base/src/main/java/org/eclipse/dataspaceconnector/core/defaults/DefaultServicesExtension.java index 55f2c82bc3b..58b2a7a3086 100644 --- a/core/base/src/main/java/org/eclipse/dataspaceconnector/core/defaults/DefaultServicesExtension.java +++ b/core/base/src/main/java/org/eclipse/dataspaceconnector/core/defaults/DefaultServicesExtension.java @@ -31,7 +31,6 @@ import org.eclipse.dataspaceconnector.spi.system.ServiceExtension; import org.eclipse.dataspaceconnector.spi.transfer.store.TransferProcessStore; -import java.time.Clock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** @@ -87,11 +86,6 @@ public PolicyDefinitionStore defaultPolicyStore() { return new InMemoryPolicyDefinitionStore(new LockManager(new ReentrantReadWriteLock(true))); } - @Provider(isDefault = true) - public Clock defaultClock() { - return Clock.systemUTC(); - } - private ContractDefinitionStore getContractDefinitionStore() { if (contractDefinitionStore == null) { contractDefinitionStore = new InMemoryContractDefinitionStore(); diff --git a/core/boot/src/main/java/org/eclipse/dataspaceconnector/boot/system/DefaultServiceExtensionContext.java b/core/boot/src/main/java/org/eclipse/dataspaceconnector/boot/system/DefaultServiceExtensionContext.java index 17b97aa4023..0fe07b27ca7 100644 --- a/core/boot/src/main/java/org/eclipse/dataspaceconnector/boot/system/DefaultServiceExtensionContext.java +++ b/core/boot/src/main/java/org/eclipse/dataspaceconnector/boot/system/DefaultServiceExtensionContext.java @@ -48,6 +48,7 @@ public DefaultServiceExtensionContext(TypeManager typeManager, Monitor monitor, registerService(TypeManager.class, typeManager); registerService(Monitor.class, monitor); registerService(Telemetry.class, telemetry); + registerService(Clock.class, Clock.systemUTC()); } @Override diff --git a/core/contract/src/test/java/org/eclipse/dataspaceconnector/contract/negotiation/ContractNegotiationIntegrationTest.java b/core/contract/src/test/java/org/eclipse/dataspaceconnector/contract/negotiation/ContractNegotiationIntegrationTest.java index 6a83225333b..40b477b193d 100644 --- a/core/contract/src/test/java/org/eclipse/dataspaceconnector/contract/negotiation/ContractNegotiationIntegrationTest.java +++ b/core/contract/src/test/java/org/eclipse/dataspaceconnector/contract/negotiation/ContractNegotiationIntegrationTest.java @@ -32,7 +32,6 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -@ComponentTest class ContractNegotiationIntegrationTest extends AbstractContractNegotiationIntegrationTest { @Test From a115110758dcb9cdc25b0396996bf5e2f9a4dde8 Mon Sep 17 00:00:00 2001 From: Alexandre Gattiker Date: Thu, 9 Jun 2022 08:08:47 +0200 Subject: [PATCH 12/13] Update ContractNegotiationIntegrationTest.java --- .../contract/negotiation/ContractNegotiationIntegrationTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/contract/src/test/java/org/eclipse/dataspaceconnector/contract/negotiation/ContractNegotiationIntegrationTest.java b/core/contract/src/test/java/org/eclipse/dataspaceconnector/contract/negotiation/ContractNegotiationIntegrationTest.java index 40b477b193d..77db66b5ae3 100644 --- a/core/contract/src/test/java/org/eclipse/dataspaceconnector/contract/negotiation/ContractNegotiationIntegrationTest.java +++ b/core/contract/src/test/java/org/eclipse/dataspaceconnector/contract/negotiation/ContractNegotiationIntegrationTest.java @@ -14,7 +14,6 @@ package org.eclipse.dataspaceconnector.contract.negotiation; -import org.eclipse.dataspaceconnector.common.annotations.ComponentTest; import org.eclipse.dataspaceconnector.spi.result.Result; import org.eclipse.dataspaceconnector.spi.types.domain.contract.agreement.ContractAgreement; import org.eclipse.dataspaceconnector.spi.types.domain.contract.negotiation.ContractOfferRequest; From c828e7e5057fe5f756194a442caa393d190af947 Mon Sep 17 00:00:00 2001 From: Alexandre Gattiker Date: Thu, 9 Jun 2022 08:10:26 +0200 Subject: [PATCH 13/13] Update ContractNegotiationIntegrationTest.java --- .../negotiation/ContractNegotiationIntegrationTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/contract/src/test/java/org/eclipse/dataspaceconnector/contract/negotiation/ContractNegotiationIntegrationTest.java b/core/contract/src/test/java/org/eclipse/dataspaceconnector/contract/negotiation/ContractNegotiationIntegrationTest.java index 77db66b5ae3..6a83225333b 100644 --- a/core/contract/src/test/java/org/eclipse/dataspaceconnector/contract/negotiation/ContractNegotiationIntegrationTest.java +++ b/core/contract/src/test/java/org/eclipse/dataspaceconnector/contract/negotiation/ContractNegotiationIntegrationTest.java @@ -14,6 +14,7 @@ package org.eclipse.dataspaceconnector.contract.negotiation; +import org.eclipse.dataspaceconnector.common.annotations.ComponentTest; import org.eclipse.dataspaceconnector.spi.result.Result; import org.eclipse.dataspaceconnector.spi.types.domain.contract.agreement.ContractAgreement; import org.eclipse.dataspaceconnector.spi.types.domain.contract.negotiation.ContractOfferRequest; @@ -31,6 +32,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +@ComponentTest class ContractNegotiationIntegrationTest extends AbstractContractNegotiationIntegrationTest { @Test