From 2a636328a0ff6b663552e4eb051b4434633d9a1d Mon Sep 17 00:00:00 2001 From: Avgustin Marinov Date: Tue, 2 Sep 2025 16:08:14 +0300 Subject: [PATCH] 20250828 cleanup (#2639) * Cleanup * Refactor artifact management --- .3rd-party/README.md | 18 +- .../reusable_workflow_license-scan.yaml | 2 +- docker/README.md | 48 +++-- docker/build/README.md | 2 - hawkbit-artifact/README.md | 5 + .../hawkbit-artifact-api/README.md | 9 +- .../AbstractArtifactStorage.java} | 62 +++--- .../ArtifactStorage.java} | 25 +-- .../encryption/ArtifactEncryption.java | 8 +- .../ArtifactEncryptionSecretsStorage.java} | 20 +- .../encryption/ArtifactEncryptionService.java | 13 +- ...ArtifactBinaryNoLongerExistsException.java | 26 +-- .../ArtifactBinaryNotFoundException.java | 24 +-- .../ArtifactDeleteFailedException.java | 22 +- .../ArtifactEncryptionFailedException.java | 12 +- ...rtifactEncryptionUnsupportedException.java | 16 +- .../exception/ArtifactStoreException.java | 12 +- .../ArtifactUploadFailedException.java | 31 +-- .../FileSizeQuotaExceededException.java | 36 ++-- .../exception/HashNotMatchException.java | 8 +- .../StorageQuotaExceededException.java | 26 +-- .../artifact/model/ArtifactHashes.java | 15 ++ .../artifact/model/ArtifactStream.java | 51 +++++ .../model/StoredArtifactInfo.java} | 17 +- .../artifact/urlresolver/ArtifactUrl.java | 15 ++ .../urlresolver/ArtifactUrlResolver.java | 64 ++++++ .../PropertyBasedArtifactUrlResolver.java | 152 +++++++++++++ ...tyBasedArtifactUrlResolverProperties.java} | 19 +- .../repository/artifact/model/DbArtifact.java | 46 ---- .../artifact/model/DbArtifactHash.java | 36 ---- .../artifact/urlhandler/ApiType.java | 31 --- .../artifact/urlhandler/ArtifactUrl.java | 36 ---- .../urlhandler/ArtifactUrlHandler.java | 39 ---- .../artifact/urlhandler/Base62Util.java | 67 ------ .../PropertyBasedArtifactUrlHandler.java | 203 ------------------ .../artifact/urlhandler/URLPlaceholder.java | 71 ------ .../ArtifactEncryptionServiceTest.java | 4 +- ...PropertyBasedArtifactUrlResolverTest.java} | 140 +++++------- .../artifact/urlhandler/Base62UtilTest.java | 43 ---- .../urlhandler/URLPlaceholderTest.java | 93 -------- .../hawkbit-artifact-fs/README.md | 8 + .../pom.xml | 2 +- .../artifact/fs/FileArtifactProperties.java} | 4 +- .../artifact/fs/FileArtifactStorage.java | 114 ++++++++++ .../fs/FileArtifactStorageConfiguration.java} | 20 +- ...ot.autoconfigure.AutoConfiguration.imports | 1 + .../artifact/fs/FileArtifactStorageTest.java} | 43 ++-- .../README.md | 18 -- .../ArtifactFileNotFoundException.java | 25 --- .../artifact/ArtifactFilesystem.java | 52 ----- .../ArtifactFilesystemRepository.java | 115 ---------- ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../artifact/ArtifactFilesystemTest.java | 53 ----- hawkbit-artifact/pom.xml | 2 +- ...ArtifactUrlResolverAutoConfiguration.java} | 24 +-- .../cache/CacheAutoConfiguration.java | 15 +- .../autoconfigure/cache/CacheProperties.java | 2 +- .../EventPublisherAutoConfiguration.java | 2 +- .../scheduling/ExecutorAutoConfiguration.java | 16 +- ...roperties.java => ExecutorProperties.java} | 4 +- ...taticUserManagementAutoConfiguration.java} | 5 +- ...ot.autoconfigure.AutoConfiguration.imports | 4 +- .../hawkbit-artifactdl-defaults.properties | 9 +- hawkbit-core/README.md | 2 +- .../exception/AbstractServerRtException.java | 63 +----- .../eclipse/hawkbit/tenancy/TenantAware.java | 2 +- .../TenantAwareAuthenticationDetails.java | 21 +- .../tenancy/TenantMetricsConfiguration.java | 4 +- .../cache/TenantAwareCacheManager.java | 14 +- .../cache/TenantCacheManager.java} | 4 +- .../eclipse/hawkbit/utils/ObjectCopyUtil.java | 69 +++--- ...eldsTest.java => RsqlQueryFieldsTest.java} | 6 +- .../ddi/json/model/DdiActionHistory.java | 4 +- .../model/DdiActivateAutoConfirmation.java | 11 +- .../hawkbit/ddi/json/model/DdiArtifact.java | 6 +- .../hawkbit/ddi/json/model/DdiConfig.java | 5 - .../ddi/json/model/DdiConfirmationBase.java | 3 +- .../json/model/DdiConfirmationBaseAction.java | 24 +-- .../ddi/json/model/DdiControllerBase.java | 2 +- .../hawkbit/ddi/json/model/DdiDeployment.java | 4 +- .../ddi/json/model/DdiDeploymentBase.java | 24 +-- .../hawkbit/ddi/json/model/DdiResult.java | 2 +- .../hawkbit/ddi/json/model/DdiUpdateMode.java | 3 +- .../rest/api/DdiRootControllerRestApi.java | 27 ++- .../ddi/json/model/DdiActionHistoryTest.java | 2 +- .../ddi/json/model/DdiArtifactHashTest.java | 2 +- .../ddi/json/model/DdiArtifactTest.java | 2 +- .../json/model/DdiCancelActionToStopTest.java | 2 +- .../hawkbit/ddi/json/model/DdiCancelTest.java | 2 +- .../hawkbit/ddi/json/model/DdiChunkTest.java | 2 +- .../hawkbit/ddi/json/model/DdiConfigTest.java | 2 +- .../json/model/DdiConfirmationBaseTest.java | 2 +- .../ddi/json/model/DdiControllerBaseTest.java | 2 +- .../ddi/json/model/DdiDeploymentBaseTest.java | 2 +- .../ddi/json/model/DdiDeploymentTest.java | 2 +- .../ddi/json/model/DdiMetadataTest.java | 2 +- .../ddi/json/model/DdiPollingTest.java | 2 +- .../ddi/json/model/DdiProgressTest.java | 2 +- .../hawkbit/ddi/json/model/DdiResultTest.java | 2 +- .../hawkbit/ddi/json/model/DdiStatusTest.java | 2 +- .../rest/resource/DataConversionHelper.java | 25 +-- .../rest/resource/DdiApiConfiguration.java | 5 +- .../ddi/rest/resource/DdiRootController.java | 40 ++-- .../AbstractDDiApiIntegrationTest.java | 20 +- .../resource/DdiArtifactDownloadTest.java | 45 ++-- .../rest/resource/DdiCancelActionTest.java | 42 ++-- .../ddi/rest/resource/DdiConfigDataTest.java | 8 +- .../resource/DdiConfirmationBaseTest.java | 13 +- .../rest/resource/DdiDeploymentBaseTest.java | 76 +++---- .../rest/resource/DdiInstalledBaseTest.java | 4 +- .../rest/resource/DdiRootControllerTest.java | 44 ++-- hawkbit-ddi/hawkbit-ddi-starter/pom.xml | 2 +- .../amqp/AmqpMessageDispatcherService.java | 42 ++-- .../hawkbit/amqp/DmfApiConfiguration.java | 9 +- .../amqp/RequeueExceptionStrategy.java | 3 +- .../AmqpMessageDispatcherServiceTest.java | 43 ++-- .../AbstractAmqpServiceIntegrationTest.java | 9 +- ...ssageDispatcherServiceIntegrationTest.java | 5 +- ...pMessageHandlerServiceIntegrationTest.java | 2 +- .../MgmtDownloadArtifactResource.java | 9 +- .../rest/resource/MgmtRolloutResource.java | 11 +- .../resource/MgmtSoftwareModuleResource.java | 24 ++- .../MgmtSystemManagementResource.java | 4 +- .../rest/resource/MgmtTargetResource.java | 33 +-- .../mapper/MgmtSoftwareModuleMapper.java | 19 +- .../resource/mapper/MgmtTargetMapper.java | 4 +- .../MgmtDistributionSetResourceTest.java | 29 ++- .../resource/MgmtRolloutResourceTest.java | 61 +++--- .../MgmtSoftwareModuleResourceTest.java | 79 ++++--- .../rest/resource/MgmtTargetResourceTest.java | 79 ++++--- .../resource/MgmtTargetTypeResourceTest.java | 2 +- hawkbit-mgmt/hawkbit-mgmt-starter/pom.xml | 2 +- .../src/main/resources/application.properties | 2 +- .../repository/ArtifactManagement.java | 20 +- .../repository/ConfirmationManagement.java | 2 +- .../repository/ControllerManagement.java | 18 +- .../repository/DeploymentManagement.java | 4 +- .../repository/DistributionSetManagement.java | 4 +- .../DistributionSetTypeManagement.java | 3 - .../repository/RolloutGroupManagement.java | 20 +- .../hawkbit/repository/RolloutManagement.java | 20 +- .../repository/SizeConversionHelper.java | 40 ---- .../SoftwareModuleTypeManagement.java | 7 - .../hawkbit/repository/SystemManagement.java | 4 +- .../hawkbit/repository/TargetManagement.java | 148 ++++++------- .../repository/TargetTypeManagement.java | 9 +- .../repository/TenantStatsManagement.java | 2 +- .../autoassign/AutoAssignExecutor.java | 8 +- .../repository/event/TenantAwareEvent.java | 4 +- .../event/entity/EntityCreatedEvent.java | 2 +- .../event/entity/EntityDeletedEvent.java | 2 +- .../event/entity/EntityIdEvent.java | 7 +- .../event/entity/EntityUpdatedEvent.java | 2 +- .../event/remote/AbstractRemoteEvent.java | 2 + .../DistributionSetTagDeletedEvent.java | 2 +- .../event/remote/DownloadProgressEvent.java | 10 +- .../event/remote/MultiActionCancelEvent.java | 8 +- .../event/remote/MultiActionEvent.java | 2 + .../event/remote/RemoteIdEvent.java | 12 +- .../TargetAssignDistributionSetEvent.java | 3 +- .../event/remote/TargetPollEvent.java | 2 +- .../remote/entity/AbstractActionEvent.java | 11 +- .../entity/AbstractRolloutGroupEvent.java | 38 +--- .../DistributionSetTagCreatedEvent.java | 3 +- .../entity/DistributionSetUpdatedEvent.java | 9 +- .../service/AbstractServiceRemoteEvent.java | 5 +- .../AssignmentQuotaExceededException.java | 76 ++----- ...utoConfirmationAlreadyActiveException.java | 27 +-- .../CancelActionNotAllowedException.java | 22 +- .../ConcurrentModificationException.java | 66 ------ .../exception/DeletedException.java | 6 +- ...DistributionSetTypeUndefinedException.java | 20 +- .../EntityAlreadyExistsException.java | 25 +-- .../exception/EntityNotFoundException.java | 47 +--- .../exception/EntityReadOnlyException.java | 27 +-- .../ForceQuitActionNotAllowedException.java | 22 +- .../IncompatibleTargetTypeException.java | 42 +--- .../IncompleteDistributionSetException.java | 14 +- .../InsufficientPermissionException.java | 2 +- .../InvalidAutoAssignActionTypeException.java | 5 +- .../InvalidConfirmationFeedbackException.java | 15 +- .../InvalidDistributionSetException.java | 15 +- .../exception/InvalidMD5HashException.java | 52 ----- .../InvalidMaintenanceScheduleException.java | 39 +--- ...tion.java => InvalidMd5HashException.java} | 21 +- ...ion.java => InvalidSha1HashException.java} | 28 +-- ...n.java => InvalidSha256HashException.java} | 28 +-- .../InvalidTargetAttributeException.java | 5 +- ...nvalidTenantConfigurationKeyException.java | 2 +- .../repository/exception/LockedException.java | 14 +- .../MethodNotSupportedException.java | 56 ----- .../MultiAssignmentIsNotEnabledException.java | 33 +-- ...rovidedInMultiAssignmentModeException.java | 33 +-- .../RSQLParameterSyntaxException.java | 31 +-- ...SQLParameterUnsupportedFieldException.java | 33 +-- .../RolloutIllegalStateException.java | 39 +--- ...areModuleNotAssignedToTargetException.java | 12 +- ...TypeNotInDistributionSetTypeException.java | 13 +- .../exception/StopRolloutException.java | 28 +-- .../exception/TargetTypeInUseException.java | 36 +--- .../TargetTypeKeyOrNameRequiredException.java | 8 +- ...TenantConfigurationValidatorException.java | 7 +- ...urationValueChangeNotAllowedException.java | 19 +- .../exception/TenantNotExistException.java | 35 +-- ...ModuleForThisDistributionSetException.java | 18 -- .../hawkbit/repository/model/Action.java | 95 ++++---- .../model/ActionCancellationType.java | 17 +- .../repository/model/ActionProperties.java | 7 +- .../repository/model/ActionStatus.java | 5 +- .../hawkbit/repository/model/Artifact.java | 10 +- .../repository/model/ArtifactUpload.java | 75 +------ .../model/AssignedSoftwareModule.java | 47 ---- .../model/AutoConfirmationStatus.java | 11 +- .../hawkbit/repository/model/BaseEntity.java | 3 +- .../repository/model/DeploymentRequest.java | 68 +++--- .../repository/model/DistributionSet.java | 25 +-- .../DistributionSetInvalidationCount.java | 20 +- .../repository/model/DistributionSetTag.java | 4 +- .../hawkbit/repository/model/PollStatus.java | 19 +- .../model/RepositoryModelConstants.java | 10 +- .../hawkbit/repository/model/Rollout.java | 33 ++- .../repository/model/RolloutGroup.java | 53 ++--- .../model/RolloutGroupsValidation.java | 35 +-- .../repository/model/SoftwareModuleType.java | 6 +- .../hawkbit/repository/model/Statistic.java | 2 +- .../eclipse/hawkbit/repository/model/Tag.java | 3 +- .../hawkbit/repository/model/Target.java | 7 - .../repository/model/TargetFilterQuery.java | 4 +- .../hawkbit/repository/model/TargetTag.java | 4 +- .../hawkbit/repository/model/TargetType.java | 8 +- .../repository/model/TargetUpdateStatus.java | 2 +- .../model/TargetWithActionType.java | 52 +---- .../model/TenantAwareBaseEntity.java | 2 +- .../repository/model/TenantConfiguration.java | 3 +- .../model/TenantConfigurationValue.java | 1 + .../model/TotalTargetCountActionStatus.java | 2 +- .../model/TotalTargetCountStatus.java | 52 ++--- .../report}/SystemUsageReport.java | 18 +- .../report}/SystemUsageReportWithTenants.java | 22 +- .../model => model/report}/TenantUsage.java | 16 +- .../hawkbit/utils/TenantConfigHelper.java | 11 +- .../model/TotalTargetCountStatusTest.java | 2 +- .../event/EventPublisherConfiguration.java | 3 - .../repository/RolloutStatusCache.java | 6 +- .../repository/jpa/utils/ExceptionMapper.java | 2 - .../jpa/model/AbstractJpaBaseEntity.java | 2 +- .../jpa/model/AbstractJpaBaseEntity.java | 2 +- .../jpa/EncryptionAwareDbArtifact.java | 66 ------ .../jpa/JpaRepositoryConfiguration.java | 12 +- .../jpa/management/JpaArtifactManagement.java | 110 +++++----- .../management/JpaConfirmationManagement.java | 2 +- .../management/JpaControllerManagement.java | 44 ++-- .../management/JpaDeploymentManagement.java | 4 +- .../JpaDistributionSetManagement.java | 10 +- .../JpaDistributionSetTypeManagement.java | 5 - .../management/JpaRolloutGroupManagement.java | 46 ++-- .../jpa/management/JpaRolloutManagement.java | 25 ++- .../JpaSoftwareModuleManagement.java | 95 ++++---- .../JpaSoftwareModuleTypeManagement.java | 5 - .../jpa/management/JpaSystemManagement.java | 16 +- .../jpa/management/JpaTargetManagement.java | 36 ++-- .../management/JpaTargetTypeManagement.java | 13 +- .../management/JpaTenantStatsManagement.java | 2 +- .../repository/jpa/model/JpaArtifact.java | 8 - .../condition/PauseRolloutGroupAction.java | 3 +- .../DistributionSetTypeSpecification.java | 12 -- .../TargetTypeSpecification.java | 2 - ...izeAndStorageQuotaCheckingInputStream.java | 6 +- .../jpa/AbstractJpaIntegrationTest.java | 6 - .../DistributionSetAccessControllerTest.java | 12 +- .../jpa/acm/TargetAccessControllerTest.java | 7 +- .../acm/TargetTypeAccessControllerTest.java | 4 - .../autoassign/AutoAssignCheckerIntTest.java | 4 +- .../management/ArtifactManagementTest.java | 123 +++++------ .../management/ControllerManagementTest.java | 72 ++----- .../management/DeploymentManagementTest.java | 106 +++++---- ...ributionSetInvalidationManagementTest.java | 6 +- .../DistributionSetManagementTest.java | 29 +-- .../RolloutGroupManagementTest.java | 10 +- .../jpa/management/RolloutManagementTest.java | 98 +++------ .../SoftwareModuleManagementTest.java | 35 +-- .../SoftwareModuleTypeManagementTest.java | 14 -- .../jpa/management/SystemManagementTest.java | 20 +- .../TargetManagementSearchTest.java | 4 +- .../jpa/management/TargetManagementTest.java | 26 +-- .../management/TargetTagManagementTest.java | 6 +- .../model/EntityInterceptorListenerTest.java | 2 +- .../jpa/rsql/RsqlRolloutFieldTest.java | 2 +- .../jpa/rsql/RsqlRolloutGroupFieldTest.java | 4 +- .../hawkbit-repository-test/pom.xml | 2 +- .../repository/test/TestConfiguration.java | 23 +- .../test/util/AbstractIntegrationTest.java | 15 +- .../util/CleanupTestExecutionListener.java | 2 +- .../repository/test/util/TestdataFactory.java | 16 +- .../hawkbit-test-defaults.properties | 3 +- .../MultiPartFileUploadException.java | 2 +- .../util/FileStreamingFailedException.java | 4 +- .../hawkbit/rest/util/FileStreamingUtil.java | 116 +++++----- .../rest/util/FileStreamingUtilTest.java | 45 +--- .../InMemoryUserAuthoritiesResolver.java | 3 +- .../eclipse/hawkbit/security/MdcHandler.java | 2 +- .../security/SpringSecurityAuditorAware.java | 2 +- hawkbit-test-report/pom.xml | 2 +- site/content/apis/dmf_api.md | 12 +- site/content/guides/clustering.md | 2 +- 305 files changed, 2253 insertions(+), 4566 deletions(-) create mode 100644 hawkbit-artifact/README.md rename hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/{repository/artifact/AbstractArtifactRepository.java => artifact/AbstractArtifactStorage.java} (71%) rename hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/{repository/artifact/ArtifactRepository.java => artifact/ArtifactStorage.java} (74%) rename hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/{repository => }/artifact/encryption/ArtifactEncryption.java (90%) rename hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/{repository/artifact/encryption/ArtifactEncryptionSecretsStore.java => artifact/encryption/ArtifactEncryptionSecretsStorage.java} (64%) rename hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/{repository => }/artifact/encryption/ArtifactEncryptionService.java (92%) rename hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/{repository => }/artifact/exception/ArtifactBinaryNoLongerExistsException.java (62%) rename hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/{repository => }/artifact/exception/ArtifactBinaryNotFoundException.java (56%) rename hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/{repository => }/artifact/exception/ArtifactDeleteFailedException.java (62%) rename hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/{repository => }/artifact/exception/ArtifactEncryptionFailedException.java (73%) rename hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/{repository => }/artifact/exception/ArtifactEncryptionUnsupportedException.java (73%) rename hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/{repository => }/artifact/exception/ArtifactStoreException.java (73%) rename hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/{repository => }/artifact/exception/ArtifactUploadFailedException.java (51%) rename {hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository => hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact}/exception/FileSizeQuotaExceededException.java (63%) rename hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/{repository => }/artifact/exception/HashNotMatchException.java (78%) rename {hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository => hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact}/exception/StorageQuotaExceededException.java (57%) create mode 100644 hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/model/ArtifactHashes.java create mode 100644 hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/model/ArtifactStream.java rename hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/{repository/artifact/model/AbstractDbArtifact.java => artifact/model/StoredArtifactInfo.java} (55%) create mode 100644 hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/urlresolver/ArtifactUrl.java create mode 100644 hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/urlresolver/ArtifactUrlResolver.java create mode 100644 hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/urlresolver/PropertyBasedArtifactUrlResolver.java rename hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/{repository/artifact/urlhandler/ArtifactUrlHandlerProperties.java => artifact/urlresolver/PropertyBasedArtifactUrlResolverProperties.java} (76%) delete mode 100644 hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/model/DbArtifact.java delete mode 100644 hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/model/DbArtifactHash.java delete mode 100644 hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/ApiType.java delete mode 100644 hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/ArtifactUrl.java delete mode 100644 hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/ArtifactUrlHandler.java delete mode 100644 hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/Base62Util.java delete mode 100644 hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/PropertyBasedArtifactUrlHandler.java delete mode 100644 hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/URLPlaceholder.java rename hawkbit-artifact/hawkbit-artifact-api/src/test/java/org/eclipse/hawkbit/{repository => }/artifact/encryption/ArtifactEncryptionServiceTest.java (90%) rename hawkbit-artifact/hawkbit-artifact-api/src/test/java/org/eclipse/hawkbit/{repository/artifact/urlhandler/PropertyBasedArtifactUrlHandlerTest.java => artifact/urlresolver/PropertyBasedArtifactUrlResolverTest.java} (50%) delete mode 100644 hawkbit-artifact/hawkbit-artifact-api/src/test/java/org/eclipse/hawkbit/repository/artifact/urlhandler/Base62UtilTest.java delete mode 100644 hawkbit-artifact/hawkbit-artifact-api/src/test/java/org/eclipse/hawkbit/repository/artifact/urlhandler/URLPlaceholderTest.java create mode 100644 hawkbit-artifact/hawkbit-artifact-fs/README.md rename hawkbit-artifact/{hawkbit-artifact-repository-filesystem => hawkbit-artifact-fs}/pom.xml (95%) rename hawkbit-artifact/{hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/repository/artifact/ArtifactFilesystemProperties.java => hawkbit-artifact-fs/src/main/java/org/eclipse/hawkbit/artifact/fs/FileArtifactProperties.java} (88%) create mode 100644 hawkbit-artifact/hawkbit-artifact-fs/src/main/java/org/eclipse/hawkbit/artifact/fs/FileArtifactStorage.java rename hawkbit-artifact/{hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/autoconfigure/repository/artifact/filesystem/ArtifactFilesystemConfiguration.java => hawkbit-artifact-fs/src/main/java/org/eclipse/hawkbit/autoconfigure/artifact/fs/FileArtifactStorageConfiguration.java} (50%) create mode 100644 hawkbit-artifact/hawkbit-artifact-fs/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports rename hawkbit-artifact/{hawkbit-artifact-repository-filesystem/src/test/java/org/eclipse/hawkbit/repository/artifact/ArtifactFilesystemRepositoryTest.java => hawkbit-artifact-fs/src/test/java/org/eclipse/hawkbit/artifact/fs/FileArtifactStorageTest.java} (74%) delete mode 100644 hawkbit-artifact/hawkbit-artifact-repository-filesystem/README.md delete mode 100644 hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/repository/artifact/ArtifactFileNotFoundException.java delete mode 100644 hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/repository/artifact/ArtifactFilesystem.java delete mode 100644 hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/repository/artifact/ArtifactFilesystemRepository.java delete mode 100644 hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/test/java/org/eclipse/hawkbit/repository/artifact/ArtifactFilesystemTest.java rename hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/artifact/{ArtifactUrlHandlerAutoConfiguration.java => PropertyBasedArtifactUrlResolverAutoConfiguration.java} (52%) rename hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/{AsyncConfigurerThreadPoolProperties.java => ExecutorProperties.java} (92%) rename hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/{InMemoryUserManagementAutoConfiguration.java => StaticUserManagementAutoConfiguration.java} (89%) rename hawkbit-core/src/main/java/org/eclipse/hawkbit/{ => tenancy}/cache/TenantAwareCacheManager.java (87%) rename hawkbit-core/src/main/java/org/eclipse/hawkbit/{cache/TenancyCacheManager.java => tenancy/cache/TenantCacheManager.java} (90%) rename hawkbit-core/src/test/java/org/eclipse/hawkbit/repository/{FileNameFieldsTest.java => RsqlQueryFieldsTest.java} (89%) delete mode 100644 hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SizeConversionHelper.java delete mode 100644 hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ConcurrentModificationException.java delete mode 100644 hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidMD5HashException.java rename hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/{InvalidTargetAddressException.java => InvalidMd5HashException.java} (51%) rename hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/{InvalidSHA1HashException.java => InvalidSha1HashException.java} (54%) rename hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/{InvalidSHA256HashException.java => InvalidSha256HashException.java} (54%) delete mode 100644 hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/MethodNotSupportedException.java delete mode 100644 hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/AssignedSoftwareModule.java rename hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/{report/model => model/report}/SystemUsageReport.java (64%) rename hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/{report/model => model/report}/SystemUsageReportWithTenants.java (65%) rename hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/{report/model => model/report}/TenantUsage.java (73%) delete mode 100644 hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/EncryptionAwareDbArtifact.java diff --git a/.3rd-party/README.md b/.3rd-party/README.md index f41d19886..94a755e46 100644 --- a/.3rd-party/README.md +++ b/.3rd-party/README.md @@ -1,10 +1,16 @@ -# Third-Party Dependencies +Third-Party Dependencies +=== -This folder provides listings of all 3rd-party dependencies incl. their licenses. There is a dedicated subfolder for -each release (and milestone) holding the release-specific information. +This folder contains DEPENDENCIES that has the list of all 3rd-party dependencies (including transitive) with their licenses and approval status. Each release (and milestone) holds the release-specific information. -The DEPENDENCIES file could be generated manually using [Eclipse Dash License Tool](https://github.com/eclipse/dash-licenses) maven plugin by running in root folder: +DEPENDENCIES file is generated (automatically and committed) by [../.github/workflows/reusable_workflow_license-scan.yaml](../.github/workflows/reusable_workflow_license-scan.yaml) during the release process ([../.github/workflows/release.yaml](../.github/workflows/release.yaml)) and on daily basis ([../.github/workflows/license-scan.yaml](../.github/workflows/license-scan.yaml)). It is also + +DEPENDENCIES file could be generated manually using [Eclipse Dash License Tool](https://github.com/eclipse/dash-licenses) maven plugin by running: ```shell -mvn clean install -PcheckLicense -DskipTests \ - --projects '!org.eclipse.hawkbit:hawkbit-repository-test,!org.eclipse.hawkbit:hawkbit-dmf-rabbitmq-test' +$ cd .. && mvn license-tool:license-check -Ddash.fail=false -PcheckLicense +``` + +Note: Some projects (e.g. test artifacts) could be excluded with *--projects* parameter, e.g: +```shell +$ cd .. && mvn license-tool:license-check -Ddash.fail=false -PcheckLicense \ --projects '!org.eclipse.hawkbit:hawkbit-repository-test,!org.eclipse.hawkbit:hawkbit-dmf-rabbitmq-test' ``` diff --git a/.github/workflows/reusable_workflow_license-scan.yaml b/.github/workflows/reusable_workflow_license-scan.yaml index b2fd670e9..23f957dff 100644 --- a/.github/workflows/reusable_workflow_license-scan.yaml +++ b/.github/workflows/reusable_workflow_license-scan.yaml @@ -50,7 +50,7 @@ jobs: - name: Check dependency licenses with dash tool (and open issues to Dash IP lab, doesn't fail) if: ${{ inputs.open_tickets }} run: | - mvn license-tool:license-check -Ddash.fail=false -PcheckLicense -Ddash.iplab.token=${GITLAB_API_TOKEN} --projects '!org.eclipse.hawkbit:hawkbit-repository-test,!org.eclipse.hawkbit:hawkbit-dmf-rabbitmq-test' + mvn license-tool:license-check -Ddash.fail=false -PcheckLicense -Ddash.iplab.token=${GITLAB_API_TOKEN} CHANGED_FILES_COUNT=$(git status --short | wc -l) CHANGED_FILES_COUNT=${CHANGED_FILES_COUNT//[[:space:]]/} echo "Number of changed files: ${CHANGED_FILES_COUNT}" diff --git a/docker/README.md b/docker/README.md index 028cd49e0..97f9dc6b2 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,24 +1,33 @@ hawkBit Docker === -# Setup +## Overview +This folder contains example Docker build and Docker Compose files to build and start the hawkBit as monolith or as microservices. -## A: Docker Container -Start the hawkBit Update Server as a single container (requires Docker to be installed and all dependencies to be available) +## Build +You could build the hawkbit Docker images following the [README.md](build/README.md) instructions. + +## Start +You can start hawkbit as a Docker Container (only monolith) or with Docker Compose + +#### A: Docker Container (only as monolith) +_Note: You need to have Docker installed on your machine._ + +Start the hawkBit Update Server (monolith) as a single container (with embedded H2, if you configure a different database, e.g. MySQL or PostgreSQL, you should start it separately): ```bash $ docker run -d -p 8080:8080 hawkbit/hawkbit-update-server:latest ``` -## B: Docker Compose -Start the hawkBit Update Server together with an MySQL and RabbitMQ instance as containers (Requires Docker Compose to be installed) +### B: Docker Compose +_Note: You need to have Docker Compose installed on your machine._ + +Start the hawkBit Update Server (monolith) together with an MySQL and RabbitMQ instance as containers (Requires Docker Compose to be installed) ```bash $ docker compose -f mysql/docker-compose-monolith-mysql.yml up ``` -You could, also start it in different flavours, with UI or in microservices mode. - -Note: Whit the upper command CTRL+C shuts down all services. Add '-d' at the end to start all into detached mode: +With the upper command CTRL+C shuts down all services. Add '-d' at the end to start all into detached mode: ```bash $ docker compose -f mysql/docker-compose-monolith-mysql.yml up -d ``` @@ -27,15 +36,20 @@ Then stop all services with: $ docker compose -f mysql/docker-compose-monolith-mysql.yml down ``` -# Access -| Service / Container | URL | Login | A | B | C | -|--------------------------|--------------------------------------------------|-------------|----------|----------|----------| -| hawkBit Update Server | [http://localhost:8080/](http://localhost:8080/) | admin:admin | ✓ | ✓ | ✓ | -| MySQL | localhost:3306/hawkbit | root | | ✓ | ✓ | -| RabbitMQ | [http://localhost:15672](http://localhost:15672) | guest:guest | | ✓ | ✓ | +You could, also start it in different flavours, with UI or in microservices mode (see Docker Compose files in [mysql](./mysql) and [postgres](./postgres) folders). For instance to start with PostgreSQL, with RabbitMQ, in microservices mode and with UI you could use: +```bash +$ docker compose -f postgres/docker-compose-micro-services-with-simple-ui-postgres.yml up +``` -# Configuration -You can override application.properties by setting an environment variable SPRING_APPLICATION_JSON for hawkbit container. +### Access +| Service / Container | URL | Login | A | B | +|-----------------------|------------------------|-------------|----------|----------| +| hawkBit Update Server | [http://localhost:8080/](http://localhost:8080/) | admin:admin | ✓ | ✓ | +| MySQL | localhost:3306/hawkbit | root | | ✓ | +| RabbitMQ | [http://localhost:15672](http://localhost:15672) | guest:guest | | ✓ | + +### Configuration +You can override _application.properties_ by setting an environment variable _SPRING_APPLICATION_JSON_ to the hawkbit container, e.g.: ```yaml hawkbit: @@ -55,4 +69,4 @@ hawkbit: "hawkbit.security.user.hawkbit.password": "{noop}isAwesome!", "hawkbit.security.user.hawkbit.roles": "TENANT_ADMIN" }' -``` +``` \ No newline at end of file diff --git a/docker/build/README.md b/docker/build/README.md index c3e0cf222..c3094e1e5 100644 --- a/docker/build/README.md +++ b/docker/build/README.md @@ -28,9 +28,7 @@ Docker image could be build, for example, with (fixed version 0.4.1 is just an e ```shell docker build --build-arg HAWKBIT_APP=hawkbit-update-server --build-arg HAWKBIT_VERSION=0.4.1 -t hawkbit_update_server:0.4.1 . -f Dockerfile ``` - or just by: - ```shell docker build --build-arg HAWKBIT_VERSION=0.4.1 -t hawkbit_update_server:0.4.1 . ``` diff --git a/hawkbit-artifact/README.md b/hawkbit-artifact/README.md new file mode 100644 index 000000000..b1b67d257 --- /dev/null +++ b/hawkbit-artifact/README.md @@ -0,0 +1,5 @@ +hawkBit Artifact +=== +The module contains internal modules for artifact storage and encryption: +* [hawkbit-artifact-api](hawkbit-artifact-api/README.md) - see for artifact API module +* [hawkbit-artifact-fs](hawkbit-artifact-fs/README.md) - see for file-system based artifact storage implementation \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-api/README.md b/hawkbit-artifact/hawkbit-artifact-api/README.md index 49dc970ba..623245991 100644 --- a/hawkbit-artifact/hawkbit-artifact-api/README.md +++ b/hawkbit-artifact/hawkbit-artifact-api/README.md @@ -1,3 +1,6 @@ -# hawkBit Artifact API - -Various internal interfaces artifact API classes. \ No newline at end of file +hawkBit Artifact API +=== +The module contains artifact API classes supporting following main concepts: +* Artifact Storage - represented by the [ArtifactStorage](src/main/java/org/eclipse/hawkbit/artifact/ArtifactStorage.java) interface. It serves for artifact binary store operations +* Artifact Encryption - represented by the [ArtifactEncryptionService](src/main/java/org/eclipse/hawkbit/artifact/encryption/ArtifactEncryptionService.java). It is a pluggable implementation of artifact encryption operations. +* Artifact URL handling - represented by[ArtifactUrlResolver](src/main/java/org/eclipse/hawkbit/artifact/urlresolver/ArtifactUrlResolver.java) interface. It provides resolving URLs to the artifacts. The module provides a simple property based implementation ([PropertyBasedArtifactUrlResolver](src/main/java/org/eclipse/hawkbit/artifact/urlresolver/PropertyBasedArtifactUrlResolver.java)) \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/AbstractArtifactRepository.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/AbstractArtifactStorage.java similarity index 71% rename from hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/AbstractArtifactRepository.java rename to hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/AbstractArtifactStorage.java index 966b88df2..1b494e1b6 100644 --- a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/AbstractArtifactRepository.java +++ b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/AbstractArtifactStorage.java @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.artifact; +package org.eclipse.hawkbit.artifact; import java.io.BufferedOutputStream; import java.io.File; @@ -22,17 +22,17 @@ import java.security.NoSuchAlgorithmException; import java.util.HexFormat; import lombok.extern.slf4j.Slf4j; -import org.eclipse.hawkbit.repository.artifact.exception.ArtifactStoreException; -import org.eclipse.hawkbit.repository.artifact.exception.HashNotMatchException; -import org.eclipse.hawkbit.repository.artifact.model.AbstractDbArtifact; -import org.eclipse.hawkbit.repository.artifact.model.DbArtifactHash; +import org.eclipse.hawkbit.artifact.exception.ArtifactStoreException; +import org.eclipse.hawkbit.artifact.exception.HashNotMatchException; +import org.eclipse.hawkbit.artifact.model.ArtifactHashes; +import org.eclipse.hawkbit.artifact.model.StoredArtifactInfo; import org.springframework.util.ObjectUtils; /** * Abstract utility class for ArtifactRepository implementations with common functionality, e.g. computation of hashes. */ @Slf4j -public abstract class AbstractArtifactRepository implements ArtifactRepository { +public abstract class AbstractArtifactStorage implements ArtifactStorage { private static final String TEMP_FILE_PREFIX = "tmp"; private static final String TEMP_FILE_SUFFIX = "artifactrepo"; @@ -40,9 +40,9 @@ public abstract class AbstractArtifactRepository implements ArtifactRepository { // suppress warning, of not strong enough hashing algorithm, SHA-1 and MD5 is not used security related @SuppressWarnings("squid:S2070") @Override - public AbstractDbArtifact store( + public StoredArtifactInfo store( final String tenant, final InputStream content, final String filename, final String contentType, - final DbArtifactHash providedHashes) { + final ArtifactHashes providedHashes) { final MessageDigest mdSHA1; final MessageDigest mdMD5; final MessageDigest mdSHA256; @@ -60,19 +60,19 @@ public abstract class AbstractArtifactRepository implements ArtifactRepository { final HexFormat hexFormat = HexFormat.of().withLowerCase(); - final String sha1Hash16 = hexFormat.formatHex(mdSHA1.digest()); - final String md5Hash16 = hexFormat.formatHex(mdMD5.digest()); - final String sha256Hash16 = hexFormat.formatHex(mdSHA256.digest()); + final String sha1Hash = hexFormat.formatHex(mdSHA1.digest()); + final String md5Hash = hexFormat.formatHex(mdMD5.digest()); + final String sha256Hash = hexFormat.formatHex(mdSHA256.digest()); - checkHashes(providedHashes, sha1Hash16, md5Hash16, sha256Hash16); + checkHashes(providedHashes, sha1Hash, md5Hash, sha256Hash); // Check if file with same sha1 hash exists and if so return it - if (existsBySha1(tenant, sha1Hash16)) { + if (existsBySha1(tenant, sha1Hash)) { // TODO - shall check if the file is really the same as bytes or just sha1 hash is the same - return addMissingHashes(getBySha1(tenant, sha1Hash16), sha1Hash16, md5Hash16, sha256Hash16); + return new StoredArtifactInfo(contentType, tempFile.length(), new ArtifactHashes(sha1Hash, md5Hash, sha256Hash)); } - return store(sanitizeTenant(tenant), new DbArtifactHash(sha1Hash16, md5Hash16, sha256Hash16), contentType, tempFile); + return store(sanitizeTenant(tenant), new ArtifactHashes(sha1Hash, md5Hash, sha256Hash), contentType, tempFile); } catch (final IOException e) { throw new ArtifactStoreException(e.getMessage(), e); } finally { @@ -104,13 +104,13 @@ public abstract class AbstractArtifactRepository implements ArtifactRepository { return file.getPath(); } - protected abstract AbstractDbArtifact store(final String tenant, final DbArtifactHash base16Hashes, - final String contentType, final String tempFile) throws IOException; + protected abstract StoredArtifactInfo store( + final String tenant, final ArtifactHashes base16Hashes, final String contentType, final String tempFile) throws IOException; // java:S1066 - more readable with separate "if" statements // java:S4042 - delete reason is not needed @SuppressWarnings({ "java:S1066", "java:S4042" }) - static File createTempFile(final boolean directory) { + public static File createTempFile(final boolean directory) { try { final File file = (directory ? Files.createTempDirectory(TEMP_FILE_PREFIX) @@ -138,22 +138,22 @@ public abstract class AbstractArtifactRepository implements ArtifactRepository { } } - private static void checkHashes(final DbArtifactHash providedHashes, - final String sha1Hash16, final String md5Hash16, final String sha256Hash16) { + private static void checkHashes( + final ArtifactHashes providedHashes, final String sha1Hash16, final String md5Hash16, final String sha256Hash16) { if (providedHashes == null) { return; } - if (areHashesNotMatching(providedHashes.getSha1(), sha1Hash16)) { - throw new HashNotMatchException("The given sha1 hash " + providedHashes.getSha1() + + if (areHashesNotMatching(providedHashes.sha1(), sha1Hash16)) { + throw new HashNotMatchException("The given sha1 hash " + providedHashes.sha1() + " does not match the calculated sha1 hash " + sha1Hash16, HashNotMatchException.SHA1); } - if (areHashesNotMatching(providedHashes.getMd5(), md5Hash16)) { - throw new HashNotMatchException("The given md5 hash " + providedHashes.getMd5() + + if (areHashesNotMatching(providedHashes.md5(), md5Hash16)) { + throw new HashNotMatchException("The given md5 hash " + providedHashes.md5() + " does not match the calculated md5 hash " + md5Hash16, HashNotMatchException.MD5); } - if (areHashesNotMatching(providedHashes.getSha256(), sha256Hash16)) { - throw new HashNotMatchException("The given sha256 hash " + providedHashes.getSha256() + + if (areHashesNotMatching(providedHashes.sha256(), sha256Hash16)) { + throw new HashNotMatchException("The given sha256 hash " + providedHashes.sha256() + " does not match the calculated sha256 hash " + sha256Hash16, HashNotMatchException.SHA256); } } @@ -167,16 +167,6 @@ public abstract class AbstractArtifactRepository implements ArtifactRepository { return new DigestInputStream(new DigestInputStream(new DigestInputStream(input, mdSHA256), mdMD5), mdSHA1); } - private AbstractDbArtifact addMissingHashes(final AbstractDbArtifact existing, - final String calculatedSha1, final String calculatedMd5, final String calculatedSha256) { - final String sha1 = checkEmpty(existing.getHashes().getSha1(), calculatedSha1); - final String md5 = checkEmpty(existing.getHashes().getMd5(), calculatedMd5); - final String sha256 = checkEmpty(existing.getHashes().getSha256(), calculatedSha256); - - existing.setHashes(new DbArtifactHash(sha1, md5, sha256)); - return existing; - } - private String checkEmpty(final String value, final String fallback) { return ObjectUtils.isEmpty(value) ? fallback : value; } diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/ArtifactRepository.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/ArtifactStorage.java similarity index 74% rename from hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/ArtifactRepository.java rename to hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/ArtifactStorage.java index b322cb465..b1c7e53c1 100644 --- a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/ArtifactRepository.java +++ b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/ArtifactStorage.java @@ -7,22 +7,23 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.artifact; +package org.eclipse.hawkbit.artifact; import java.io.InputStream; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; -import org.eclipse.hawkbit.repository.artifact.exception.ArtifactStoreException; -import org.eclipse.hawkbit.repository.artifact.exception.HashNotMatchException; -import org.eclipse.hawkbit.repository.artifact.model.AbstractDbArtifact; -import org.eclipse.hawkbit.repository.artifact.model.DbArtifactHash; +import org.eclipse.hawkbit.artifact.exception.ArtifactBinaryNotFoundException; +import org.eclipse.hawkbit.artifact.exception.ArtifactStoreException; +import org.eclipse.hawkbit.artifact.exception.HashNotMatchException; +import org.eclipse.hawkbit.artifact.model.ArtifactHashes; +import org.eclipse.hawkbit.artifact.model.StoredArtifactInfo; /** - * ArtifactRepository service interface. + * Artifact Store service interface. */ -public interface ArtifactRepository { +public interface ArtifactStorage { /** * Stores an artifact into the repository. @@ -37,20 +38,20 @@ public interface ArtifactRepository { * @throws ArtifactStoreException in case storing of the artifact was not successful * @throws HashNotMatchException in case {@code hash} is provided and not matching to the calculated hashes during storing */ - AbstractDbArtifact store( + StoredArtifactInfo store( @NotEmpty String tenant, @NotNull InputStream content, @NotEmpty String filename, - String contentType, DbArtifactHash hash); + String contentType, ArtifactHashes hash); /** - * Retrieves a {@link AbstractDbArtifact} from the store by its SHA1 hash. Throws {@link org.eclipse.hawkbit.repository.artifact.exception.ArtifactBinaryNotFoundException} if not found. + * Retrieves a {@link StoredArtifactInfo} from the store by its SHA1 hash. Throws {@link ArtifactBinaryNotFoundException} if not found. + * The caller is responsible to close the InputStream. * * @param tenant the tenant to store the artifact * @param sha1Hash the sha1-hash of the file to lookup. * @return The artifact file object or {@code null} if no file exists. * @throws UnsupportedOperationException if implementation does not support the operation */ - AbstractDbArtifact getBySha1(@NotEmpty String tenant, @NotEmpty String sha1Hash); - + InputStream getBySha1(@NotEmpty String tenant, @NotEmpty String sha1Hash); /** * Checks if an artifact exists for a given tenant by its sha1 hash diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/encryption/ArtifactEncryption.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/encryption/ArtifactEncryption.java similarity index 90% rename from hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/encryption/ArtifactEncryption.java rename to hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/encryption/ArtifactEncryption.java index 8d576ab56..023ba301f 100644 --- a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/encryption/ArtifactEncryption.java +++ b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/encryption/ArtifactEncryption.java @@ -7,13 +7,13 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.artifact.encryption; +package org.eclipse.hawkbit.artifact.encryption; import java.io.InputStream; import java.util.Map; import java.util.Set; -import org.eclipse.hawkbit.repository.artifact.exception.ArtifactEncryptionFailedException; +import org.eclipse.hawkbit.artifact.exception.ArtifactEncryptionFailedException; /** * Interface definition for artifact encryption. @@ -23,7 +23,7 @@ public interface ArtifactEncryption { /** * Defines the required secret keys for particular encryption algorithm. * - * @return list of required secret keys + * @return set of required secret keys */ Set requiredSecretKeys(); @@ -61,4 +61,4 @@ public interface ArtifactEncryption { * @return encryption overhead in byte */ int encryptionSizeOverhead(); -} +} \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/encryption/ArtifactEncryptionSecretsStore.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/encryption/ArtifactEncryptionSecretsStorage.java similarity index 64% rename from hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/encryption/ArtifactEncryptionSecretsStore.java rename to hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/encryption/ArtifactEncryptionSecretsStorage.java index c1e62572a..c347e796b 100644 --- a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/encryption/ArtifactEncryptionSecretsStore.java +++ b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/encryption/ArtifactEncryptionSecretsStorage.java @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.artifact.encryption; +package org.eclipse.hawkbit.artifact.encryption; import java.util.Optional; @@ -15,7 +15,7 @@ import java.util.Optional; * Interface definition for artifact encryption secrets store. It maintains secret key/value pairs * identified by id (e.g. software module id) */ -public interface ArtifactEncryptionSecretsStore { +public interface ArtifactEncryptionSecretsStorage { /** * Adds secret key/value pair associated with particular id (e.g. software module id) to the store. @@ -26,14 +26,6 @@ public interface ArtifactEncryptionSecretsStore { */ void addSecret(final long id, final String secretKey, final String secretValue); - /** - * Checks if secret is present for particular id and key in the store. - * - * @param id id of the secret - * @param secretKey key of the secret - */ - boolean secretExists(final long id, final String secretKey); - /** * Retrieves secret value associated with particular id and key from the store. * @@ -41,12 +33,4 @@ public interface ArtifactEncryptionSecretsStore { * @param secretKey key of the secret */ Optional getSecret(final long id, final String secretKey); - - /** - * Removes secret key/value pair associated with particular id from the store. - * - * @param id id of the secret - * @param secretKey key of the secret - */ - void removeSecret(final long id, final String secretKey); } \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/encryption/ArtifactEncryptionService.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/encryption/ArtifactEncryptionService.java similarity index 92% rename from hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/encryption/ArtifactEncryptionService.java rename to hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/encryption/ArtifactEncryptionService.java index 5e76fe06c..22f5fb3b8 100644 --- a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/encryption/ArtifactEncryptionService.java +++ b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/encryption/ArtifactEncryptionService.java @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.artifact.encryption; +package org.eclipse.hawkbit.artifact.encryption; import java.io.InputStream; import java.util.HashMap; @@ -17,12 +17,11 @@ import java.util.Set; import lombok.AccessLevel; import lombok.NoArgsConstructor; -import org.eclipse.hawkbit.repository.artifact.exception.ArtifactEncryptionUnsupportedException; +import org.eclipse.hawkbit.artifact.exception.ArtifactEncryptionUnsupportedException; import org.springframework.beans.factory.annotation.Autowired; /** - * Service responsible for encryption operations. Should be registered as a bean in order its autowired dependencies - * to be injected. + * Service responsible for encryption operations. Should be registered as a bean in order its autowired dependencies to be injected. */ @NoArgsConstructor(access = AccessLevel.PRIVATE) @SuppressWarnings("java:S6548") // singleton holder ensures static access to spring resources in some places @@ -31,7 +30,7 @@ public final class ArtifactEncryptionService { private static final ArtifactEncryptionService SINGLETON = new ArtifactEncryptionService(); private ArtifactEncryption artifactEncryption; - private ArtifactEncryptionSecretsStore artifactEncryptionSecretsStore; + private ArtifactEncryptionSecretsStorage artifactEncryptionSecretsStore; /** * @return the artifact encryption service singleton instance @@ -46,7 +45,7 @@ public final class ArtifactEncryptionService { } @Autowired(required = false) // spring setter injection - public void setArtifactEncryptionSecretsStore(final ArtifactEncryptionSecretsStore artifactEncryptionSecretsStore) { + public void setArtifactEncryptionSecretsStore(final ArtifactEncryptionSecretsStorage artifactEncryptionSecretsStore) { this.artifactEncryptionSecretsStore = artifactEncryptionSecretsStore; } @@ -111,7 +110,7 @@ public final class ArtifactEncryptionService { throw new ArtifactEncryptionUnsupportedException("Artifact decryption is not supported."); } - final var secrets = getEncryptionSecrets(id); + final Map secrets = getEncryptionSecrets(id); try { return artifactEncryption.decryptStream(secrets, encryptedArtifactStream); } finally { diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/exception/ArtifactBinaryNoLongerExistsException.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/ArtifactBinaryNoLongerExistsException.java similarity index 62% rename from hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/exception/ArtifactBinaryNoLongerExistsException.java rename to hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/ArtifactBinaryNoLongerExistsException.java index e85e6f577..8eaca6311 100644 --- a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/exception/ArtifactBinaryNoLongerExistsException.java +++ b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/ArtifactBinaryNoLongerExistsException.java @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.artifact.exception; +package org.eclipse.hawkbit.artifact.exception; import java.io.Serial; @@ -28,29 +28,7 @@ public class ArtifactBinaryNoLongerExistsException extends AbstractServerRtExcep private static final SpServerError THIS_ERROR = SpServerError.SP_ARTIFACT_BINARY_DELETED; - /** - * Creates a new ArtifactBinaryGoneException error. - */ public ArtifactBinaryNoLongerExistsException() { super(THIS_ERROR); } - - /** - * Creates a new ArtifactBinaryGoneException error with cause. - * - * @param cause for the exception - */ - public ArtifactBinaryNoLongerExistsException(final Throwable cause) { - super(THIS_ERROR, cause); - } - - /** - * Creates a new ArtifactBinaryGoneException error with message. - * - * @param message of the error - */ - public ArtifactBinaryNoLongerExistsException(final String message) { - super(message, THIS_ERROR); - } - -} +} \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/exception/ArtifactBinaryNotFoundException.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/ArtifactBinaryNotFoundException.java similarity index 56% rename from hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/exception/ArtifactBinaryNotFoundException.java rename to hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/ArtifactBinaryNotFoundException.java index 5179a8e54..18e8021cc 100644 --- a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/exception/ArtifactBinaryNotFoundException.java +++ b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/ArtifactBinaryNotFoundException.java @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.artifact.exception; +package org.eclipse.hawkbit.artifact.exception; import java.io.Serial; @@ -23,25 +23,7 @@ public final class ArtifactBinaryNotFoundException extends AbstractServerRtExcep @Serial private static final long serialVersionUID = 1L; - /** - * Creates a new FileUploadFailedException with - * {@link SpServerError#SP_ARTIFACT_LOAD_FAILED} error. - */ - public ArtifactBinaryNotFoundException() { - super(SpServerError.SP_ARTIFACT_LOAD_FAILED); - } - - /** - * @param cause for the exception - */ - public ArtifactBinaryNotFoundException(final Throwable cause) { - super(SpServerError.SP_ARTIFACT_LOAD_FAILED, cause); - } - - /** - * @param message of the error - */ public ArtifactBinaryNotFoundException(final String message) { - super(message, SpServerError.SP_ARTIFACT_LOAD_FAILED); + super(SpServerError.SP_ARTIFACT_LOAD_FAILED, message); } -} +} \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/exception/ArtifactDeleteFailedException.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/ArtifactDeleteFailedException.java similarity index 62% rename from hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/exception/ArtifactDeleteFailedException.java rename to hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/ArtifactDeleteFailedException.java index 0f7e05418..05b5dcfe8 100644 --- a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/exception/ArtifactDeleteFailedException.java +++ b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/ArtifactDeleteFailedException.java @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.artifact.exception; +package org.eclipse.hawkbit.artifact.exception; import java.io.Serial; @@ -26,25 +26,7 @@ public final class ArtifactDeleteFailedException extends AbstractServerRtExcepti @Serial private static final long serialVersionUID = 1L; - /** - * Creates a new FileUploadFailedException with - * {@link SpServerError#SP_ARTIFACT_DELETE_FAILED} error. - */ - public ArtifactDeleteFailedException() { - super(SpServerError.SP_ARTIFACT_DELETE_FAILED); - } - - /** - * @param cause for the exception - */ public ArtifactDeleteFailedException(final Throwable cause) { super(SpServerError.SP_ARTIFACT_DELETE_FAILED, cause); } - - /** - * @param message of the error - */ - public ArtifactDeleteFailedException(final String message) { - super(message, SpServerError.SP_ARTIFACT_DELETE_FAILED); - } -} +} \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/exception/ArtifactEncryptionFailedException.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/ArtifactEncryptionFailedException.java similarity index 73% rename from hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/exception/ArtifactEncryptionFailedException.java rename to hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/ArtifactEncryptionFailedException.java index edc8150ee..d5d025542 100644 --- a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/exception/ArtifactEncryptionFailedException.java +++ b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/ArtifactEncryptionFailedException.java @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.artifact.exception; +package org.eclipse.hawkbit.artifact.exception; import java.io.Serial; @@ -35,16 +35,8 @@ public final class ArtifactEncryptionFailedException extends AbstractServerRtExc @Getter private final EncryptionOperation encryptionOperation; - public ArtifactEncryptionFailedException(final EncryptionOperation encryptionOperation) { - this(encryptionOperation, null, null); - } - - public ArtifactEncryptionFailedException(final EncryptionOperation encryptionOperation, final String message) { - this(encryptionOperation, message, null); - } - public ArtifactEncryptionFailedException(final EncryptionOperation encryptionOperation, final String message, final Throwable cause) { - super(message, SpServerError.SP_ARTIFACT_ENCRYPTION_FAILED, cause); + super(SpServerError.SP_ARTIFACT_ENCRYPTION_FAILED, message, cause); this.encryptionOperation = encryptionOperation; } } \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/exception/ArtifactEncryptionUnsupportedException.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/ArtifactEncryptionUnsupportedException.java similarity index 73% rename from hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/exception/ArtifactEncryptionUnsupportedException.java rename to hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/ArtifactEncryptionUnsupportedException.java index ea2c2c76b..8a1656e4a 100644 --- a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/exception/ArtifactEncryptionUnsupportedException.java +++ b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/ArtifactEncryptionUnsupportedException.java @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.artifact.exception; +package org.eclipse.hawkbit.artifact.exception; import java.io.Serial; @@ -22,17 +22,7 @@ public final class ArtifactEncryptionUnsupportedException extends AbstractServer @Serial private static final long serialVersionUID = 1L; - /** - * Constructor. - */ - public ArtifactEncryptionUnsupportedException() { - super(SpServerError.SP_ARTIFACT_ENCRYPTION_NOT_SUPPORTED); - } - - /** - * @param message of the error - */ public ArtifactEncryptionUnsupportedException(final String message) { - super(message, SpServerError.SP_ARTIFACT_ENCRYPTION_NOT_SUPPORTED); + super(SpServerError.SP_ARTIFACT_ENCRYPTION_NOT_SUPPORTED, message); } -} +} \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/exception/ArtifactStoreException.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/ArtifactStoreException.java similarity index 73% rename from hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/exception/ArtifactStoreException.java rename to hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/ArtifactStoreException.java index 5d4e5dc0e..cf767fdbc 100644 --- a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/exception/ArtifactStoreException.java +++ b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/ArtifactStoreException.java @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.artifact.exception; +package org.eclipse.hawkbit.artifact.exception; import java.io.Serial; @@ -19,12 +19,10 @@ public class ArtifactStoreException extends RuntimeException { @Serial private static final long serialVersionUID = 1L; - /** - * Constructs a ArtifactStoreException with message and cause. - * - * @param message the message of the exception - * @param cause of the exception - */ + public ArtifactStoreException(final String message) { + this(message, null); + } + public ArtifactStoreException(final String message, final Throwable cause) { super(message, cause); } diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/exception/ArtifactUploadFailedException.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/ArtifactUploadFailedException.java similarity index 51% rename from hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/exception/ArtifactUploadFailedException.java rename to hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/ArtifactUploadFailedException.java index 4647b210f..c99ce2bc7 100644 --- a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/exception/ArtifactUploadFailedException.java +++ b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/ArtifactUploadFailedException.java @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.artifact.exception; +package org.eclipse.hawkbit.artifact.exception; import java.io.Serial; @@ -23,34 +23,7 @@ public final class ArtifactUploadFailedException extends AbstractServerRtExcepti @Serial private static final long serialVersionUID = 1L; - /** - * Creates a new FileUploadFailedException with - * {@link SpServerError#SP_ARTIFACT_UPLOAD_FAILED} error. - */ - public ArtifactUploadFailedException() { - super(SpServerError.SP_ARTIFACT_UPLOAD_FAILED); - } - - /** - * @param cause for the exception - */ public ArtifactUploadFailedException(final Throwable cause) { super(SpServerError.SP_ARTIFACT_UPLOAD_FAILED, cause); } - - /** - * @param message of the error - */ - public ArtifactUploadFailedException(final String message) { - super(message, SpServerError.SP_ARTIFACT_UPLOAD_FAILED); - } - - /** - * @param message for the error - * @param cause of the error - */ - public ArtifactUploadFailedException(final String message, final Throwable cause) { - super(message, SpServerError.SP_ARTIFACT_UPLOAD_FAILED, cause); - } - -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/FileSizeQuotaExceededException.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/FileSizeQuotaExceededException.java similarity index 63% rename from hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/FileSizeQuotaExceededException.java rename to hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/FileSizeQuotaExceededException.java index 4c8777d6e..ca3910215 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/FileSizeQuotaExceededException.java +++ b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/FileSizeQuotaExceededException.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019 Bosch Software Innovations GmbH and others + * Copyright (c) 2025 Contributors to the Eclipse Foundation * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -7,9 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.exception; - -import static org.eclipse.hawkbit.repository.SizeConversionHelper.byteValueToReadableString; +package org.eclipse.hawkbit.artifact.exception; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -26,28 +24,28 @@ public class FileSizeQuotaExceededException extends AbstractServerRtException { private static final String MAX_ARTIFACT_SIZE_EXCEEDED = "Maximum artifact size (%s) exceeded."; private static final SpServerError errorType = SpServerError.SP_FILE_SIZE_QUOTA_EXCEEDED; + private static final String KB = "KB"; + private static final String MB = "MB"; + private final long exceededQuotaValue; - /** - * Creates a new FileSizeQuotaExceededException with a quota value. - * - * @param exceededQuotaValue Value by how much the quota was exceeded - */ public FileSizeQuotaExceededException(final long exceededQuotaValue) { - super(createQuotaErrorMessage(exceededQuotaValue), errorType); + super(errorType, createQuotaErrorMessage(exceededQuotaValue)); this.exceededQuotaValue = exceededQuotaValue; } - /** - * Get a readable string of size quota including unit - * - * @return file size quota with unit - */ - public String getExceededQuotaValueString() { - return byteValueToReadableString(exceededQuotaValue); - } - private static String createQuotaErrorMessage(final long exceededQuotaValue) { return String.format(MAX_ARTIFACT_SIZE_EXCEEDED, byteValueToReadableString(exceededQuotaValue)); } + + static String byteValueToReadableString(final long byteValue) { + double outputValue = byteValue / 1024.0; + String unit = KB; + if (outputValue >= 1024) { + outputValue = outputValue / 1024.0; + unit = MB; + } + // We cut decimal places to avoid localization handling + return (long) outputValue + " " + unit; + } } diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/exception/HashNotMatchException.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/HashNotMatchException.java similarity index 78% rename from hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/exception/HashNotMatchException.java rename to hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/HashNotMatchException.java index 21da96e50..c0eab3204 100644 --- a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/exception/HashNotMatchException.java +++ b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/HashNotMatchException.java @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.artifact.exception; +package org.eclipse.hawkbit.artifact.exception; import java.io.Serial; @@ -28,12 +28,6 @@ public class HashNotMatchException extends RuntimeException { private final String hashFunction; - /** - * Constructs a HashNotMatchException with message. - * - * @param message the message of the exception - * @param hashFunction the hash function which caused this exception - */ public HashNotMatchException(final String message, final String hashFunction) { super(message); this.hashFunction = hashFunction; diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/StorageQuotaExceededException.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/StorageQuotaExceededException.java similarity index 57% rename from hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/StorageQuotaExceededException.java rename to hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/StorageQuotaExceededException.java index bdc12826b..d06b907a1 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/StorageQuotaExceededException.java +++ b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/exception/StorageQuotaExceededException.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2019 Bosch Software Innovations GmbH and others + * Copyright (c) 2025 Contributors to the Eclipse Foundation * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -7,9 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.exception; - -import static org.eclipse.hawkbit.repository.SizeConversionHelper.byteValueToReadableString; +package org.eclipse.hawkbit.artifact.exception; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -28,26 +26,12 @@ public class StorageQuotaExceededException extends AbstractServerRtException { private final long exceededQuotaValue; - /** - * Creates a new StorageQuotaExceededException with a quota value. - * - * @param exceededQuotaValue Value by how much the quota was exceeded - */ public StorageQuotaExceededException(final long exceededQuotaValue) { - super(createQuotaErrorMessage(exceededQuotaValue), errorType); + super(errorType, createQuotaErrorMessage(exceededQuotaValue)); this.exceededQuotaValue = exceededQuotaValue; } - /** - * Get a readable string of size quota including unit - * - * @return file size quota with unit - */ - public String getExceededQuotaValueString() { - return byteValueToReadableString(exceededQuotaValue); - } - private static String createQuotaErrorMessage(final long exceededQuotaValue) { - return String.format(MAX_ARTIFACT_SIZE_TOTAL_EXCEEDED, byteValueToReadableString(exceededQuotaValue)); + return String.format(MAX_ARTIFACT_SIZE_TOTAL_EXCEEDED, FileSizeQuotaExceededException.byteValueToReadableString(exceededQuotaValue)); } -} +} \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/model/ArtifactHashes.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/model/ArtifactHashes.java new file mode 100644 index 000000000..d659c1e2b --- /dev/null +++ b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/model/ArtifactHashes.java @@ -0,0 +1,15 @@ +/** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.artifact.model; + +/** + * Representation of artifact hashes. + */ +public record ArtifactHashes(String sha1, String md5, String sha256) {} \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/model/ArtifactStream.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/model/ArtifactStream.java new file mode 100644 index 000000000..d0bc5bd5c --- /dev/null +++ b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/model/ArtifactStream.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.artifact.model; + +import java.io.IOException; +import java.io.InputStream; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; + +@EqualsAndHashCode(callSuper = false) +@ToString +public class ArtifactStream extends InputStream { + + @EqualsAndHashCode.Exclude + @ToString.Exclude + private final InputStream inputStream; + @Getter + private final long size; + @Getter + private final String sha1Hash; + + public ArtifactStream(InputStream inputStream, long size, String sha1Hash) { + this.inputStream = inputStream; + this.size = size; + this.sha1Hash = sha1Hash; + } + + @Override + public int read() throws IOException { + return inputStream.read(); + } + + @Override + public int read(final byte[] b, final int off, final int len) throws IOException { + return inputStream.read(b, off, len); + } + + @Override + public void close() throws IOException { + inputStream.close(); + } +} \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/model/AbstractDbArtifact.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/model/StoredArtifactInfo.java similarity index 55% rename from hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/model/AbstractDbArtifact.java rename to hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/model/StoredArtifactInfo.java index 9229e163b..059246973 100644 --- a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/model/AbstractDbArtifact.java +++ b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/model/StoredArtifactInfo.java @@ -7,28 +7,25 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.artifact.model; +package org.eclipse.hawkbit.artifact.model; import java.util.Objects; import lombok.Data; /** - * Database representation of artifact. + * Info for an imported artifact binary. */ @Data -public abstract class AbstractDbArtifact implements DbArtifact { +public class StoredArtifactInfo { - private final String artifactId; - private final long size; private final String contentType; + private final long size; + private final ArtifactHashes hashes; - private DbArtifactHash hashes; - - protected AbstractDbArtifact(final String artifactId, final DbArtifactHash hashes, final long size, final String contentType) { - this.artifactId = Objects.requireNonNull(artifactId, "Artifact ID cannot be null"); + public StoredArtifactInfo(final String contentType, final long size, final ArtifactHashes hashes) { this.hashes = Objects.requireNonNull(hashes, "Hashes cannot be null"); - this.size = size; this.contentType = contentType; + this.size = size; } } \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/urlresolver/ArtifactUrl.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/urlresolver/ArtifactUrl.java new file mode 100644 index 000000000..2f0f8c63a --- /dev/null +++ b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/urlresolver/ArtifactUrl.java @@ -0,0 +1,15 @@ +/** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.artifact.urlresolver; + +/** + * Container for a generated Artifact URL. + */ +public record ArtifactUrl(String protocol, String rel, String ref) {} \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/urlresolver/ArtifactUrlResolver.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/urlresolver/ArtifactUrlResolver.java new file mode 100644 index 000000000..42ee29d5f --- /dev/null +++ b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/urlresolver/ArtifactUrlResolver.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.artifact.urlresolver; + +import java.net.URI; +import java.util.List; + +/** + * Interface declaration of the {@link ArtifactUrlResolver} which generates the URLs to specific artifacts. + */ +public interface ArtifactUrlResolver { + + /** + * hawkBit API type. + */ + enum ApiType { + + /** + * Support for Device Management Federation API. + */ + DMF, + + /** + * Support for Direct Device Integration API. + */ + DDI, + + /** + * Support for Management API. + */ + MGMT + } + + /** + * Returns a generated download URL for a given artifact parameters for a specific protocol. + * + * @param downloadDescriptor data for URL generation + * @param api given protocol that URL needs to support + * @return a URL for the given artifact parameters in a given protocol + */ + List getUrls(DownloadDescriptor downloadDescriptor, ApiType api); + + /** + * Returns a generated download URL for a given artifact parameters for a specific protocol. + * + * @param downloadDescriptor data for URL generation + * @param api given protocol that URL needs to support + * @param requestUri of the request that allows the handler to align the generated URL to the original request. + * @return a URL for the given artifact parameters in a given protocol + */ + List getUrls(DownloadDescriptor downloadDescriptor, ApiType api, URI requestUri); + + /** + * Container for variables available to the {@link ArtifactUrlResolver}. + */ + record DownloadDescriptor(String tenant, String controllerId, Long softwareModuleId, String filename, String sha1) {} +} \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/urlresolver/PropertyBasedArtifactUrlResolver.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/urlresolver/PropertyBasedArtifactUrlResolver.java new file mode 100644 index 000000000..36d700855 --- /dev/null +++ b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/urlresolver/PropertyBasedArtifactUrlResolver.java @@ -0,0 +1,152 @@ +/** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.artifact.urlresolver; + +import java.net.URI; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; +import java.util.Set; + +import org.eclipse.hawkbit.artifact.urlresolver.PropertyBasedArtifactUrlResolverProperties.UrlProtocol; +import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; + +/** + * Implementation for ArtifactUrlHandler for creating urls to download resource based on patterns configured by + * {@link PropertyBasedArtifactUrlResolverProperties}. + *

+ * This mechanism can be used to generate links to arbitrary file hosting infrastructure. However, the hawkBit update server + * supports hosting files as well in the following {@link UrlProtocol#getRef()} patterns: + *

+ * Default:
+ * {protocol}://{hostname}:{port}{contextPath}/{tenant}/controller/v1/{controllerId} + * /softwaremodules/{softwareModuleId}/artifacts/{artifactFileName} + *

+ * Default (MD5SUM files): + * {protocol}://{hostname}:{port}{contextPath}/{tenant}/controller/v1/{controllerId}/ + * softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}.MD5SUM + */ +public class PropertyBasedArtifactUrlResolver implements ArtifactUrlResolver { + + private static final String PROTOCOL_PLACEHOLDER = "protocol"; + private static final String PROTOCOL_REQUEST_PLACEHOLDER = "protocolRequest"; + private static final String HOSTNAME_PLACEHOLDER = "hostname"; + private static final String HOSTNAME_REQUEST_PLACEHOLDER = "hostnameRequest"; + private static final String HOSTNAME_WITH_DOMAIN_REQUEST_PLACEHOLDER = "domainRequest"; + private static final String IP_PLACEHOLDER = "ip"; + private static final String PORT_PLACEHOLDER = "port"; + private static final String PORT_REQUEST_PLACEHOLDER = "portRequest"; + private static final String TENANT_PLACEHOLDER = "tenant"; + private static final String CONTEXT_PATH = "contextPath"; + private static final String CONTROLLER_ID_PLACEHOLDER = "controllerId"; + private static final String SOFTWARE_MODULE_ID_PLACEHOLDER = "softwareModuleId"; + private static final String ARTIFACT_FILENAME_PLACEHOLDER = "artifactFileName"; + private static final String ARTIFACT_SHA1_PLACEHOLDER = "artifactSHA1"; + // by default, we download via the controller / DDI API download endpoint + static final String DEFAULT_URL_PROTOCOL_REF = "{" + PROTOCOL_REQUEST_PLACEHOLDER + "}://{" + HOSTNAME_REQUEST_PLACEHOLDER + "}:{" + PORT_REQUEST_PLACEHOLDER + "}{" + CONTEXT_PATH + "}/{" + TENANT_PLACEHOLDER + "}/controller/v1/{" + CONTROLLER_ID_PLACEHOLDER + "}/softwaremodules/{" + SOFTWARE_MODULE_ID_PLACEHOLDER + "}/artifacts/{" + ARTIFACT_FILENAME_PLACEHOLDER + "}"; + + private final PropertyBasedArtifactUrlResolverProperties urlHandlerProperties; + private final String contextPath; + + @SuppressWarnings("java:S3358") // better readable this way + public PropertyBasedArtifactUrlResolver(final PropertyBasedArtifactUrlResolverProperties urlHandlerProperties, final String contextPath) { + this.urlHandlerProperties = urlHandlerProperties; + this.contextPath = ObjectUtils.isEmpty(contextPath) || "/".equals(contextPath) + ? "" + : (contextPath.charAt(0) == '/' ? contextPath : '/' + contextPath); // normalize context path + } + + @Override + public List getUrls(final DownloadDescriptor downloadDescriptor, final ApiType api) { + return getUrls(downloadDescriptor, api, null); + } + + @Override + public List getUrls(final DownloadDescriptor downloadDescriptor, final ApiType api, final URI requestUri) { + return urlHandlerProperties.getProtocols().values().stream() + .filter(urlProtocol -> urlProtocol.isEnabled() && urlProtocol.getSupports().contains(api)) + .map(urlProtocol -> new ArtifactUrl( + urlProtocol.getProtocol().toUpperCase(), urlProtocol.getRel(), + generateUrl(urlProtocol, downloadDescriptor, requestUri))) + .toList(); + } + + private String generateUrl(final UrlProtocol protocol, final DownloadDescriptor placeholder, final URI requestUri) { + final Set> entrySet = getReplaceMap(protocol, placeholder, requestUri).entrySet(); + String urlPattern = protocol.getRef(); + for (final Entry entry : entrySet) { + if (List.of(PORT_PLACEHOLDER, PORT_REQUEST_PLACEHOLDER).contains(entry.getKey())) { + urlPattern = urlPattern.replace(":{" + entry.getKey() + "}", + ObjectUtils.isEmpty(entry.getValue()) ? "" : (":" + entry.getValue())); + } else { + if (entry.getValue() != null) { + urlPattern = urlPattern.replace("{" + entry.getKey() + "}", entry.getValue()); + } + } + } + return urlPattern; + } + + private Map getReplaceMap(final UrlProtocol protocol, final DownloadDescriptor placeholder, final URI requestUri) { + final Map replaceMap = new HashMap<>(); + + replaceMap.put(PROTOCOL_PLACEHOLDER, protocol.getProtocol()); + replaceMap.put(PROTOCOL_REQUEST_PLACEHOLDER, Optional.ofNullable(requestUri).map(URI::getScheme).orElseGet(protocol::getProtocol)); + + replaceMap.put(HOSTNAME_PLACEHOLDER, protocol.getHostname()); + replaceMap.put(IP_PLACEHOLDER, protocol.getIp()); + replaceMap.put(HOSTNAME_REQUEST_PLACEHOLDER, Optional.ofNullable(requestUri).map(URI::getHost).orElseGet(protocol::getHostname)); + replaceMap.put(HOSTNAME_WITH_DOMAIN_REQUEST_PLACEHOLDER, computeHostWithRequestDomain(protocol, requestUri)); + + replaceMap.put(PORT_PLACEHOLDER, getPort(protocol)); + replaceMap.put( + PORT_REQUEST_PLACEHOLDER, + Optional.ofNullable(requestUri) + .map(URI::getPort) + .map(port -> port > 0 ? String.valueOf(port) : "") + .orElseGet(() -> getPort(protocol))); + + replaceMap.put(CONTEXT_PATH, contextPath); + + replaceMap.put(TENANT_PLACEHOLDER, placeholder.tenant()); + replaceMap.put(CONTROLLER_ID_PLACEHOLDER, placeholder.controllerId()); + replaceMap.put(SOFTWARE_MODULE_ID_PLACEHOLDER, String.valueOf(placeholder.softwareModuleId())); + replaceMap.put(ARTIFACT_FILENAME_PLACEHOLDER, URLEncoder.encode(placeholder.filename(), StandardCharsets.UTF_8)); + replaceMap.put(ARTIFACT_SHA1_PLACEHOLDER, placeholder.sha1()); + return replaceMap; + } + + private static String getPort(final UrlProtocol protocol) { + return ObjectUtils.isEmpty(protocol.getPort()) ? null : String.valueOf(protocol.getPort()); + } + + private static String computeHostWithRequestDomain(final UrlProtocol protocol, final URI requestUri) { + if (requestUri == null) { + return protocol.getHostname(); + } + if (!protocol.getHostname().contains(".")) { + return protocol.getHostname(); + } + + final List domainElements = Arrays.asList(StringUtils.delimitedListToStringArray(requestUri.getHost(), ".")); + if (domainElements.isEmpty()) { + return protocol.getHostname(); + } + + final String domain = StringUtils.collectionToDelimitedString(domainElements.subList(1, domainElements.size()), "."); + return StringUtils.delimitedListToStringArray(protocol.getHostname(), ".")[0].trim() + "." + domain; + } +} \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/ArtifactUrlHandlerProperties.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/urlresolver/PropertyBasedArtifactUrlResolverProperties.java similarity index 76% rename from hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/ArtifactUrlHandlerProperties.java rename to hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/urlresolver/PropertyBasedArtifactUrlResolverProperties.java index 1be88147c..65d5cde78 100644 --- a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/ArtifactUrlHandlerProperties.java +++ b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/urlresolver/PropertyBasedArtifactUrlResolverProperties.java @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.artifact.urlhandler; +package org.eclipse.hawkbit.artifact.urlresolver; import java.util.Arrays; import java.util.Collections; @@ -19,14 +19,13 @@ import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; /** - * Artifact handler properties class for holding all supported protocols with - * host, ip, port and download pattern. + * Artifact handler properties class for holding all supported protocols with host, ip, port and download pattern. * - * @see PropertyBasedArtifactUrlHandler + * @see PropertyBasedArtifactUrlResolver */ @Data @ConfigurationProperties("hawkbit.artifact.url") -public class ArtifactUrlHandlerProperties { +public class PropertyBasedArtifactUrlResolverProperties { /** * Rel as key and complete protocol as value. @@ -53,9 +52,9 @@ public class ArtifactUrlHandlerProperties { /** * Hypermedia ref pattern for this protocol. Supported placeholders are the properties - * supported by {@link PropertyBasedArtifactUrlHandler}. + * supported by {@link PropertyBasedArtifactUrlResolver}. */ - private String ref = PropertyBasedArtifactUrlHandler.DEFAULT_URL_PROTOCOL_REF; + private String ref = PropertyBasedArtifactUrlResolver.DEFAULT_URL_PROTOCOL_REF; /** * Protocol name placeholder that can be used in ref pattern. @@ -70,8 +69,6 @@ public class ArtifactUrlHandlerProperties { /** * IP address placeholder that can be used in ref pattern. */ - // Exception squid:S1313 - default only, can be configured - @SuppressWarnings("squid:S1313") private String ip = "127.0.0.1"; /** @@ -82,9 +79,9 @@ public class ArtifactUrlHandlerProperties { /** * Support for the following hawkBit API. */ - private List supports = Arrays.asList(ApiType.DDI, ApiType.DMF, ApiType.MGMT); + private List supports = Arrays.asList(ArtifactUrlResolver.ApiType.DDI, ArtifactUrlResolver.ApiType.DMF, ArtifactUrlResolver.ApiType.MGMT); - public void setSupports(final List supports) { + public void setSupports(final List supports) { this.supports = Collections.unmodifiableList(supports); } } diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/model/DbArtifact.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/model/DbArtifact.java deleted file mode 100644 index 166162d14..000000000 --- a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/model/DbArtifact.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.artifact.model; - -import java.io.InputStream; - -/** - * Interface definition for artifact binary. - */ -public interface DbArtifact { - - /** - * @return ID of the artifact - */ - String getArtifactId(); - - /** - * @return hashes of the artifact - */ - DbArtifactHash getHashes(); - - /** - * @return size of the artifact in bytes - */ - long getSize(); - - /** - * @return content-type if known by the repository or null - */ - String getContentType(); - - /** - * Creates an {@link InputStream} on this artifact. Caller has to take care of - * closing the stream. Repeatable calls open a new {@link InputStream}. - * - * @return {@link InputStream} to read from artifact. - */ - InputStream getFileInputStream(); -} \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/model/DbArtifactHash.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/model/DbArtifactHash.java deleted file mode 100644 index 17a5e8f67..000000000 --- a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/model/DbArtifactHash.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.artifact.model; - -import lombok.Data; - -/** - * Database representation of artifact hash. - */ -@Data -public class DbArtifactHash { - - private final String sha1; - private final String md5; - private final String sha256; - - /** - * Constructor. - * - * @param sha1 the sha1 hash - * @param md5 the md5 hash - * @param sha256 the sha256 hash - */ - public DbArtifactHash(final String sha1, final String md5, final String sha256) { - this.sha1 = sha1; - this.md5 = md5; - this.sha256 = sha256; - } -} \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/ApiType.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/ApiType.java deleted file mode 100644 index 6ff9589db..000000000 --- a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/ApiType.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.artifact.urlhandler; - -/** - * hawkBit API type. - */ -public enum ApiType { - - /** - * Support for Device Management Federation API. - */ - DMF, - - /** - * Support for Direct Device Integration API. - */ - DDI, - - /** - * Support for Management API. - */ - MGMT -} \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/ArtifactUrl.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/ArtifactUrl.java deleted file mode 100644 index c7332dac0..000000000 --- a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/ArtifactUrl.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.artifact.urlhandler; - -import lombok.Data; - -/** - * Container for a generated Artifact URL. - */ -@Data -public class ArtifactUrl { - - private final String protocol; - private final String rel; - private final String ref; - - /** - * Constructor. - * - * @param protocol string, e.g. ftp, http, https - * @param rel hypermedia value - * @param ref hypermedia value - */ - public ArtifactUrl(final String protocol, final String rel, final String ref) { - this.protocol = protocol; - this.rel = rel; - this.ref = ref; - } -} \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/ArtifactUrlHandler.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/ArtifactUrlHandler.java deleted file mode 100644 index 940d32acc..000000000 --- a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/ArtifactUrlHandler.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.artifact.urlhandler; - -import java.net.URI; -import java.util.List; - -/** - * Interface declaration of the {@link ArtifactUrlHandler} which generates the URLs to specific artifacts. - */ -public interface ArtifactUrlHandler { - - /** - * Returns a generated download URL for a given artifact parameters for a specific protocol. - * - * @param placeholder data for URL generation - * @param api given protocol that URL needs to support - * @return a URL for the given artifact parameters in a given protocol - */ - List getUrls(URLPlaceholder placeholder, ApiType api); - - /** - * Returns a generated download URL for a given artifact parameters for a - * specific protocol. - * - * @param placeholder data for URL generation - * @param api given protocol that URL needs to support - * @param requestUri of the request that allows the handler to align the generated URL to the original request. - * @return a URL for the given artifact parameters in a given protocol - */ - List getUrls(URLPlaceholder placeholder, ApiType api, URI requestUri); -} \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/Base62Util.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/Base62Util.java deleted file mode 100644 index b86416a1b..000000000 --- a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/Base62Util.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.artifact.urlhandler; - -import lombok.AccessLevel; -import lombok.NoArgsConstructor; - -/** - * Utility class for Base10 to Base62 conversion and vice versa. Base62 has the benefit of being shorter in ASCII representation than Base10. - */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) -final class Base62Util { - - private static final String BASE62_ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - private static final int BASE62_BASE = BASE62_ALPHABET.length(); - - /** - * @param l number - * @return converted number into Base62 ASCII string - */ - static String fromBase10(final long l) { - if (l == 0) { - return "0"; - } - - long temp = l; - final StringBuilder sb = new StringBuilder(); - - while (temp > 0) { - temp = fromBase10(temp, sb); - } - return sb.reverse().toString(); - } - - /** - * @param base62 number - * @return converted number into Base10 - */ - static Long toBase10(final String base62) { - return toBase10(new StringBuilder(base62).reverse().toString().toCharArray()); - } - - static Long fromBase10(final long l, final StringBuilder sb) { - final int rem = (int) (l % BASE62_BASE); - sb.append(BASE62_ALPHABET.charAt(rem)); - return l / BASE62_BASE; - } - - private static Long toBase10(final char[] chars) { - long base10 = 0L; - for (int i = chars.length - 1; i >= 0; i--) { - base10 += toBase10(BASE62_ALPHABET.indexOf(chars[i]), i); - } - return base10; - } - - private static int toBase10(final int n, final int pow) { - return n * (int) Math.pow(BASE62_BASE, pow); - } -} \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/PropertyBasedArtifactUrlHandler.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/PropertyBasedArtifactUrlHandler.java deleted file mode 100644 index eb67562bd..000000000 --- a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/PropertyBasedArtifactUrlHandler.java +++ /dev/null @@ -1,203 +0,0 @@ -/** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.artifact.urlhandler; - -import java.net.URI; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; -import java.util.Set; - -import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrlHandlerProperties.UrlProtocol; -import org.springframework.util.ObjectUtils; -import org.springframework.util.StringUtils; - -/** - * Implementation for ArtifactUrlHandler for creating urls to download resource based on patterns configured by - * {@link ArtifactUrlHandlerProperties}. - * - * This mechanism can be used to generate links to arbitrary file hosting infrastructure. However, the hawkBit update server - * supports hosting files as well in the following {@link UrlProtocol#getRef()} patterns: - * - * Default: - * {protocol}://{hostname}:{port}{contextPath}/{tenant}/controller/v1/{controllerId} - * /softwaremodules/{softwareModuleId}/artifacts/{artifactFileName} - * - * Default (MD5SUM files): - * {protocol}://{hostname}:{port}{contextPath}/{tenant}/controller/v1/{controllerId}/ - * softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}.MD5SUM - */ -public class PropertyBasedArtifactUrlHandler implements ArtifactUrlHandler { - - private static final String PROTOCOL_PLACEHOLDER = "protocol"; - private static final String HOSTNAME_PLACEHOLDER = "hostname"; - private static final String IP_PLACEHOLDER = "ip"; - private static final String PORT_PLACEHOLDER = "port"; - private static final String CONTEXT_PATH = "contextPath"; - private static final String CONTROLLER_ID_PLACEHOLDER = "controllerId"; - private static final String TARGET_ID_BASE10_PLACEHOLDER = "targetId"; - private static final String TARGET_ID_BASE62_PLACEHOLDER = "targetIdBase62"; - private static final String HOSTNAME_REQUEST_PLACEHOLDER = "hostnameRequest"; - private static final String PORT_REQUEST_PLACEHOLDER = "portRequest"; - private static final String PROTOCOL_REQUEST_PLACEHOLDER = "protocolRequest"; - private static final String HOSTNAME_WITH_DOMAIN_REQUEST_PLACEHOLDER = "domainRequest"; - private static final String ARTIFACT_FILENAME_PLACEHOLDER = "artifactFileName"; - private static final String ARTIFACT_SHA1_PLACEHOLDER = "artifactSHA1"; - private static final String ARTIFACT_ID_BASE10_PLACEHOLDER = "artifactId"; - private static final String ARTIFACT_ID_BASE62_PLACEHOLDER = "artifactIdBase62"; - private static final String TENANT_PLACEHOLDER = "tenant"; - private static final String TENANT_ID_BASE10_PLACEHOLDER = "tenantId"; - private static final String TENANT_ID_BASE62_PLACEHOLDER = "tenantIdBase62"; - private static final String SOFTWARE_MODULE_ID_BASE10_PLACEHOLDER = "softwareModuleId"; - private static final String SOFTWARE_MODULE_ID_BASE62_PLACEHOLDER = "softwareModuleIdBase62"; - static final String DEFAULT_URL_PROTOCOL_REF = "{" + PROTOCOL_PLACEHOLDER + "}://{" + HOSTNAME_PLACEHOLDER + "}:{" + PORT_PLACEHOLDER + "}{" + CONTEXT_PATH + "}/{" + TENANT_PLACEHOLDER + "}/controller/v1/{" + CONTROLLER_ID_PLACEHOLDER + "}/softwaremodules/{" + SOFTWARE_MODULE_ID_BASE10_PLACEHOLDER + "}/artifacts/{" + ARTIFACT_FILENAME_PLACEHOLDER + "}"; - - private final ArtifactUrlHandlerProperties urlHandlerProperties; - private final String contextPath; - - /** - * @param urlHandlerProperties for URL generation configuration - */ - public PropertyBasedArtifactUrlHandler(final ArtifactUrlHandlerProperties urlHandlerProperties, final String contextPath) { - this.urlHandlerProperties = urlHandlerProperties; - this.contextPath = contextPath == null || "/".equals(contextPath) ? "" : contextPath; // normalize - } - - @Override - public List getUrls(final URLPlaceholder placeholder, final ApiType api) { - return getUrls(placeholder, api, null); - } - - @Override - public List getUrls(final URLPlaceholder placeholder, final ApiType api, final URI requestUri) { - return urlHandlerProperties.getProtocols().values().stream() - .filter(urlProtocol -> urlProtocol.getSupports().contains(api) && urlProtocol.isEnabled()) - .map(urlProtocol -> new ArtifactUrl(urlProtocol.getProtocol().toUpperCase(), urlProtocol.getRel(), - generateUrl(urlProtocol, placeholder, requestUri))) - .toList(); - - } - - private static String getRequestPort(final UrlProtocol protocol, final URI requestUri) { - if (requestUri == null) { - return getPort(protocol); - } - // if port undefined then default protocol port is used - return requestUri.getPort() > 0 ? String.valueOf(requestUri.getPort()) : ""; - } - - private static String getRequestHost(final UrlProtocol protocol, final URI requestUri) { - if (requestUri == null) { - return protocol.getHostname(); - } - - return Optional.ofNullable(requestUri.getHost()).orElse(protocol.getHostname()); - } - - private static String getRequestProtocol(final UrlProtocol protocol, final URI requestUri) { - if (requestUri == null) { - return protocol.getProtocol(); - } - - return Optional.ofNullable(requestUri.getScheme()).orElse(protocol.getProtocol()); - } - - private static String getPort(final UrlProtocol protocol) { - return ObjectUtils.isEmpty(protocol.getPort()) ? null : String.valueOf(protocol.getPort()); - } - - private static String computeHostWithRequestDomain(final UrlProtocol protocol, final URI requestUri) { - - if (requestUri == null) { - return protocol.getHostname(); - } - - if (!protocol.getHostname().contains(".")) { - return protocol.getHostname(); - } - - final String host = StringUtils.delimitedListToStringArray(protocol.getHostname(), ".")[0].trim(); - - final List domainElements = Arrays - .asList(StringUtils.delimitedListToStringArray(requestUri.getHost(), ".")); - final String domain = StringUtils.collectionToDelimitedString(domainElements.subList(1, domainElements.size()), - "."); - - if (ObjectUtils.isEmpty(domain)) { - return protocol.getHostname(); - } - - return host + "." + domain; - } - - private String generateUrl(final UrlProtocol protocol, final URLPlaceholder placeholder, - final URI requestUri) { - final Set> entrySet = getReplaceMap(protocol, placeholder, requestUri).entrySet(); - - String urlPattern = protocol.getRef(); - - for (final Entry entry : entrySet) { - if (List.of(PORT_PLACEHOLDER, PORT_REQUEST_PLACEHOLDER).contains(entry.getKey())) { - urlPattern = urlPattern.replace(":{" + entry.getKey() + "}", - ObjectUtils.isEmpty(entry.getValue()) ? "" : (":" + entry.getValue())); - } else { - if (entry.getValue() != null) { - urlPattern = urlPattern.replace("{" + entry.getKey() + "}", entry.getValue()); - } - } - } - - return urlPattern; - } - - private Map getReplaceMap(final UrlProtocol protocol, final URLPlaceholder placeholder, - final URI requestUri) { - final Map replaceMap = new HashMap<>(); - replaceMap.put(IP_PLACEHOLDER, protocol.getIp()); - - replaceMap.put(HOSTNAME_PLACEHOLDER, protocol.getHostname()); - - replaceMap.put(HOSTNAME_REQUEST_PLACEHOLDER, getRequestHost(protocol, requestUri)); - replaceMap.put(PORT_REQUEST_PLACEHOLDER, getRequestPort(protocol, requestUri)); - replaceMap.put(HOSTNAME_WITH_DOMAIN_REQUEST_PLACEHOLDER, computeHostWithRequestDomain(protocol, requestUri)); - replaceMap.put(PROTOCOL_REQUEST_PLACEHOLDER, getRequestProtocol(protocol, requestUri)); - - replaceMap.put(CONTEXT_PATH, contextPath); - - replaceMap.put(ARTIFACT_FILENAME_PLACEHOLDER, - URLEncoder.encode(placeholder.getSoftwareData().getFilename(), StandardCharsets.UTF_8)); - - replaceMap.put(ARTIFACT_SHA1_PLACEHOLDER, placeholder.getSoftwareData().getSha1Hash()); - replaceMap.put(PROTOCOL_PLACEHOLDER, protocol.getProtocol()); - replaceMap.put(PORT_PLACEHOLDER, getPort(protocol)); - replaceMap.put(TENANT_PLACEHOLDER, placeholder.getTenant()); - replaceMap.put(TENANT_ID_BASE10_PLACEHOLDER, String.valueOf(placeholder.getTenantId())); - replaceMap.put(TENANT_ID_BASE62_PLACEHOLDER, Base62Util.fromBase10(placeholder.getTenantId())); - replaceMap.put(CONTROLLER_ID_PLACEHOLDER, placeholder.getControllerId()); - replaceMap.put(TARGET_ID_BASE10_PLACEHOLDER, String.valueOf(placeholder.getTargetId())); - if (placeholder.getTargetId() != null) { - replaceMap.put(TARGET_ID_BASE62_PLACEHOLDER, Base62Util.fromBase10(placeholder.getTargetId())); - } - replaceMap.put(ARTIFACT_ID_BASE62_PLACEHOLDER, - Base62Util.fromBase10(placeholder.getSoftwareData().getArtifactId())); - replaceMap.put(ARTIFACT_ID_BASE10_PLACEHOLDER, String.valueOf(placeholder.getSoftwareData().getArtifactId())); - replaceMap.put(SOFTWARE_MODULE_ID_BASE10_PLACEHOLDER, - String.valueOf(placeholder.getSoftwareData().getSoftwareModuleId())); - replaceMap.put(SOFTWARE_MODULE_ID_BASE62_PLACEHOLDER, - Base62Util.fromBase10(placeholder.getSoftwareData().getSoftwareModuleId())); - return replaceMap; - } - -} diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/URLPlaceholder.java b/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/URLPlaceholder.java deleted file mode 100644 index 940540bc1..000000000 --- a/hawkbit-artifact/hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/repository/artifact/urlhandler/URLPlaceholder.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.artifact.urlhandler; - -import lombok.Data; - -/** - * Container for variables available to the {@link ArtifactUrlHandler}. - */ -@Data -public class URLPlaceholder { - - private final String tenant; - private final Long tenantId; - private final String controllerId; - private final Long targetId; - private final SoftwareData softwareData; - - /** - * Constructor. - * - * @param tenant of the client - * @param tenantId of teh tenant - * @param controllerId of the target - * @param targetId of the target - * @param softwareData information about the artifact and software module that can be accessed by the URL. - */ - public URLPlaceholder(final String tenant, final Long tenantId, final String controllerId, final Long targetId, - final SoftwareData softwareData) { - this.tenant = tenant; - this.tenantId = tenantId; - this.controllerId = controllerId; - this.targetId = targetId; - this.softwareData = softwareData; - } - - /** - * Information about the artifact and software module that can be accessed - * by the URL. - */ - @Data - public static class SoftwareData { - - private Long softwareModuleId; - private String filename; - private Long artifactId; - private String sha1Hash; - - /** - * Constructor. - * - * @param softwareModuleId of the module the artifact belongs to - * @param filename of the artifact - * @param artifactId of the artifact - * @param sha1Hash of the artifact - */ - public SoftwareData(final Long softwareModuleId, final String filename, final Long artifactId, final String sha1Hash) { - this.softwareModuleId = softwareModuleId; - this.filename = filename; - this.artifactId = artifactId; - this.sha1Hash = sha1Hash; - } - } -} \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/test/java/org/eclipse/hawkbit/repository/artifact/encryption/ArtifactEncryptionServiceTest.java b/hawkbit-artifact/hawkbit-artifact-api/src/test/java/org/eclipse/hawkbit/artifact/encryption/ArtifactEncryptionServiceTest.java similarity index 90% rename from hawkbit-artifact/hawkbit-artifact-api/src/test/java/org/eclipse/hawkbit/repository/artifact/encryption/ArtifactEncryptionServiceTest.java rename to hawkbit-artifact/hawkbit-artifact-api/src/test/java/org/eclipse/hawkbit/artifact/encryption/ArtifactEncryptionServiceTest.java index 081ee5078..fc9ce4f7a 100644 --- a/hawkbit-artifact/hawkbit-artifact-api/src/test/java/org/eclipse/hawkbit/repository/artifact/encryption/ArtifactEncryptionServiceTest.java +++ b/hawkbit-artifact/hawkbit-artifact-api/src/test/java/org/eclipse/hawkbit/artifact/encryption/ArtifactEncryptionServiceTest.java @@ -7,12 +7,12 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.artifact.encryption; +package org.eclipse.hawkbit.artifact.encryption; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import org.eclipse.hawkbit.repository.artifact.exception.ArtifactEncryptionUnsupportedException; +import org.eclipse.hawkbit.artifact.exception.ArtifactEncryptionUnsupportedException; import org.junit.jupiter.api.Test; /** diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/test/java/org/eclipse/hawkbit/repository/artifact/urlhandler/PropertyBasedArtifactUrlHandlerTest.java b/hawkbit-artifact/hawkbit-artifact-api/src/test/java/org/eclipse/hawkbit/artifact/urlresolver/PropertyBasedArtifactUrlResolverTest.java similarity index 50% rename from hawkbit-artifact/hawkbit-artifact-api/src/test/java/org/eclipse/hawkbit/repository/artifact/urlhandler/PropertyBasedArtifactUrlHandlerTest.java rename to hawkbit-artifact/hawkbit-artifact-api/src/test/java/org/eclipse/hawkbit/artifact/urlresolver/PropertyBasedArtifactUrlResolverTest.java index de924e19d..03473f5a8 100644 --- a/hawkbit-artifact/hawkbit-artifact-api/src/test/java/org/eclipse/hawkbit/repository/artifact/urlhandler/PropertyBasedArtifactUrlHandlerTest.java +++ b/hawkbit-artifact/hawkbit-artifact-api/src/test/java/org/eclipse/hawkbit/artifact/urlresolver/PropertyBasedArtifactUrlResolverTest.java @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.artifact.urlhandler; +package org.eclipse.hawkbit.artifact.urlresolver; import static org.assertj.core.api.Assertions.assertThat; @@ -15,8 +15,8 @@ import java.net.URI; import java.net.URISyntaxException; import java.util.List; -import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrlHandlerProperties.UrlProtocol; -import org.eclipse.hawkbit.repository.artifact.urlhandler.URLPlaceholder.SoftwareData; +import org.eclipse.hawkbit.artifact.urlresolver.ArtifactUrlResolver.DownloadDescriptor; +import org.eclipse.hawkbit.artifact.urlresolver.PropertyBasedArtifactUrlResolverProperties.UrlProtocol; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -29,55 +29,44 @@ import org.mockito.junit.jupiter.MockitoExtension; * Story: Test to generate the artifact download URL */ @ExtendWith(MockitoExtension.class) -class PropertyBasedArtifactUrlHandlerTest { +class PropertyBasedArtifactUrlResolverTest { - private static final String TEST_PROTO = "coap"; + private static final String TEST_PROTO = "https"; private static final String TEST_REL = "download-udp"; - private static final long TENANT_ID = 456789L; - private static final String CONTROLLER_ID = "Test"; - private static final String FILENAME_DECODE = "test123!§$%&"; - private static final String FILENAME_ENCODE = "test123%21%C2%A7%24%25%26"; - private static final long SOFTWARE_MODULE_ID = 87654L; - private static final long TARGET_ID = 3474366L; - private static final String TARGET_ID_BASE62 = "EZqA"; - private static final String SHA1HASH = "test12345"; - private static final long ARTIFACT_ID = 1345678L; - private static final String ARTIFACT_ID_BASE62 = "5e4U"; private static final String TENANT = "TEST_TENANT"; + private static final String CONTROLLER_ID = "Test"; + private static final long SOFTWARE_MODULE_ID = 87654L; + private static final String FILENAME = "test123!§$%&"; + private static final String FILENAME_ENCODED = "test123%21%C2%A7%24%25%26"; + private static final String SHA1 = "0123456789012345678901234567890123456789"; private static final String HTTP_LOCALHOST = "http://localhost:8080/"; - private static final URLPlaceholder placeHolder = new URLPlaceholder( - TENANT, TENANT_ID, CONTROLLER_ID, TARGET_ID, - new SoftwareData(SOFTWARE_MODULE_ID, FILENAME_DECODE, ARTIFACT_ID, SHA1HASH)); - private ArtifactUrlHandler urlHandlerUnderTest; - private ArtifactUrlHandlerProperties properties; + private static final DownloadDescriptor DOWNLOAD_DESCRIPTOR = new DownloadDescriptor(TENANT, CONTROLLER_ID, SOFTWARE_MODULE_ID, FILENAME, + SHA1); + + private ArtifactUrlResolver urlHandlerUnderTest; + private PropertyBasedArtifactUrlResolverProperties properties; @BeforeEach void setup() { - properties = new ArtifactUrlHandlerProperties(); - urlHandlerUnderTest = new PropertyBasedArtifactUrlHandler(properties, ""); + properties = new PropertyBasedArtifactUrlResolverProperties(); + urlHandlerUnderTest = new PropertyBasedArtifactUrlResolver(properties, ""); } - /** - * Tests the generation of http download url. - */ @Test void urlGenerationWithDefaultConfiguration() { properties.getProtocols().put("download-http", new UrlProtocol()); - final List ddiUrls = urlHandlerUnderTest.getUrls(placeHolder, ApiType.DDI); + final List ddiUrls = urlHandlerUnderTest.getUrls(DOWNLOAD_DESCRIPTOR, ArtifactUrlResolver.ApiType.DDI); assertThat(ddiUrls).containsExactly( - new ArtifactUrl( - "http".toUpperCase(), "download-http", - HTTP_LOCALHOST + TENANT + "/controller/v1/" + - CONTROLLER_ID + "/softwaremodules/" + SOFTWARE_MODULE_ID + "/artifacts/" + FILENAME_ENCODE)) - .isEqualTo(urlHandlerUnderTest.getUrls(placeHolder, ApiType.DMF)); + new ArtifactUrl( + "http".toUpperCase(), "download-http", + HTTP_LOCALHOST + TENANT + "/controller/v1/" + + CONTROLLER_ID + "/softwaremodules/" + SOFTWARE_MODULE_ID + "/artifacts/" + FILENAME_ENCODED)) + .isEqualTo(urlHandlerUnderTest.getUrls(DOWNLOAD_DESCRIPTOR, ArtifactUrlResolver.ApiType.DMF)); } - /** - * Tests the generation of custom download url with a CoAP example that supports DMF only. - */ @Test void urlGenerationWithCustomConfiguration() { final UrlProtocol proto = new UrlProtocol(); @@ -85,41 +74,17 @@ class PropertyBasedArtifactUrlHandlerTest { proto.setPort(5683); proto.setProtocol(TEST_PROTO); proto.setRel(TEST_REL); - proto.setSupports(List.of(ApiType.DMF)); - proto.setRef("{protocol}://{ip}:{port}/fw/{tenant}/{controllerId}/sha1/{artifactSHA1}"); + proto.setSupports(List.of(ArtifactUrlResolver.ApiType.DMF)); + proto.setRef("{protocol}://{ip}:{port}/fw/{tenant}/{controllerId}/sha1/{artifactFileName}"); properties.getProtocols().put(TEST_PROTO, proto); - assertThat(urlHandlerUnderTest.getUrls(placeHolder, ApiType.DDI)).isEmpty(); - assertThat(urlHandlerUnderTest.getUrls(placeHolder, ApiType.DMF)).containsExactly( + assertThat(urlHandlerUnderTest.getUrls(DOWNLOAD_DESCRIPTOR, ArtifactUrlResolver.ApiType.DDI)).isEmpty(); + assertThat(urlHandlerUnderTest.getUrls(DOWNLOAD_DESCRIPTOR, ArtifactUrlResolver.ApiType.DMF)).containsExactly( new ArtifactUrl( TEST_PROTO.toUpperCase(), TEST_REL, - "coap://127.0.0.1:5683/fw/" + TENANT + "/" + CONTROLLER_ID + "/sha1/" + SHA1HASH)); + TEST_PROTO + "://127.0.0.1:5683/fw/" + TENANT + "/" + CONTROLLER_ID + "/sha1/" + FILENAME_ENCODED)); } - /** - * Tests the generation of custom download url using Base62 references with a CoAP example that supports DMF only. - */ - @Test - void urlGenerationWithCustomShortConfiguration() { - final UrlProtocol proto = new UrlProtocol(); - proto.setIp("127.0.0.1"); - proto.setPort(5683); - proto.setProtocol(TEST_PROTO); - proto.setRel(TEST_REL); - proto.setSupports(List.of(ApiType.DMF)); - proto.setRef("{protocol}://{ip}:{port}/fws/{tenant}/{targetIdBase62}/{artifactIdBase62}"); - properties.getProtocols().put("ftp", proto); - - assertThat(urlHandlerUnderTest.getUrls(placeHolder, ApiType.DDI)).isEmpty(); - assertThat(urlHandlerUnderTest.getUrls(placeHolder, ApiType.DMF)).containsExactly( - new ArtifactUrl( - TEST_PROTO.toUpperCase(), TEST_REL, - TEST_PROTO + "://127.0.0.1:5683/fws/" + TENANT + "/" + TARGET_ID_BASE62 + "/" + ARTIFACT_ID_BASE62)); - } - - /** - * Verifies that the full qualified host of the statically defined hostname is replaced with the host of the request. - */ @Test void urlGenerationWithHostFromRequest() throws URISyntaxException { final String testHost = "ddi.host.com"; @@ -129,14 +94,15 @@ class PropertyBasedArtifactUrlHandlerTest { proto.setPort(5683); proto.setProtocol(TEST_PROTO); proto.setRel(TEST_REL); - proto.setSupports(List.of(ApiType.DDI)); - proto.setRef("{protocol}://{hostnameRequest}:{port}/fws/{tenant}/{targetIdBase62}/{artifactIdBase62}"); + proto.setSupports(List.of(ArtifactUrlResolver.ApiType.DDI)); + proto.setRef("{protocol}://{hostnameRequest}:{port}/fws/{tenant}/{controllerId}/{artifactFileName}"); properties.getProtocols().put("ftp", proto); - assertThat(urlHandlerUnderTest.getUrls(placeHolder, ApiType.DDI, new URI("https://" + testHost))).containsExactly( + assertThat(urlHandlerUnderTest.getUrls(DOWNLOAD_DESCRIPTOR, ArtifactUrlResolver.ApiType.DDI, + new URI("https://" + testHost))).containsExactly( new ArtifactUrl( TEST_PROTO.toUpperCase(), TEST_REL, - TEST_PROTO + "://" + testHost + ":5683/fws/" + TENANT + "/" + TARGET_ID_BASE62 + "/" + ARTIFACT_ID_BASE62)); + TEST_PROTO + "://" + testHost + ":5683/fws/" + TENANT + "/" + CONTROLLER_ID + "/" + FILENAME_ENCODED)); } /** @@ -147,13 +113,14 @@ class PropertyBasedArtifactUrlHandlerTest { final String testHost = "ddi.host.com"; final UrlProtocol proto = new UrlProtocol(); - proto.setRef("{protocolRequest}://{hostname}:{port}/fws/{tenant}/{targetIdBase62}/{artifactIdBase62}"); + proto.setRef("{protocolRequest}://{hostname}:{port}/fws/{tenant}/{controllerId}/{artifactFileName}"); properties.getProtocols().put("download-http", proto); - assertThat(urlHandlerUnderTest.getUrls(placeHolder, ApiType.DDI, new URI("https://" + testHost))).containsExactly( + assertThat(urlHandlerUnderTest.getUrls(DOWNLOAD_DESCRIPTOR, ArtifactUrlResolver.ApiType.DDI, + new URI("https://" + testHost))).containsExactly( new ArtifactUrl( "http".toUpperCase(), "download-http", - "https://localhost:8080/fws/" + TENANT + "/" + TARGET_ID_BASE62 + "/" + ARTIFACT_ID_BASE62)); + "https://localhost:8080/fws/" + TENANT + "/" + CONTROLLER_ID + "/" + FILENAME_ENCODED)); } /** @@ -162,21 +129,23 @@ class PropertyBasedArtifactUrlHandlerTest { @Test void urlGenerationWithPortFromRequest() throws URISyntaxException { final UrlProtocol proto = new UrlProtocol(); - proto.setRef("{protocol}://{hostname}:{portRequest}/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}"); + proto.setRef( + "{protocol}://{hostname}:{portRequest}/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}"); properties.getProtocols().put("download-http", proto); - assertThat(urlHandlerUnderTest.getUrls(placeHolder, ApiType.DDI, new URI("http://anotherHost.com:8083"))).containsExactly( + assertThat(urlHandlerUnderTest.getUrls(DOWNLOAD_DESCRIPTOR, ArtifactUrlResolver.ApiType.DDI, + new URI("http://anotherHost.com:8083"))).containsExactly( new ArtifactUrl( "http".toUpperCase(), "download-http", "http://localhost:8083/" + TENANT + "/controller/v1/" + - CONTROLLER_ID + "/softwaremodules/" + SOFTWARE_MODULE_ID + "/artifacts/" + FILENAME_ENCODE)); + CONTROLLER_ID + "/softwaremodules/" + SOFTWARE_MODULE_ID + "/artifacts/" + FILENAME_ENCODED)); - assertThat(urlHandlerUnderTest.getUrls(placeHolder, ApiType.DMF)).containsExactly( + assertThat(urlHandlerUnderTest.getUrls(DOWNLOAD_DESCRIPTOR, ArtifactUrlResolver.ApiType.DMF)).containsExactly( new ArtifactUrl( "http".toUpperCase(), "download-http", "http://localhost:8080/" + TENANT + "/controller/v1/" + - CONTROLLER_ID + "/softwaremodules/" + SOFTWARE_MODULE_ID + "/artifacts/" + FILENAME_ENCODE)); + CONTROLLER_ID + "/softwaremodules/" + SOFTWARE_MODULE_ID + "/artifacts/" + FILENAME_ENCODED)); } /** @@ -186,17 +155,16 @@ class PropertyBasedArtifactUrlHandlerTest { void urlGenerationWithPortFromRequestForHttps() throws URISyntaxException { final String protocol = "https"; final UrlProtocol proto = new UrlProtocol(); - proto.setRef("{protocolRequest}://{hostnameRequest}:{portRequest}/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}"); + proto.setRef( + "{protocolRequest}://{hostnameRequest}:{portRequest}/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}"); proto.setProtocol(protocol); properties.getProtocols().put("download-http", proto); final URI uri = new URI(protocol + "://anotherHost.com"); - assertThat(urlHandlerUnderTest.getUrls(placeHolder, ApiType.DDI, uri)).containsExactly( + assertThat(urlHandlerUnderTest.getUrls(DOWNLOAD_DESCRIPTOR, ArtifactUrlResolver.ApiType.DDI, uri)).containsExactly( new ArtifactUrl( protocol.toUpperCase(), "download-http", - uri + "/" + TENANT + "/controller/v1/" + - CONTROLLER_ID + "/softwaremodules/" + SOFTWARE_MODULE_ID + "/artifacts/" + FILENAME_ENCODE)); - + uri + "/" + TENANT + "/controller/v1/" + CONTROLLER_ID + "/softwaremodules/" + SOFTWARE_MODULE_ID + "/artifacts/" + FILENAME_ENCODED)); } /** @@ -206,20 +174,22 @@ class PropertyBasedArtifactUrlHandlerTest { void urlGenerationWithDomainFromRequest() throws URISyntaxException { final UrlProtocol proto = new UrlProtocol(); proto.setHostname("host.bumlux.net"); - proto.setRef("{protocol}://{domainRequest}/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}"); + proto.setRef( + "{protocol}://{domainRequest}/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}"); properties.getProtocols().put("download-http", proto); - assertThat(urlHandlerUnderTest.getUrls(placeHolder, ApiType.DDI, new URI("http://anotherHost.com:8083"))).containsExactly( + assertThat(urlHandlerUnderTest.getUrls(DOWNLOAD_DESCRIPTOR, ArtifactUrlResolver.ApiType.DDI, + new URI("http://anotherHost.com:8083"))).containsExactly( new ArtifactUrl( "http".toUpperCase(), "download-http", "http://host.com/" + TENANT + "/controller/v1/" + - CONTROLLER_ID + "/softwaremodules/" + SOFTWARE_MODULE_ID + "/artifacts/" + FILENAME_ENCODE)); + CONTROLLER_ID + "/softwaremodules/" + SOFTWARE_MODULE_ID + "/artifacts/" + FILENAME_ENCODED)); - assertThat(urlHandlerUnderTest.getUrls(placeHolder, ApiType.DMF)).containsExactly( + assertThat(urlHandlerUnderTest.getUrls(DOWNLOAD_DESCRIPTOR, ArtifactUrlResolver.ApiType.DMF)).containsExactly( new ArtifactUrl( "http".toUpperCase(), "download-http", "http://host.bumlux.net/" + TENANT + "/controller/v1/" + - CONTROLLER_ID + "/softwaremodules/" + SOFTWARE_MODULE_ID + "/artifacts/" + FILENAME_ENCODE)); + CONTROLLER_ID + "/softwaremodules/" + SOFTWARE_MODULE_ID + "/artifacts/" + FILENAME_ENCODED)); } } \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/test/java/org/eclipse/hawkbit/repository/artifact/urlhandler/Base62UtilTest.java b/hawkbit-artifact/hawkbit-artifact-api/src/test/java/org/eclipse/hawkbit/repository/artifact/urlhandler/Base62UtilTest.java deleted file mode 100644 index 3d2028414..000000000 --- a/hawkbit-artifact/hawkbit-artifact-api/src/test/java/org/eclipse/hawkbit/repository/artifact/urlhandler/Base62UtilTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.artifact.urlhandler; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.jupiter.api.Test; - -/** - * Feature: Unit Tests - Artifact URL Handler
- * Story: Base62 Utility tests - */ -class Base62UtilTest { - - /** - * Convert Base10 numbers to Base62 ASCII strings. - */ - @Test - void fromBase10() { - assertThat(Base62Util.fromBase10(0L)).isEqualTo("0"); - assertThat(Base62Util.fromBase10(11L)).isEqualTo("B"); - assertThat(Base62Util.fromBase10(36L)).isEqualTo("a"); - assertThat(Base62Util.fromBase10(999L)).isEqualTo("G7"); - } - - /** - * Convert Base62 ASCII strings to Base10 numbers. - */ - @Test - void toBase10() { - assertThat(Base62Util.toBase10("0")).isZero(); - assertThat(Base62Util.toBase10("B")).isEqualTo(11); - assertThat(Base62Util.toBase10("a")).isEqualTo(36L); - assertThat(Base62Util.toBase10("G7")).isEqualTo(999L); - } -} \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-api/src/test/java/org/eclipse/hawkbit/repository/artifact/urlhandler/URLPlaceholderTest.java b/hawkbit-artifact/hawkbit-artifact-api/src/test/java/org/eclipse/hawkbit/repository/artifact/urlhandler/URLPlaceholderTest.java deleted file mode 100644 index 1c3833631..000000000 --- a/hawkbit-artifact/hawkbit-artifact-api/src/test/java/org/eclipse/hawkbit/repository/artifact/urlhandler/URLPlaceholderTest.java +++ /dev/null @@ -1,93 +0,0 @@ -/** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.artifact.urlhandler; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.jupiter.api.Test; - -/** - * Feature: Unit Tests - Artifact URL Handler
- * Story: URL placeholder tests - */ -class URLPlaceholderTest { - - private final URLPlaceholder.SoftwareData softwareData; - private final URLPlaceholder placeholder; - - public URLPlaceholderTest() { - this.softwareData = new URLPlaceholder.SoftwareData(1L, "file.txt", 123L, "someHash123"); - this.placeholder = new URLPlaceholder("SuperCorp", 123L, "Super-1", 1L, softwareData); - } - - /** - * Same object should be equal - */ - @Test - // Exception squid:S5785 - JUnit assertTrue/assertFalse should be simplified to the corresponding dedicated assertion - // Need to test the equals method and need to bypass magic logic in utility classes - @SuppressWarnings({ "squid:S5838" }) - void sameObjectShouldBeEqual() { - assertThat(softwareData.equals(softwareData)).isTrue(); - assertThat(placeholder.equals(placeholder)).isTrue(); - } - - /** - * Different object should not be equal - */ - @Test - @SuppressWarnings({ "squid:S5838" }) - void differentObjectShouldNotBeEqual() { - final URLPlaceholder.SoftwareData softwareData2 = new URLPlaceholder.SoftwareData(2L, "file.txt", 123L, "someHash123"); - final URLPlaceholder placeholder2 = new URLPlaceholder("SuperCorp", 123L, "Super-2", 2L, softwareData2); - final URLPlaceholder placeholderWithOtherSoftwareData = new URLPlaceholder(placeholder.getTenant(), - placeholder.getTenantId(), placeholder.getControllerId(), placeholder.getTargetId(), softwareData2); - assertThat(placeholder.equals(placeholder2)).isFalse(); - assertThat(placeholder2.equals(placeholder)).isFalse(); - assertThat(softwareData.equals(softwareData2)).isFalse(); - assertThat(softwareData2.equals(softwareData)).isFalse(); - assertThat(placeholder.equals(placeholderWithOtherSoftwareData)).isFalse(); - } - - /** - * Different objects with same properties should be equal - */ - @Test - void differentObjectsWithSamePropertiesShouldBeEqual() { - final URLPlaceholder placeholderWithSameProperties = new URLPlaceholder(placeholder.getTenant(), placeholder.getTenantId(), - placeholder.getControllerId(), placeholder.getTargetId(), softwareData); - assertThat(placeholder).isEqualTo(placeholderWithSameProperties); - assertThat(placeholderWithSameProperties).isEqualTo(placeholder); - } - - /** - * Should not equal null - */ - @Test - // Exception squid:S5785 - JUnit assertTrue/assertFalse should be simplified to - // the corresponding dedicated assertion - // Need to test the equals method and need to bypass magic logic in utility - // classes - @SuppressWarnings({ "squid:S5838" }) - void shouldNotEqualNull() { - assertThat(placeholder.equals(null)).isFalse(); - assertThat(softwareData.equals(null)).isFalse(); - } - - /** - * HashCode should not change - */ - @Test - void hashCodeShouldNotChange() { - final URLPlaceholder placeholderWithSameProperties = new URLPlaceholder(placeholder.getTenant(), placeholder.getTenantId(), - placeholder.getControllerId(), placeholder.getTargetId(), softwareData); - assertThat(placeholder).hasSameHashCodeAs(placeholder).hasSameHashCodeAs(placeholderWithSameProperties); - } -} diff --git a/hawkbit-artifact/hawkbit-artifact-fs/README.md b/hawkbit-artifact/hawkbit-artifact-fs/README.md new file mode 100644 index 000000000..251483373 --- /dev/null +++ b/hawkbit-artifact/hawkbit-artifact-fs/README.md @@ -0,0 +1,8 @@ +Eclipse.IoT hawkBit - Artifact Repository File System +=== +This module contains the implementation of [ArtifactStorage](../hawkbit-artifact-api/src/main/java/org/eclipse/hawkbit/artifact/ArtifactStorage.java) based on the file-system. +It's a very convenient and easy implementation of storing the artifact binaries into the file-system based on the SHA-1 hash naming. + +Due to the limit of many file-systems of files within one directory, the files +are stored in different sub-directories based on the last four digits of the +SHA1-hash `/basepath/[two digit sha1]/[two digit sha1/sha1-hash-filename]`. diff --git a/hawkbit-artifact/hawkbit-artifact-repository-filesystem/pom.xml b/hawkbit-artifact/hawkbit-artifact-fs/pom.xml similarity index 95% rename from hawkbit-artifact/hawkbit-artifact-repository-filesystem/pom.xml rename to hawkbit-artifact/hawkbit-artifact-fs/pom.xml index d340b6e5a..76271258b 100644 --- a/hawkbit-artifact/hawkbit-artifact-repository-filesystem/pom.xml +++ b/hawkbit-artifact/hawkbit-artifact-fs/pom.xml @@ -18,7 +18,7 @@ ${revision} - hawkbit-artifact-repository-filesystem + hawkbit-artifact-fs hawkBit :: Artifact :: Filesystem Artifact Repository diff --git a/hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/repository/artifact/ArtifactFilesystemProperties.java b/hawkbit-artifact/hawkbit-artifact-fs/src/main/java/org/eclipse/hawkbit/artifact/fs/FileArtifactProperties.java similarity index 88% rename from hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/repository/artifact/ArtifactFilesystemProperties.java rename to hawkbit-artifact/hawkbit-artifact-fs/src/main/java/org/eclipse/hawkbit/artifact/fs/FileArtifactProperties.java index 3e3f4005a..a89d8cac8 100644 --- a/hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/repository/artifact/ArtifactFilesystemProperties.java +++ b/hawkbit-artifact/hawkbit-artifact-fs/src/main/java/org/eclipse/hawkbit/artifact/fs/FileArtifactProperties.java @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.artifact; +package org.eclipse.hawkbit.artifact.fs; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -17,7 +17,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; */ @Data @ConfigurationProperties("org.eclipse.hawkbit.repository.file") -public class ArtifactFilesystemProperties { +public class FileArtifactProperties { /** * The base-path of the directory to store the artifacts. diff --git a/hawkbit-artifact/hawkbit-artifact-fs/src/main/java/org/eclipse/hawkbit/artifact/fs/FileArtifactStorage.java b/hawkbit-artifact/hawkbit-artifact-fs/src/main/java/org/eclipse/hawkbit/artifact/fs/FileArtifactStorage.java new file mode 100644 index 000000000..92cd7a39a --- /dev/null +++ b/hawkbit-artifact/hawkbit-artifact-fs/src/main/java/org/eclipse/hawkbit/artifact/fs/FileArtifactStorage.java @@ -0,0 +1,114 @@ +/** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.artifact.fs; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.apache.commons.io.FileUtils; +import org.eclipse.hawkbit.artifact.AbstractArtifactStorage; +import org.eclipse.hawkbit.artifact.ArtifactStorage; +import org.eclipse.hawkbit.artifact.exception.ArtifactBinaryNotFoundException; +import org.eclipse.hawkbit.artifact.exception.ArtifactStoreException; +import org.eclipse.hawkbit.artifact.model.ArtifactHashes; +import org.eclipse.hawkbit.artifact.model.StoredArtifactInfo; +import org.springframework.validation.annotation.Validated; + +/** + * Implementation of the {@link ArtifactStorage} to store artifacts on the file-system. The files are stored by their SHA1 hash of the + * artifact binary. Duplicate files with the same SHA1 hash will only be stored once. + *

+ * All files are stored flat in one base directory configured in the {@link FileArtifactProperties#getPath()}. + *

+ * Due to the limit of many file-systems of files within one directory, the files are stored in different subdirectories based on the last four + * digits of the SHA1-hash {@code (/basepath/[two digit sha1]/[two digit sha1])}. + */ +@Validated +public class FileArtifactStorage extends AbstractArtifactStorage { + + private final FileArtifactProperties artifactResourceProperties; + + public FileArtifactStorage(final FileArtifactProperties artifactResourceProperties) { + this.artifactResourceProperties = artifactResourceProperties; + } + + @Override + public void deleteBySha1(final String tenant, final String sha1) { + FileUtils.deleteQuietly(getFile(tenant, sha1)); + } + + @Override + public InputStream getBySha1(final String tenant, final String sha1) { + final File file = getFile(tenant, sha1); + if (!file.exists()) { + throw new ArtifactBinaryNotFoundException(sha1); + } + try { + return new BufferedInputStream(new FileInputStream(file)); + } catch (final FileNotFoundException e) { + throw new ArtifactBinaryNotFoundException(sha1); + } + } + + @Override + public void deleteByTenant(final String tenant) { + FileUtils.deleteQuietly(Paths.get(artifactResourceProperties.getPath(), sanitizeTenant(tenant)).toFile()); + } + + @Override + public boolean existsBySha1(final String tenant, final String sha1) { + return getFile(tenant, sha1).exists(); + } + + @Override + protected StoredArtifactInfo store(final String tenant, final ArtifactHashes base16Hashes, final String contentType, final String tempFile) + throws IOException { + final File file = new File(tempFile); + final File fileSHA1Naming = getFile(tenant, base16Hashes.sha1()); + if (fileSHA1Naming.exists()) { + FileUtils.deleteQuietly(file); + } else { + Files.move(file.toPath(), fileSHA1Naming.toPath()); + } + + return new StoredArtifactInfo(contentType, fileSHA1Naming.length(), base16Hashes); + } + + private File getFile(final String tenant, final String sha1) { + // ensure that the sha1 is not a path traversal attack + if (sha1.indexOf('/') >= 0 || sha1.indexOf('\\') >= 0) { + throw new IllegalArgumentException("Invalid SHA-1 hash: " + sha1); + } + + final File artifactDirectory = getSha1DirectoryPath(tenant, sha1).toFile(); + if (!artifactDirectory.isDirectory()) { + if (artifactDirectory.isFile()) { + throw new ArtifactStoreException(artifactDirectory + " is a file, but a directory is required."); + } else if (!artifactDirectory.mkdirs()) { + throw new ArtifactStoreException("Fail to create directories: " + artifactDirectory); + } + } + return new File(artifactDirectory, sha1); + } + + private Path getSha1DirectoryPath(final String tenant, final String sha1) { + final int length = sha1.length(); + final String folder1 = sha1.substring(length - 4, length - 2); + final String folder2 = sha1.substring(length - 2, length); + return Paths.get(artifactResourceProperties.getPath(), sanitizeTenant(tenant), folder1, folder2); + } +} \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/autoconfigure/repository/artifact/filesystem/ArtifactFilesystemConfiguration.java b/hawkbit-artifact/hawkbit-artifact-fs/src/main/java/org/eclipse/hawkbit/autoconfigure/artifact/fs/FileArtifactStorageConfiguration.java similarity index 50% rename from hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/autoconfigure/repository/artifact/filesystem/ArtifactFilesystemConfiguration.java rename to hawkbit-artifact/hawkbit-artifact-fs/src/main/java/org/eclipse/hawkbit/autoconfigure/artifact/fs/FileArtifactStorageConfiguration.java index ea9ba64a4..e7c85fb99 100644 --- a/hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/autoconfigure/repository/artifact/filesystem/ArtifactFilesystemConfiguration.java +++ b/hawkbit-artifact/hawkbit-artifact-fs/src/main/java/org/eclipse/hawkbit/autoconfigure/artifact/fs/FileArtifactStorageConfiguration.java @@ -7,30 +7,30 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.autoconfigure.repository.artifact.filesystem; +package org.eclipse.hawkbit.autoconfigure.artifact.fs; -import org.eclipse.hawkbit.repository.artifact.ArtifactFilesystemProperties; -import org.eclipse.hawkbit.repository.artifact.ArtifactFilesystemRepository; -import org.eclipse.hawkbit.repository.artifact.ArtifactRepository; +import org.eclipse.hawkbit.artifact.ArtifactStorage; +import org.eclipse.hawkbit.artifact.fs.FileArtifactProperties; +import org.eclipse.hawkbit.artifact.fs.FileArtifactStorage; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** - * Configuration for the {@link ArtifactFilesystemRepository}. + * Configuration for the {@link FileArtifactStorage}. */ @Configuration -@EnableConfigurationProperties(ArtifactFilesystemProperties.class) -public class ArtifactFilesystemConfiguration { +@EnableConfigurationProperties(FileArtifactProperties.class) +public class FileArtifactStorageConfiguration { /** * @param artifactFilesystemProperties the artifact file system properties - * @return Default {@link ArtifactRepository} implementation. + * @return Default {@link ArtifactStorage} implementation. */ @Bean @ConditionalOnMissingBean - public ArtifactRepository artifactRepository(final ArtifactFilesystemProperties artifactFilesystemProperties) { - return new ArtifactFilesystemRepository(artifactFilesystemProperties); + public ArtifactStorage artifactRepository(final FileArtifactProperties artifactFilesystemProperties) { + return new FileArtifactStorage(artifactFilesystemProperties); } } \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-fs/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/hawkbit-artifact/hawkbit-artifact-fs/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..8062fc010 --- /dev/null +++ b/hawkbit-artifact/hawkbit-artifact-fs/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +org.eclipse.hawkbit.autoconfigure.artifact.fs.FileArtifactStorageConfiguration \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/test/java/org/eclipse/hawkbit/repository/artifact/ArtifactFilesystemRepositoryTest.java b/hawkbit-artifact/hawkbit-artifact-fs/src/test/java/org/eclipse/hawkbit/artifact/fs/FileArtifactStorageTest.java similarity index 74% rename from hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/test/java/org/eclipse/hawkbit/repository/artifact/ArtifactFilesystemRepositoryTest.java rename to hawkbit-artifact/hawkbit-artifact-fs/src/test/java/org/eclipse/hawkbit/artifact/fs/FileArtifactStorageTest.java index 282d4cc79..dc4d5cc1a 100644 --- a/hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/test/java/org/eclipse/hawkbit/repository/artifact/ArtifactFilesystemRepositoryTest.java +++ b/hawkbit-artifact/hawkbit-artifact-fs/src/test/java/org/eclipse/hawkbit/artifact/fs/FileArtifactStorageTest.java @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.artifact; +package org.eclipse.hawkbit.artifact.fs; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -21,8 +21,9 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.assertj.core.api.Assertions; -import org.eclipse.hawkbit.repository.artifact.exception.ArtifactBinaryNotFoundException; -import org.eclipse.hawkbit.repository.artifact.model.AbstractDbArtifact; +import org.eclipse.hawkbit.artifact.AbstractArtifactStorage; +import org.eclipse.hawkbit.artifact.exception.ArtifactBinaryNotFoundException; +import org.eclipse.hawkbit.artifact.model.StoredArtifactInfo; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -32,19 +33,19 @@ import org.junit.jupiter.api.Test; * Story: Test storing artifact binaries in the file-system */ @Slf4j -class ArtifactFilesystemRepositoryTest { +class FileArtifactStorageTest { private static final String TENANT = "test_tenant"; - private static ArtifactFilesystemProperties artifactResourceProperties; - private static ArtifactFilesystemRepository artifactFilesystemRepository; + private static FileArtifactProperties artifactResourceProperties; + private static FileArtifactStorage artifactFilesystemRepository; @BeforeAll static void setup() { - artifactResourceProperties = new ArtifactFilesystemProperties(); - artifactResourceProperties.setPath(AbstractArtifactRepository.createTempFile(true).toString()); + artifactResourceProperties = new FileArtifactProperties(); + artifactResourceProperties.setPath(AbstractArtifactStorage.createTempFile(true).toString()); - artifactFilesystemRepository = new ArtifactFilesystemRepository(artifactResourceProperties); + artifactFilesystemRepository = new FileArtifactStorage(artifactResourceProperties); } @AfterAll @@ -64,10 +65,10 @@ class ArtifactFilesystemRepositoryTest { @Test void storeSuccessfully() throws IOException { final byte[] fileContent = randomBytes(); - final AbstractDbArtifact artifact = storeRandomArtifact(fileContent); + final StoredArtifactInfo artifact = storeRandomArtifact(fileContent); final byte[] readContent = new byte[fileContent.length]; - IOUtils.read(artifact.getFileInputStream(), readContent); + IOUtils.read(artifactFilesystemRepository.getBySha1(TENANT, artifact.getHashes().sha1()), readContent); assertThat(readContent).isEqualTo(fileContent); } @@ -77,9 +78,9 @@ class ArtifactFilesystemRepositoryTest { @Test void getStoredArtifactBasedOnSHA1Hash() throws IOException { final byte[] fileContent = randomBytes(); - final AbstractDbArtifact artifact = storeRandomArtifact(fileContent); + final StoredArtifactInfo artifact = storeRandomArtifact(fileContent); - assertThat(artifactFilesystemRepository.getBySha1(TENANT, artifact.getHashes().getSha1())).isNotNull(); + assertThat(artifactFilesystemRepository.getBySha1(TENANT, artifact.getHashes().sha1())).isNotNull(); } /** @@ -87,10 +88,10 @@ class ArtifactFilesystemRepositoryTest { */ @Test void deleteStoredArtifactBySHA1Hash() throws IOException { - final AbstractDbArtifact artifact = storeRandomArtifact(randomBytes()); - artifactFilesystemRepository.deleteBySha1(TENANT, artifact.getHashes().getSha1()); + final StoredArtifactInfo artifact = storeRandomArtifact(randomBytes()); + artifactFilesystemRepository.deleteBySha1(TENANT, artifact.getHashes().sha1()); - final String sha1Hash = artifact.getHashes().getSha1(); + final String sha1Hash = artifact.getHashes().sha1(); assertThatExceptionOfType(ArtifactBinaryNotFoundException.class) .isThrownBy(() -> artifactFilesystemRepository.getBySha1(TENANT, sha1Hash)); } @@ -100,10 +101,10 @@ class ArtifactFilesystemRepositoryTest { */ @Test void deleteStoredArtifactOfTenant() throws IOException { - final AbstractDbArtifact artifact = storeRandomArtifact(randomBytes()); + final StoredArtifactInfo artifact = storeRandomArtifact(randomBytes()); artifactFilesystemRepository.deleteByTenant(TENANT); - final String sha1Hash = artifact.getHashes().getSha1(); + final String sha1Hash = artifact.getHashes().sha1(); assertThatExceptionOfType(ArtifactBinaryNotFoundException.class) .isThrownBy(() -> artifactFilesystemRepository.getBySha1(TENANT, sha1Hash)); } @@ -119,9 +120,9 @@ class ArtifactFilesystemRepositoryTest { Assertions.fail("did not expect an exception while deleting a file which does not exists"); } - final AbstractDbArtifact artifact = storeRandomArtifact(randomBytes()); + final StoredArtifactInfo artifact = storeRandomArtifact(randomBytes()); try { - artifactFilesystemRepository.deleteBySha1("tenantWhichDoesNotExist", artifact.getHashes().getSha1()); + artifactFilesystemRepository.deleteBySha1("tenantWhichDoesNotExist", artifact.getHashes().sha1()); } catch (final Exception e) { Assertions.fail("did not expect an exception while deleting a file which does not exists"); } @@ -133,7 +134,7 @@ class ArtifactFilesystemRepositoryTest { return randomBytes; } - private AbstractDbArtifact storeRandomArtifact(final byte[] fileContent) throws IOException { + private StoredArtifactInfo storeRandomArtifact(final byte[] fileContent) throws IOException { try (final ByteArrayInputStream inputStream = new ByteArrayInputStream(fileContent)) { return artifactFilesystemRepository.store(TENANT, inputStream, "filename.tmp", "application/txt", null); } diff --git a/hawkbit-artifact/hawkbit-artifact-repository-filesystem/README.md b/hawkbit-artifact/hawkbit-artifact-repository-filesystem/README.md deleted file mode 100644 index 44d133a4e..000000000 --- a/hawkbit-artifact/hawkbit-artifact-repository-filesystem/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# Eclipse.IoT hawkBit - Artifact Repository File System - -This module contains the implementation of the `ArtifactRepository` based on the file-system. -It's a very convenient and easy implementation of storing the artifact binaries into the file-system based on the SHA-1 -hash naming. - -Due the limit of many file-systems of files within one directory, the files -are stored in different sub-directories based on the last four digits of the -SHA1-hash `/basepath/[two digit sha1]/[two digit sha1/sha1-hash-filename]`. - -# Compile - -#### Build hawkbit-artifact-repository-filesystem - -``` -$ cd hawkbit/hawkbit-artifact-repository-filesystem -$ mvn clean install -``` diff --git a/hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/repository/artifact/ArtifactFileNotFoundException.java b/hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/repository/artifact/ArtifactFileNotFoundException.java deleted file mode 100644 index 63acf7733..000000000 --- a/hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/repository/artifact/ArtifactFileNotFoundException.java +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.artifact; - -/** - * Exception thrown in case that the artifact could not be read. - */ -public class ArtifactFileNotFoundException extends RuntimeException { - - /** - * Creates the Exception from its cause - * - * @param cause the original exception - */ - public ArtifactFileNotFoundException(final Exception cause) { - super(cause); - } -} \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/repository/artifact/ArtifactFilesystem.java b/hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/repository/artifact/ArtifactFilesystem.java deleted file mode 100644 index 0133bad22..000000000 --- a/hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/repository/artifact/ArtifactFilesystem.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.artifact; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.util.Objects; - -import jakarta.validation.constraints.NotNull; - -import lombok.EqualsAndHashCode; -import org.eclipse.hawkbit.repository.artifact.model.AbstractDbArtifact; -import org.eclipse.hawkbit.repository.artifact.model.DbArtifactHash; - -/** - * {@link AbstractDbArtifact} implementation which dynamically creates a {@link FileInputStream} on calling {@link #getFileInputStream()}. - */ -@EqualsAndHashCode(callSuper = true) -public class ArtifactFilesystem extends AbstractDbArtifact { - - private final File file; - - public ArtifactFilesystem( - @NotNull final File file, @NotNull final String artifactId, - @NotNull final DbArtifactHash hashes, final Long size, - final String contentType) { - super(artifactId, hashes, size, contentType); - this.file = Objects.requireNonNull(file, "Artifact file may not be null"); - } - - // suppress warning, this InputStream needs to be closed by the caller, this - // cannot be closed in this method - @SuppressWarnings("squid:S2095") - @Override - public InputStream getFileInputStream() { - try { - return new BufferedInputStream(new FileInputStream(file)); - } catch (final FileNotFoundException e) { - throw new ArtifactFileNotFoundException(e); - } - } -} \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/repository/artifact/ArtifactFilesystemRepository.java b/hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/repository/artifact/ArtifactFilesystemRepository.java deleted file mode 100644 index 175817791..000000000 --- a/hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/repository/artifact/ArtifactFilesystemRepository.java +++ /dev/null @@ -1,115 +0,0 @@ -/** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.artifact; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Optional; - -import org.apache.commons.io.FileUtils; -import org.eclipse.hawkbit.repository.artifact.exception.ArtifactBinaryNotFoundException; -import org.eclipse.hawkbit.repository.artifact.model.AbstractDbArtifact; -import org.eclipse.hawkbit.repository.artifact.model.DbArtifactHash; -import org.springframework.validation.annotation.Validated; - -/** - * Implementation of the {@link ArtifactRepository} to store artifacts on the - * file-system. The files are stored by their SHA1 hash of the artifact binary. - * Duplicate files with the same SHA1 hash will only be stored once. - * - * All files are stored flat in one base directory configured in the - * {@link ArtifactFilesystemProperties#getPath()}. - * - * Due to the limit of many file-systems of files within one directory, the files - * are stored in different subdirectories based on the last four digits of the - * SHA1-hash {@code (/basepath/[two digit sha1]/[two digit sha1])}. - */ -@Validated -public class ArtifactFilesystemRepository extends AbstractArtifactRepository { - - private final ArtifactFilesystemProperties artifactResourceProperties; - - /** - * Constructor. - * - * @param artifactResourceProperties the properties which holds the necessary configuration for the file-system repository - */ - public ArtifactFilesystemRepository(final ArtifactFilesystemProperties artifactResourceProperties) { - this.artifactResourceProperties = artifactResourceProperties; - } - - @Override - public void deleteBySha1(final String tenant, final String sha1Hash) { - FileUtils.deleteQuietly(getFile(tenant, sha1Hash)); - } - - @Override - public AbstractDbArtifact getBySha1(final String tenant, final String sha1) { - final File file = getFile(tenant, sha1); - if (!file.exists()) { - throw new ArtifactBinaryNotFoundException(sha1); - } - - return new ArtifactFilesystem(file, sha1, new DbArtifactHash(sha1, null, null), file.length(), null); - } - - @Override - public void deleteByTenant(final String tenant) { - FileUtils.deleteQuietly(Paths.get(artifactResourceProperties.getPath(), sanitizeTenant(tenant)).toFile()); - } - - @Override - public boolean existsBySha1(final String tenant, final String sha1) { - return getFile(tenant, sha1).exists(); - } - - @Override - protected AbstractDbArtifact store(final String tenant, final DbArtifactHash base16Hashes, final String contentType, final String tempFile) - throws IOException { - final File file = new File(tempFile); - return renameFileToSHA1Naming( - tenant, file, - new ArtifactFilesystem(file, base16Hashes.getSha1(), base16Hashes, file.length(), contentType)); - } - - private ArtifactFilesystem renameFileToSHA1Naming(final String tenant, final File file, - final AbstractDbArtifact artifact) throws IOException { - final File fileSHA1Naming = getFile(tenant, artifact.getHashes().getSha1()); - if (fileSHA1Naming.exists()) { - FileUtils.deleteQuietly(file); - } else { - Files.move(file.toPath(), fileSHA1Naming.toPath()); - } - - return new ArtifactFilesystem( - fileSHA1Naming, artifact.getArtifactId(), artifact.getHashes(), artifact.getSize(), artifact.getContentType()); - } - - private File getFile(final String tenant, final String sha1) { - // ensure that the sha1 is not a path traversal attack - if (sha1.indexOf('/') >= 0 || sha1.indexOf('\\') >= 0) { - throw new IllegalArgumentException("Invalid sha1 hash: " + sha1); - } - - final File aritfactDirectory = getSha1DirectoryPath(tenant, sha1).toFile(); - aritfactDirectory.mkdirs(); - return new File(aritfactDirectory, sha1); - } - - private Path getSha1DirectoryPath(final String tenant, final String sha1) { - final int length = sha1.length(); - final String folder1 = sha1.substring(length - 4, length - 2); - final String folder2 = sha1.substring(length - 2, length); - return Paths.get(artifactResourceProperties.getPath(), sanitizeTenant(tenant), folder1, folder2); - } -} \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index fe8092964..000000000 --- a/hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.hawkbit.autoconfigure.repository.artifact.filesystem.ArtifactFilesystemConfiguration \ No newline at end of file diff --git a/hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/test/java/org/eclipse/hawkbit/repository/artifact/ArtifactFilesystemTest.java b/hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/test/java/org/eclipse/hawkbit/repository/artifact/ArtifactFilesystemTest.java deleted file mode 100644 index f5dae9c95..000000000 --- a/hawkbit-artifact/hawkbit-artifact-repository-filesystem/src/test/java/org/eclipse/hawkbit/repository/artifact/ArtifactFilesystemTest.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.artifact; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; - -import org.apache.commons.io.IOUtils; -import org.eclipse.hawkbit.repository.artifact.model.DbArtifactHash; -import org.junit.jupiter.api.Test; - -/** - * Feature: Unit Tests - Artifact File System Repository
- * Story: Test storing artifact binaries in the file-system - */ -class ArtifactFilesystemTest { - - /** - * Verifies that an exception is thrown on opening an InputStream when file does not exists - */ - @Test - void getInputStreamOfNonExistingFileThrowsException() { - final File file = new File("fileWhichTotalDoesNotExists"); - final ArtifactFilesystem underTest = new ArtifactFilesystem( - file, "fileWhichTotalDoesNotExists", - new DbArtifactHash("1", "2", "3"), 0L, null); - assertThatThrownBy(underTest::getFileInputStream) - .isInstanceOf(ArtifactFileNotFoundException.class) - .hasCauseInstanceOf(FileNotFoundException.class); - } - - /** - * Verifies that an InputStream can be opened if file exists - */ - @Test - void getInputStreamOfExistingFile() throws IOException { - final ArtifactFilesystem underTest = new ArtifactFilesystem( - AbstractArtifactRepository.createTempFile(false), ArtifactFilesystemTest.class.getSimpleName(), - new DbArtifactHash("1", "2", "3"), 0L, null); - assertThat(IOUtils.read(underTest.getFileInputStream(), new byte[16])).isZero(); - } -} \ No newline at end of file diff --git a/hawkbit-artifact/pom.xml b/hawkbit-artifact/pom.xml index eeaba7752..eea31afaa 100644 --- a/hawkbit-artifact/pom.xml +++ b/hawkbit-artifact/pom.xml @@ -24,6 +24,6 @@ hawkbit-artifact-api - hawkbit-artifact-repository-filesystem + hawkbit-artifact-fs \ No newline at end of file diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/artifact/ArtifactUrlHandlerAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/artifact/PropertyBasedArtifactUrlResolverAutoConfiguration.java similarity index 52% rename from hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/artifact/ArtifactUrlHandlerAutoConfiguration.java rename to hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/artifact/PropertyBasedArtifactUrlResolverAutoConfiguration.java index 27cccb8cb..bf3da754d 100644 --- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/artifact/ArtifactUrlHandlerAutoConfiguration.java +++ b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/artifact/PropertyBasedArtifactUrlResolverAutoConfiguration.java @@ -9,9 +9,9 @@ */ package org.eclipse.hawkbit.autoconfigure.artifact; -import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrlHandler; -import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrlHandlerProperties; -import org.eclipse.hawkbit.repository.artifact.urlhandler.PropertyBasedArtifactUrlHandler; +import org.eclipse.hawkbit.artifact.urlresolver.ArtifactUrlResolver; +import org.eclipse.hawkbit.artifact.urlresolver.PropertyBasedArtifactUrlResolver; +import org.eclipse.hawkbit.artifact.urlresolver.PropertyBasedArtifactUrlResolverProperties; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -20,22 +20,18 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; /** - * Autoconfiguration for {@link ArtifactUrlHandler} based on a properties. + * Autoconfiguration for {@link ArtifactUrlResolver} based on a properties. */ @Configuration -@EnableConfigurationProperties({ ArtifactUrlHandlerProperties.class }) +@EnableConfigurationProperties({ PropertyBasedArtifactUrlResolverProperties.class }) @PropertySource("classpath:/hawkbit-artifactdl-defaults.properties") -public class ArtifactUrlHandlerAutoConfiguration { +public class PropertyBasedArtifactUrlResolverAutoConfiguration { - /** - * @param urlHandlerProperties for bean configuration - * @return PropertyBasedArtifactUrlHandler bean - */ @Bean - @ConditionalOnMissingBean(ArtifactUrlHandler.class) - PropertyBasedArtifactUrlHandler propertyBasedArtifactUrlHandler( - final ArtifactUrlHandlerProperties urlHandlerProperties, + @ConditionalOnMissingBean(ArtifactUrlResolver.class) + PropertyBasedArtifactUrlResolver propertyBasedArtifactUrlHandler( + final PropertyBasedArtifactUrlResolverProperties urlHandlerProperties, @Value("${server.servlet.context-path:}") final String contextPath) { - return new PropertyBasedArtifactUrlHandler(urlHandlerProperties, contextPath); + return new PropertyBasedArtifactUrlResolver(urlHandlerProperties, contextPath); } } \ No newline at end of file diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/CacheAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/CacheAutoConfiguration.java index 2e0464a20..48f493ee7 100644 --- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/CacheAutoConfiguration.java +++ b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/CacheAutoConfiguration.java @@ -10,8 +10,8 @@ package org.eclipse.hawkbit.autoconfigure.cache; import com.github.benmanes.caffeine.cache.Caffeine; -import org.eclipse.hawkbit.cache.TenancyCacheManager; -import org.eclipse.hawkbit.cache.TenantAwareCacheManager; +import org.eclipse.hawkbit.tenancy.cache.TenantCacheManager; +import org.eclipse.hawkbit.tenancy.cache.TenantAwareCacheManager; import org.eclipse.hawkbit.tenancy.TenantAware; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -27,7 +27,7 @@ import org.springframework.context.annotation.Primary; * A configuration for configuring the spring {@link CacheManager} for specific multi-tenancy caching. The caches between * tenants must not interfere each other. *

- * This is done by providing a special {@link TenancyCacheManager} which generates a cache name included the current tenant. + * This is done by providing a special {@link TenantCacheManager} which generates a cache name included the current tenant. */ @Configuration @EnableCaching @@ -39,9 +39,8 @@ public class CacheAutoConfiguration { @Bean @ConditionalOnMissingBean @Primary - TenancyCacheManager cacheManager( - @Qualifier("directCacheManager") final CacheManager directCacheManager, - final TenantAware tenantAware) { + TenantCacheManager cacheManager( + @Qualifier("directCacheManager") final CacheManager directCacheManager, final TenantAware tenantAware) { return new TenantAwareCacheManager(directCacheManager, tenantAware); } @@ -63,9 +62,7 @@ public class CacheAutoConfiguration { final CaffeineCacheManager cacheManager = new CaffeineCacheManager(); if (cacheProperties.getTtl() > 0) { - final Caffeine cacheBuilder = Caffeine.newBuilder() - .expireAfterWrite(cacheProperties.getTtl(), cacheProperties.getTtlUnit()); - cacheManager.setCaffeine(cacheBuilder); + cacheManager.setCaffeine(Caffeine.newBuilder().expireAfterWrite(cacheProperties.getTtl(), cacheProperties.getTtlUnit())); } return cacheManager; diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/CacheProperties.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/CacheProperties.java index 9c6286e59..6431765ec 100644 --- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/CacheProperties.java +++ b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/CacheProperties.java @@ -19,7 +19,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; * After lifetime the data gets reloaded out of the database. */ @Data -@ConfigurationProperties("hawkbit.cache.global") +@ConfigurationProperties("hawkbit.cache") public class CacheProperties { /** diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/repository/event/EventPublisherAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/repository/event/EventPublisherAutoConfiguration.java index 64fe11c06..b99af7f47 100644 --- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/repository/event/EventPublisherAutoConfiguration.java +++ b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/repository/event/EventPublisherAutoConfiguration.java @@ -15,7 +15,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; /** - * Autoconfiguration for the events.. + * Autoconfiguration for the events. */ @Configuration @Import(EventPublisherConfiguration.class) diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/ExecutorAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/ExecutorAutoConfiguration.java index ea13d603e..e637938ca 100644 --- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/ExecutorAutoConfiguration.java +++ b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/ExecutorAutoConfiguration.java @@ -38,13 +38,13 @@ import org.springframework.security.concurrent.DelegatingSecurityContextSchedule */ @Slf4j @Configuration -@EnableConfigurationProperties(AsyncConfigurerThreadPoolProperties.class) +@EnableConfigurationProperties(ExecutorProperties.class) public class ExecutorAutoConfiguration { - private final AsyncConfigurerThreadPoolProperties asyncConfigurerProperties; + private final ExecutorProperties executorProperties; - public ExecutorAutoConfiguration(final AsyncConfigurerThreadPoolProperties asyncConfigurerProperties) { - this.asyncConfigurerProperties = asyncConfigurerProperties; + public ExecutorAutoConfiguration(final ExecutorProperties executorProperties) { + this.executorProperties = executorProperties; } /** @@ -72,7 +72,7 @@ public class ExecutorAutoConfiguration { @ConditionalOnMissingBean public ScheduledExecutorService scheduledExecutorService() { return new DelegatingSecurityContextScheduledExecutorService(Executors.newScheduledThreadPool( - asyncConfigurerProperties.getSchedulerThreads(), threadFactory("central-scheduled-executor-pool-%d"))); + executorProperties.getSchedulerThreads(), threadFactory("central-scheduled-executor-pool-%d"))); } /** @@ -97,9 +97,9 @@ public class ExecutorAutoConfiguration { * @return central ThreadPoolExecutor for general purpose multithreaded operations. Tries an orderly shutdown when destroyed. */ private ThreadPoolExecutor threadPoolExecutor() { - final BlockingQueue blockingQueue = new ArrayBlockingQueue<>(asyncConfigurerProperties.getQueueSize()); - return new ThreadPoolExecutor(asyncConfigurerProperties.getCoreThreads(), - asyncConfigurerProperties.getMaxThreads(), asyncConfigurerProperties.getIdleTimeout(), + final BlockingQueue blockingQueue = new ArrayBlockingQueue<>(executorProperties.getQueueSize()); + return new ThreadPoolExecutor(executorProperties.getCoreThreads(), + executorProperties.getMaxThreads(), executorProperties.getIdleTimeout(), TimeUnit.MILLISECONDS, blockingQueue, threadFactory("central-executor-pool-%d"), new PoolSizeExceededPolicy()); diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/AsyncConfigurerThreadPoolProperties.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/ExecutorProperties.java similarity index 92% rename from hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/AsyncConfigurerThreadPoolProperties.java rename to hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/ExecutorProperties.java index 24777fe60..4c7228bf3 100644 --- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/AsyncConfigurerThreadPoolProperties.java +++ b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/ExecutorProperties.java @@ -16,8 +16,8 @@ import org.springframework.boot.context.properties.ConfigurationProperties; * Properties for the async configurer. */ @Data -@ConfigurationProperties("hawkbit.threadpool") -public class AsyncConfigurerThreadPoolProperties { +@ConfigurationProperties("hawkbit.executor") +public class ExecutorProperties { /** * Max queue size for central event executor. diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/InMemoryUserManagementAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/StaticUserManagementAutoConfiguration.java similarity index 89% rename from hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/InMemoryUserManagementAutoConfiguration.java rename to hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/StaticUserManagementAutoConfiguration.java index c6269418f..f83c75e50 100644 --- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/InMemoryUserManagementAutoConfiguration.java +++ b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/StaticUserManagementAutoConfiguration.java @@ -25,11 +25,12 @@ import org.springframework.security.config.annotation.authentication.configurati @Configuration @Order(Ordered.HIGHEST_PRECEDENCE) @EnableConfigurationProperties({ TenantAwareUserProperties.class }) -public class InMemoryUserManagementAutoConfiguration extends GlobalAuthenticationConfigurerAdapter { +public class StaticUserManagementAutoConfiguration extends GlobalAuthenticationConfigurerAdapter { private final StaticAuthenticationProvider authenticationProvider; - InMemoryUserManagementAutoConfiguration(final SecurityProperties securityProperties, + StaticUserManagementAutoConfiguration( + final SecurityProperties securityProperties, final TenantAwareUserProperties tenantAwareUserProperties) { authenticationProvider = new StaticAuthenticationProvider(tenantAwareUserProperties, securityProperties); } diff --git a/hawkbit-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/hawkbit-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 1dd95aab0..91a1a0602 100644 --- a/hawkbit-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/hawkbit-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,8 +1,8 @@ -org.eclipse.hawkbit.autoconfigure.artifact.ArtifactUrlHandlerAutoConfiguration +org.eclipse.hawkbit.autoconfigure.artifact.PropertyBasedArtifactUrlResolverAutoConfiguration org.eclipse.hawkbit.autoconfigure.cache.CacheAutoConfiguration org.eclipse.hawkbit.autoconfigure.repository.event.EventPublisherAutoConfiguration org.eclipse.hawkbit.autoconfigure.repository.JpaRepositoryAutoConfiguration org.eclipse.hawkbit.autoconfigure.scheduling.AsyncConfigurerAutoConfiguration org.eclipse.hawkbit.autoconfigure.scheduling.ExecutorAutoConfiguration org.eclipse.hawkbit.autoconfigure.security.SecurityAutoConfiguration -org.eclipse.hawkbit.autoconfigure.security.InMemoryUserManagementAutoConfiguration +org.eclipse.hawkbit.autoconfigure.security.StaticUserManagementAutoConfiguration diff --git a/hawkbit-autoconfigure/src/main/resources/hawkbit-artifactdl-defaults.properties b/hawkbit-autoconfigure/src/main/resources/hawkbit-artifactdl-defaults.properties index 06683b25b..82d515611 100644 --- a/hawkbit-autoconfigure/src/main/resources/hawkbit-artifactdl-defaults.properties +++ b/hawkbit-autoconfigure/src/main/resources/hawkbit-artifactdl-defaults.properties @@ -22,11 +22,4 @@ hawkbit.artifact.url.protocols.md5sum-http.hostname=${hawkbit.artifact.url.proto hawkbit.artifact.url.protocols.md5sum-http.ip=${hawkbit.artifact.url.protocols.download-http.ip} hawkbit.artifact.url.protocols.md5sum-http.port=${hawkbit.artifact.url.protocols.download-http.port} hawkbit.artifact.url.protocols.md5sum-http.supports=DDI -hawkbit.artifact.url.protocols.md5sum-http.ref=${hawkbit.artifact.url.protocols.download-http.ref}.MD5SUM -hawkbit.artifact.url.protocols.download-cdn-http.rel=download -hawkbit.artifact.url.protocols.download-cdn-http.hostname=localhost -hawkbit.artifact.url.protocols.download-cdn-http.ip=127.0.0.1 -hawkbit.artifact.url.protocols.download-cdn-http.protocol=http -hawkbit.artifact.url.protocols.download-cdn-http.port=8080 -hawkbit.artifact.url.protocols.download-cdn-http.supports=MGMT -hawkbit.artifact.url.protocols.download-cdn-http.ref={protocolRequest}://{hostnameRequest}:{portRequest}/rest/v1/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName} \ No newline at end of file +hawkbit.artifact.url.protocols.md5sum-http.ref=${hawkbit.artifact.url.protocols.download-http.ref}.MD5SUM \ No newline at end of file diff --git a/hawkbit-core/README.md b/hawkbit-core/README.md index bf75314d1..0d80cd7b3 100644 --- a/hawkbit-core/README.md +++ b/hawkbit-core/README.md @@ -1,3 +1,3 @@ # hawkBit Core -Various internal interfaces and utility classes. \ No newline at end of file +Various internal / core interfaces and utility classes. \ No newline at end of file diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/AbstractServerRtException.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/AbstractServerRtException.java index ef9718c3f..285b33ba9 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/AbstractServerRtException.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/AbstractServerRtException.java @@ -28,73 +28,28 @@ public abstract class AbstractServerRtException extends RuntimeException { private final SpServerError error; private final transient Map info; - /** - * Parameterized constructor. - * - * @param error detail - */ protected AbstractServerRtException(final SpServerError error) { - super(error.getMessage()); - this.error = error; - this.info = null; + this(error, error.getMessage()); } - /** - * Parameterized constructor. - * - * @param message custom error message - * @param error detail - */ - protected AbstractServerRtException(final String message, final SpServerError error) { - this(message, error, (Map) null); + protected AbstractServerRtException(final SpServerError error, final String message) { + this(error, message, (Map) null); } - /** - * Parameterized constructor. - * - * @param message custom error message - * @param error detail - */ - protected AbstractServerRtException(final String message, final SpServerError error, final Map info) { - super(message); - this.error = error; - this.info = info; + protected AbstractServerRtException(final SpServerError error, final String message, final Map info) { + this(error, message, info, null); } - /** - * Parameterized constructor. - * - * @param message custom error message - * @param error detail - * @param cause of the exception - */ - protected AbstractServerRtException(final String message, final SpServerError error, final Throwable cause) { - super(message, cause); - this.error = error; - this.info = null; + protected AbstractServerRtException(final SpServerError error, final String message, final Throwable cause) { + this(error, message, null, cause); } - /** - * Parameterized constructor. - * - * @param error detail - * @param cause of the exception - */ protected AbstractServerRtException(final SpServerError error, final Throwable cause) { - super(error.getMessage(), cause); - this.error = error; - this.info = null; + this(error, error.getMessage(), null, cause); } - /** - * Parameterized constructor. - * - * @param message custom error message - * @param error detail - * @param cause of the exception - */ protected AbstractServerRtException( - final String message, final SpServerError error, final Throwable cause, final Map info) { + final SpServerError error, final String message, final Map info, final Throwable cause) { super(message, cause); this.error = error; this.info = info; diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/TenantAware.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/TenantAware.java index d3abe8d90..3847313e4 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/TenantAware.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/TenantAware.java @@ -86,7 +86,7 @@ public interface TenantAware { if (context.getAuthentication() != null) { final Object principal = context.getAuthentication().getPrincipal(); if (context.getAuthentication().getDetails() instanceof TenantAwareAuthenticationDetails tenantAwareAuthenticationDetails) { - return tenantAwareAuthenticationDetails.getTenant(); + return tenantAwareAuthenticationDetails.tenant(); } else if (principal instanceof TenantAwareUser tenantAwareUser) { return tenantAwareUser.getTenant(); } diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/TenantAwareAuthenticationDetails.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/TenantAwareAuthenticationDetails.java index 533ab4900..3acc7b42f 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/TenantAwareAuthenticationDetails.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/TenantAwareAuthenticationDetails.java @@ -12,31 +12,14 @@ package org.eclipse.hawkbit.tenancy; import java.io.Serial; import java.io.Serializable; -import lombok.Getter; -import lombok.ToString; import org.springframework.security.authentication.AbstractAuthenticationToken; /** * An authentication details object {@link AbstractAuthenticationToken#getDetails()} which is stored in the * spring security authentication token details to transport the principal and tenant in the security context session. */ -@Getter -@ToString -public class TenantAwareAuthenticationDetails implements Serializable { +public record TenantAwareAuthenticationDetails(String tenant, boolean controller) implements Serializable { @Serial private static final long serialVersionUID = 1L; - - private final String tenant; - private final boolean controller; - - /** - * @param tenant the current tenant - * @param controller boolean flag to indicate if this authenticated token is a controller authentication. {@code true} in case of - * authenticated controller otherwise {@code false} - */ - public TenantAwareAuthenticationDetails(final String tenant, final boolean controller) { - this.tenant = tenant; - this.controller = controller; - } -} +} \ No newline at end of file diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/TenantMetricsConfiguration.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/TenantMetricsConfiguration.java index 6b9730984..b0a1266f4 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/TenantMetricsConfiguration.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/TenantMetricsConfiguration.java @@ -19,6 +19,7 @@ import io.micrometer.core.instrument.Tag; import io.micrometer.observation.ObservationRegistry; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import lombok.NonNull; import org.eclipse.hawkbit.tenancy.TenantAware.TenantResolver; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties; @@ -59,8 +60,9 @@ public class TenantMetricsConfiguration { public DefaultServerRequestObservationConvention serverRequestObservationConvention(final TenantResolver tenantResolver) { return new DefaultServerRequestObservationConvention() { + @NonNull @Override - public KeyValues getLowCardinalityKeyValues(final ServerRequestObservationContext context) { + public KeyValues getLowCardinalityKeyValues(@NonNull final ServerRequestObservationContext context) { // Make sure that KeyValues entries are already sorted by name for better performance return KeyValues.of(exception(context), method(context), outcome(context), status(context), tenant(), uri(context)); } diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/TenantAwareCacheManager.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/cache/TenantAwareCacheManager.java similarity index 87% rename from hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/TenantAwareCacheManager.java rename to hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/cache/TenantAwareCacheManager.java index 79e06e8ce..cbd75a733 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/TenantAwareCacheManager.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/cache/TenantAwareCacheManager.java @@ -7,14 +7,17 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.cache; +package org.eclipse.hawkbit.tenancy.cache; import java.util.Collection; import java.util.Collections; +import java.util.Optional; +import lombok.NonNull; import org.eclipse.hawkbit.tenancy.TenantAware; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; +import org.springframework.lang.Nullable; /** * A {@link CacheManager} delegator which wraps the {@link CacheManager#getCache(String)} and {@link CacheManager#getCacheNames()} @@ -22,7 +25,7 @@ import org.springframework.cache.CacheManager; *

* Additionally, it also provides functionality to retrieve all caches overall tenants at once, for monitoring and system access. */ -public class TenantAwareCacheManager implements TenancyCacheManager { +public class TenantAwareCacheManager implements TenantCacheManager { private static final String TENANT_CACHE_DELIMITER = "|"; @@ -40,8 +43,9 @@ public class TenantAwareCacheManager implements TenancyCacheManager { this.tenantAware = tenantAware; } + @Nullable @Override - public Cache getCache(final String name) { + public Cache getCache(@NonNull final String name) { final String currentTenant = tenantAware.getCurrentTenant(); if (isTenantInvalid(currentTenant)) { return null; @@ -50,6 +54,7 @@ public class TenantAwareCacheManager implements TenancyCacheManager { return delegate.getCache(buildKey(currentTenant.toUpperCase(), name)); } + @NonNull @Override public Collection getCacheNames() { final String currentTenant = tenantAware.getCurrentTenant(); @@ -67,7 +72,8 @@ public class TenantAwareCacheManager implements TenancyCacheManager { @Override public void evictCaches(final String tenant) { - getCacheNames(tenant).forEach(cacheName -> delegate.getCache(buildKey(tenant, cacheName)).clear()); + getCacheNames(tenant).forEach( + cacheName -> Optional.ofNullable(delegate.getCache(buildKey(tenant, cacheName))).ifPresent(Cache::clear)); } /** diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/TenancyCacheManager.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/cache/TenantCacheManager.java similarity index 90% rename from hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/TenancyCacheManager.java rename to hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/cache/TenantCacheManager.java index 5805d144a..8ef0db2de 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/TenancyCacheManager.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/cache/TenantCacheManager.java @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.cache; +package org.eclipse.hawkbit.tenancy.cache; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; @@ -15,7 +15,7 @@ import org.springframework.cache.CacheManager; /** * A cache interface which handles multi tenancy. */ -public interface TenancyCacheManager extends CacheManager { +public interface TenantCacheManager extends CacheManager { /** * A direct-access for retrieving the cache without including the current tenant key. This is necessary e.g. for retrieving caches not for diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/utils/ObjectCopyUtil.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/utils/ObjectCopyUtil.java index d265045b1..df78935d9 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/utils/ObjectCopyUtil.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/utils/ObjectCopyUtil.java @@ -71,7 +71,7 @@ public class ObjectCopyUtil { final ToSetter toSetter = toSetter(toClass, setterName, fieldName, fromMethod.getReturnType()); if (toSetter == null && toGetter == null) { // we allow toSetter to be null, but in that case the toGetter must not be null and the - // from value shall always match the to value (without setting it) + // 'from' value shall always match the to value (without setting it) throw new IllegalStateException("Setter counterpart for " + fromMethod + " is not found in " + toClass.getName()); } propertySetters.add(new PropertyCopyFunction(fromMethod, toSetter, toGetter)); @@ -284,50 +284,41 @@ public class ObjectCopyUtil { private record ToSetter(BiConsumer toSetter, int order) {} @SuppressWarnings("java:S1210") // java:S1210 - return 0 only when default equals return equals, assume equal hashCodes for equal objects - private static class PropertyCopyFunction implements CopyFunction, Comparable { - - private final Method fromMethod; - private final ToSetter toSetter; - private final UnaryOperator toGetter; - - private PropertyCopyFunction(final Method fromMethod, final ToSetter toSetter, final UnaryOperator toGetter) { - this.fromMethod = fromMethod; - this.toGetter = toGetter; - this.toSetter = toSetter; - } + private record PropertyCopyFunction(Method fromMethod, ToSetter toSetter, UnaryOperator toGetter) + implements CopyFunction, Comparable { public boolean apply(final Object from, final Object to, final boolean setNullValues, final UnaryOperator propertyProcessor) { - final Object value; - try { - value = fromMethod.invoke(from); - } catch (final IllegalAccessException e) { - throw new IllegalStateException("Failed to get source value", e); - } catch (final InvocationTargetException e) { - throw new IllegalStateException("Failed to get source value", e.getTargetException() == null ? e : e.getTargetException()); - } - if (value == null && !setNullValues) { // if !setNullValues null means no change - return false; - } - if (toGetter != null) { - final Object currentValue = toGetter.apply(to); - if (Objects.equals(value, currentValue)) { - return false; // no change + final Object value; + try { + value = fromMethod.invoke(from); + } catch (final IllegalAccessException e) { + throw new IllegalStateException("Failed to get source value", e); + } catch (final InvocationTargetException e) { + throw new IllegalStateException("Failed to get source value", e.getTargetException() == null ? e : e.getTargetException()); } + if (value == null && !setNullValues) { // if !setNullValues null means no change + return false; + } + if (toGetter != null) { + final Object currentValue = toGetter.apply(to); + if (Objects.equals(value, currentValue)) { + return false; // no change + } + } + if (toSetter == null) { + throw new IllegalStateException( + "Setter counterpart for " + fromMethod + " is not found in " + to.getClass().getName() + + " and the 'from' value is not equal to the 'to' value"); + } + toSetter.toSetter().accept(to, propertyProcessor.apply(value)); + return true; } - if (toSetter == null) { - throw new IllegalStateException( - "Setter counterpart for " + fromMethod + " is not found in " + to.getClass().getName() + - " and the 'from' value is not equal to the 'to' value"); - } - toSetter.toSetter().accept(to, propertyProcessor.apply(value)); - return true; - } - public int compareTo(final PropertyCopyFunction other) { - final int orderCompare = Integer.compare(this.toSetter.order(), other.toSetter.order()); - return orderCompare == 0 ? Integer.compare(this.hashCode(), other.hashCode()) : orderCompare; + public int compareTo(final PropertyCopyFunction other) { + final int orderCompare = Integer.compare(this.toSetter.order(), other.toSetter.order()); + return orderCompare == 0 ? Integer.compare(this.hashCode(), other.hashCode()) : orderCompare; + } } - } // functional interface to apply the copy operation private interface CopyFunction { diff --git a/hawkbit-core/src/test/java/org/eclipse/hawkbit/repository/FileNameFieldsTest.java b/hawkbit-core/src/test/java/org/eclipse/hawkbit/repository/RsqlQueryFieldsTest.java similarity index 89% rename from hawkbit-core/src/test/java/org/eclipse/hawkbit/repository/FileNameFieldsTest.java rename to hawkbit-core/src/test/java/org/eclipse/hawkbit/repository/RsqlQueryFieldsTest.java index 7624c32b9..60e8fda8c 100644 --- a/hawkbit-core/src/test/java/org/eclipse/hawkbit/repository/FileNameFieldsTest.java +++ b/hawkbit-core/src/test/java/org/eclipse/hawkbit/repository/RsqlQueryFieldsTest.java @@ -18,7 +18,7 @@ import io.github.classgraph.ClassInfo; import io.github.classgraph.ScanResult; import org.junit.jupiter.api.Test; -class FileNameFieldsTest { +class RsqlQueryFieldsTest { /** * Verifies that fields classes are correctly implemented @@ -35,9 +35,7 @@ class FileNameFieldsTest { .map(clazz -> (Class) clazz) .toList(); assertThat(matchingClasses).isNotEmpty(); - matchingClasses.forEach(providerClass -> { - assertThat(providerClass.getEnumConstants()).isNotEmpty(); - }); + matchingClasses.forEach(providerClass -> assertThat(providerClass.getEnumConstants()).isNotEmpty()); } } } \ No newline at end of file diff --git a/hawkbit-ddi/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiActionHistory.java b/hawkbit-ddi/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiActionHistory.java index 3c90c798d..60c222e5d 100644 --- a/hawkbit-ddi/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiActionHistory.java +++ b/hawkbit-ddi/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiActionHistory.java @@ -47,9 +47,7 @@ public class DdiActionHistory { * @param messages is a list of messages retrieved from action history. */ @JsonCreator - public DdiActionHistory( - @JsonProperty("status") final String status, - @JsonProperty("messages") final List messages) { + public DdiActionHistory(@JsonProperty("status") final String status, @JsonProperty("messages") final List messages) { this.status = status; this.messages = messages; } diff --git a/hawkbit-ddi/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiActivateAutoConfirmation.java b/hawkbit-ddi/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiActivateAutoConfirmation.java index 60a8b358f..f05bd842f 100644 --- a/hawkbit-ddi/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiActivateAutoConfirmation.java +++ b/hawkbit-ddi/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiActivateAutoConfirmation.java @@ -14,6 +14,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.springframework.lang.Nullable; @Data @JsonIgnoreProperties(ignoreUnknown = true) @@ -27,16 +28,10 @@ public class DdiActivateAutoConfirmation { "confirming future actions", example = "exampleRemark") private final String remark; - /** - * Constructor. - * - * @param initiator can be null - * @param remark can be null - */ @JsonCreator public DdiActivateAutoConfirmation( - @JsonProperty(value = "initiator") final String initiator, - @JsonProperty(value = "remark") final String remark) { + @Nullable @JsonProperty(value = "initiator") final String initiator, + @Nullable @JsonProperty(value = "remark") final String remark) { this.initiator = initiator; this.remark = remark; } diff --git a/hawkbit-ddi/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiArtifact.java b/hawkbit-ddi/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiArtifact.java index 00db7bc05..472ea1753 100644 --- a/hawkbit-ddi/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiArtifact.java +++ b/hawkbit-ddi/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiArtifact.java @@ -32,7 +32,7 @@ import org.springframework.hateoas.RepresentationModel; * **download** - HTTPs Download resource for artifacts. The resource supports partial download as specified by RFC7233 (range requests). Keep in mind that the target needs to have the artifact assigned in order to be granted permission to download. * **md5sum** - HTTPs Download resource for MD5SUM file is an optional auto generated artifact that is especially useful for Linux based devices on order to check artifact consistency after download by using the md5sum command line tool. The MD5 and SHA1 are in addition available as metadata in the deployment command itself. * **download-http** - HTTP Download resource for artifacts. The resource supports partial download as specified by RFC7233 (range requests). Keep in mind that the target needs to have the artifact assigned in order to be granted permission to download. (note: anonymous download needs to be enabled on the service account for non-TLS access) - * **md5sum-http** - HTTP Download resource for MD5SUM file is an optional auto generated artifact that is especially useful for Linux based devices on order to check artifact consistency after download by using the md5sum command line tool. The MD5 and SHA1 are in addition available as metadata in the deployment command itself. (note: anonymous download needs to be enabled on the service account for non-TLS access) + * **md5sum-http** - HTTP Download resource for MD5SUM file is an optional auto generated artifact that is especially useful for Linux based devices on order to check artifact consistency after download by using the md5sum command line tool. The MD5 and SHA1 are in addition available as metadata in the deployment command itself. (note: anonymous download needs to be enabled on the service account for non-TLS access) """, example = """ { "filename" : "binaryFile", @@ -47,10 +47,10 @@ import org.springframework.hateoas.RepresentationModel; "href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/40/filename/binaryFile" }, "download-http" : { - "href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/40/filename/binaryFile" + "href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/40/filename/binaryFile" }, "md5sum-http" : { - "href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/40/filename/binaryFile.MD5SUM" + "href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/40/filename/binaryFile.MD5SUM" }, "md5sum" : { "href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/40/filename/binaryFile.MD5SUM" diff --git a/hawkbit-ddi/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiConfig.java b/hawkbit-ddi/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiConfig.java index a4ec4bc50..89c98dce8 100644 --- a/hawkbit-ddi/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiConfig.java +++ b/hawkbit-ddi/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiConfig.java @@ -28,11 +28,6 @@ public class DdiConfig { private final DdiPolling polling; - /** - * Constructor. - * - * @param polling configuration of the polling for the target - */ @JsonCreator public DdiConfig(@JsonProperty("polling") final DdiPolling polling) { this.polling = polling; diff --git a/hawkbit-ddi/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiConfirmationBase.java b/hawkbit-ddi/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiConfirmationBase.java index 1d6d929a5..1d3d613c9 100644 --- a/hawkbit-ddi/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiConfirmationBase.java +++ b/hawkbit-ddi/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiConfirmationBase.java @@ -57,8 +57,7 @@ public class DdiConfirmationBase extends RepresentationModel createChunks( final Target target, final Action uAction, - final ArtifactUrlHandler artifactUrlHandler, final SystemManagement systemManagement, + final ArtifactUrlResolver artifactUrlHandler, final SystemManagement systemManagement, final HttpRequest request, final ControllerManagement controllerManagement) { final Map> metadata = controllerManagement .findTargetVisibleMetaDataBySoftwareModuleId(uAction.getDistributionSet().getModules().stream() @@ -146,7 +145,7 @@ public final class DataConversionHelper { } static List createArtifacts(final Target target, final SoftwareModule module, - final ArtifactUrlHandler artifactUrlHandler, final SystemManagement systemManagement, + final ArtifactUrlResolver artifactUrlHandler, final SystemManagement systemManagement, final HttpRequest request) { return new ResponseList<>(module.getArtifacts().stream() @@ -171,7 +170,7 @@ public final class DataConversionHelper { } private static DdiArtifact createArtifact( - final Target target, final ArtifactUrlHandler artifactUrlHandler, + final Target target, final ArtifactUrlResolver artifactUrlHandler, final Artifact artifact, final SystemManagement systemManagement, final HttpRequest request) { final DdiArtifact file = new DdiArtifact( artifact.getFilename(), @@ -180,13 +179,11 @@ public final class DataConversionHelper { final TenantMetaData tenantMetadata = systemManagement.getTenantMetadataWithoutDetails(); artifactUrlHandler - .getUrls(new URLPlaceholder( - tenantMetadata.getTenant(), tenantMetadata.getId(), target.getControllerId(), target.getId(), - new SoftwareData( - artifact.getSoftwareModule().getId(), artifact.getFilename(), artifact.getId(), - artifact.getSha1Hash())), - ApiType.DDI, request.getURI()) - .forEach(entry -> file.add(Link.of(entry.getRef()).withRel(entry.getRel()).expand())); + .getUrls(new DownloadDescriptor( + tenantMetadata.getTenant(), target.getControllerId(), + artifact.getSoftwareModule().getId(), artifact.getFilename(), artifact.getSha1Hash()), + ArtifactUrlResolver.ApiType.DDI, request.getURI()) + .forEach(entry -> file.add(Link.of(entry.ref()).withRel(entry.rel()).expand())); return file; } diff --git a/hawkbit-ddi/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiApiConfiguration.java b/hawkbit-ddi/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiApiConfiguration.java index 42ec245d0..055b64de0 100644 --- a/hawkbit-ddi/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiApiConfiguration.java +++ b/hawkbit-ddi/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiApiConfiguration.java @@ -17,11 +17,10 @@ import org.springframework.context.annotation.Import; import org.springframework.stereotype.Controller; /** - * Enable {@link ComponentScan} in the resource package to setup all - * {@link Controller} annotated classes and setup the REST-Resources for the + * Enable {@link ComponentScan} in the resource package to set up all {@link Controller} annotated classes and set up the REST-Resources for the * Direct Device Integration API. */ @Configuration @ComponentScan @Import({ RestConfiguration.class, OpenApi.class, DdiOpenApiConfiguration.class }) -public class DdiApiConfiguration {} +public class DdiApiConfiguration {} \ No newline at end of file diff --git a/hawkbit-ddi/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java b/hawkbit-ddi/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java index 45690f43d..819603b6e 100644 --- a/hawkbit-ddi/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java +++ b/hawkbit-ddi/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java @@ -21,6 +21,8 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; +import org.eclipse.hawkbit.artifact.model.ArtifactStream; +import org.eclipse.hawkbit.artifact.urlresolver.ArtifactUrlResolver; import org.eclipse.hawkbit.audit.AuditLog; import org.eclipse.hawkbit.ddi.json.model.DdiActionFeedback; import org.eclipse.hawkbit.ddi.json.model.DdiActionHistory; @@ -50,13 +52,10 @@ import org.eclipse.hawkbit.repository.ControllerManagement; import org.eclipse.hawkbit.repository.RepositoryConstants; import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.UpdateMode; -import org.eclipse.hawkbit.repository.artifact.model.DbArtifact; -import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrlHandler; import org.eclipse.hawkbit.repository.event.remote.DownloadProgressEvent; import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.InvalidConfirmationFeedbackException; -import org.eclipse.hawkbit.repository.exception.SoftwareModuleNotAssignedToTargetException; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate; import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate.ActionStatusCreateBuilder; @@ -99,7 +98,7 @@ public class DdiRootController implements DdiRootControllerRestApi { private final ControllerManagement controllerManagement; private final ConfirmationManagement confirmationManagement; private final ArtifactManagement artifactManagement; - private final ArtifactUrlHandler artifactUrlHandler; + private final ArtifactUrlResolver artifactUrlHandler; private final SystemManagement systemManagement; private final ApplicationEventPublisher eventPublisher; private final HawkbitSecurityProperties securityProperties; @@ -108,7 +107,7 @@ public class DdiRootController implements DdiRootControllerRestApi { @SuppressWarnings("java:S107") public DdiRootController( final ControllerManagement controllerManagement, final ConfirmationManagement confirmationManagement, - final ArtifactManagement artifactManagement, final ArtifactUrlHandler artifactUrlHandler, + final ArtifactManagement artifactManagement, final ArtifactUrlResolver artifactUrlHandler, final SystemManagement systemManagement, final ApplicationEventPublisher eventPublisher, final HawkbitSecurityProperties securityProperties, final TenantAware tenantAware) { @@ -131,11 +130,10 @@ public class DdiRootController implements DdiRootControllerRestApi { final Target target = findTarget(controllerId); - final SoftwareModule softwareModule = controllerManagement.getSoftwareModule(softwareModuleId) - .orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, softwareModuleId)); - + final SoftwareModule softwareModule = controllerManagement.getSoftwareModule(softwareModuleId); return new ResponseEntity<>( - DataConversionHelper.createArtifacts(target, softwareModule, artifactUrlHandler, systemManagement, + DataConversionHelper.createArtifacts( + target, softwareModule, artifactUrlHandler, systemManagement, new ServletServerHttpRequest(RequestResponseContextHolder.getHttpServletRequest())), HttpStatus.OK); } @@ -147,7 +145,7 @@ public class DdiRootController implements DdiRootControllerRestApi { final Target target = controllerManagement.findOrRegisterTargetIfItDoesNotExist( controllerId, IpUtil.getClientIpFromRequest(RequestResponseContextHolder.getHttpServletRequest(), securityProperties)); final Action activeAction = controllerManagement.findActiveActionWithHighestWeight(controllerId).orElse(null); - final Action installedAction = controllerManagement.getInstalledActionByTarget(target).orElse(null); + final Action installedAction = controllerManagement.findInstalledActionByTarget(target).orElse(null); checkAndCancelExpiredAction(activeAction); @@ -170,16 +168,14 @@ public class DdiRootController implements DdiRootControllerRestApi { final ResponseEntity result; final Target target = findTarget(controllerId); - final SoftwareModule module = controllerManagement.getSoftwareModule(softwareModuleId) - .orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, softwareModuleId)); - + final SoftwareModule module = controllerManagement.getSoftwareModule(softwareModuleId); if (checkModule(fileName, module)) { log.warn("Software module with id {} could not be found (1).", softwareModuleId); result = ResponseEntity.notFound().build(); } else { // Artifact presence is ensured in 'checkModule' final Artifact artifact = module.getArtifactByFilename(fileName).orElseThrow(NoSuchElementException::new); - final DbArtifact file = artifactManagement.loadArtifactBinary(artifact.getSha1Hash(), module.getId(), module.isEncrypted()); + final ArtifactStream file = artifactManagement.getArtifactStream(artifact.getSha1Hash(), module.getId(), module.isEncrypted()); final String ifMatch = RequestResponseContextHolder.getHttpServletRequest().getHeader(HttpHeaders.IF_MATCH); if (ifMatch != null && !HttpUtil.matchesHttpHeader(ifMatch, artifact.getSha1Hash())) { @@ -212,9 +208,7 @@ public class DdiRootController implements DdiRootControllerRestApi { final String fileName) { final Target target = findTarget(controllerId); - final SoftwareModule module = controllerManagement.getSoftwareModule(softwareModuleId) - .orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, softwareModuleId)); - + final SoftwareModule module = controllerManagement.getSoftwareModule(softwareModuleId); if (checkModule(fileName, module)) { log.warn("Software module with id {} could not be found (2).", softwareModuleId); return ResponseEntity.notFound().build(); @@ -596,9 +590,7 @@ public class DdiRootController implements DdiRootControllerRestApi { } private ActionStatus logDownload(final HttpServletRequest request, final Target target, final Long module) { - final Action action = controllerManagement - .getActionForDownloadByTargetAndSoftwareModule(target.getControllerId(), module) - .orElseThrow(() -> new SoftwareModuleNotAssignedToTargetException(module, target.getControllerId())); + final Action action = controllerManagement.getActionForDownloadByTargetAndSoftwareModule(target.getControllerId(), module); return controllerManagement.addInformationalActionStatus( ActionStatusCreate.builder() .actionId(action.getId()) @@ -750,16 +742,16 @@ public class DdiRootController implements DdiRootControllerRestApi { } private Optional generateDdiActionHistory(final Action action, final Integer actionHistoryMessageCount) { - final List actionHistoryMsgs = controllerManagement.getActionHistoryMessages( + final List actionHistoryMessages = controllerManagement.getActionHistoryMessages( action.getId(), actionHistoryMessageCount == null ? Integer.parseInt(DdiRestConstants.NO_ACTION_HISTORY) : actionHistoryMessageCount); - return actionHistoryMsgs.isEmpty() + return actionHistoryMessages.isEmpty() ? Optional.empty() - : Optional.of(new DdiActionHistory(action.getStatus().name(), actionHistoryMsgs)); + : Optional.of(new DdiActionHistory(action.getStatus().name(), actionHistoryMessages)); } private DdiAutoConfirmationState getAutoConfirmationState(final String controllerId) { - return confirmationManagement.getStatus(controllerId).map(status -> { + return confirmationManagement.findStatus(controllerId).map(status -> { final DdiAutoConfirmationState state = new DdiAutoConfirmationState( true, status.getInitiator(), status.getRemark(), status.getActivatedAt()); log.trace("Returning state auto-conf state active [initiator='{}' | activatedAt={}] for device {}", diff --git a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/AbstractDDiApiIntegrationTest.java b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/AbstractDDiApiIntegrationTest.java index 46c746683..ae440db45 100644 --- a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/AbstractDDiApiIntegrationTest.java +++ b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/AbstractDDiApiIntegrationTest.java @@ -39,12 +39,8 @@ import org.eclipse.hawkbit.ddi.json.model.DdiConfirmationFeedback; import org.eclipse.hawkbit.ddi.json.model.DdiProgress; import org.eclipse.hawkbit.ddi.json.model.DdiResult; import org.eclipse.hawkbit.ddi.json.model.DdiStatus; -import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; -import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; import org.eclipse.hawkbit.repository.jpa.JpaRepositoryConfiguration; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; -import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetSpecification; -import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -171,7 +167,7 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat protected ResultActions performGet(final String url, final MediaType mediaType, final ResultMatcher statusMatcher, final String... values) throws Exception { - return mvc.perform(MockMvcRequestBuilders.get(url, values).accept(mediaType) + return mvc.perform(MockMvcRequestBuilders.get(url, (Object[]) values).accept(mediaType) .with(new RequestOnHawkbitDefaultPortPostProcessor())) .andDo(MockMvcResultPrinter.print()) .andExpect(statusMatcher) @@ -281,14 +277,12 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat } protected String getJsonClosedDeploymentActionFeedback() throws JsonProcessingException { - return getJsonActionFeedback( - DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.NONE, Collections.singletonList("closed")); + return getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.NONE, Collections.singletonList("closed")); } protected String getJsonActionFeedback( final DdiStatus.ExecutionStatus executionStatus, final DdiResult.FinalResult finalResult) throws JsonProcessingException { - return getJsonActionFeedback( - executionStatus, finalResult, Collections.singletonList(randomString(1000))); + return getJsonActionFeedback(executionStatus, finalResult, Collections.singletonList(randomString(1000))); } protected String getJsonActionFeedback( @@ -376,10 +370,10 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat contains(artifact.getSha256Hash()))) .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0]._links.download-http.href", contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId + - "/softwaremodules/" + osModuleId + "/artifacts/" + artifact.getFilename() + "/download"))) + "/softwaremodules/" + osModuleId + "/artifacts/" + artifact.getFilename()))) .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0]._links.md5sum-http.href", contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId + - "/softwaremodules/" + osModuleId + "/artifacts/" + artifact.getFilename() + "/download.MD5SUM"))) + "/softwaremodules/" + osModuleId + "/artifacts/" + artifact.getFilename() + ".MD5SUM"))) .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].size", contains(ARTIFACT_SIZE))) .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].filename", contains(artifactSignature.getFilename()))) @@ -391,10 +385,10 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat contains(artifactSignature.getSha256Hash()))) .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1]._links.download-http.href", contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId + - "/softwaremodules/" + osModuleId + "/artifacts/" + artifactSignature.getFilename() + "/download"))) + "/softwaremodules/" + osModuleId + "/artifacts/" + artifactSignature.getFilename()))) .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1]._links.md5sum-http.href", contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId + - "/softwaremodules/" + osModuleId + "/artifacts/" + artifactSignature.getFilename() + "/download.MD5SUM"))) + "/softwaremodules/" + osModuleId + "/artifacts/" + artifactSignature.getFilename() + ".MD5SUM"))) .andExpect(jsonPath(prefix + ".chunks[?(@.part=='bApp')].version", contains(findFirstModuleByType(ds, appType).orElseThrow().getVersion()))) .andExpect(jsonPath(prefix + ".chunks[?(@.part=='bApp')].metadata").doesNotExist()) diff --git a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiArtifactDownloadTest.java b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiArtifactDownloadTest.java index 043467d4b..58be27f93 100644 --- a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiArtifactDownloadTest.java +++ b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiArtifactDownloadTest.java @@ -57,8 +57,8 @@ import org.springframework.test.web.servlet.MvcResult; @SpringBootTest(classes = { DownloadTestConfiguration.class }) class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest { - private static volatile int downloadProgress = 0; - private static volatile long shippedBytes = 0; + private static int downloadProgress = 0; + private static long shippedBytes = 0; private final SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.ENGLISH); @@ -68,7 +68,7 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest { } /** - * Tests non allowed requests on the artifact ressource, e.g. invalid URI, wrong if-match, wrong command. + * Tests not allowed requests on the artifact resource, e.g. invalid URI, wrong if-match, wrong command. */ @Test void invalidRequestsOnArtifactResource() throws Exception { @@ -83,7 +83,8 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest { final int artifactSize = 5 * 1024; final byte[] random = nextBytes(artifactSize); final Artifact artifact = artifactManagement.create(new ArtifactUpload( - new ByteArrayInputStream(random), findFirstModuleByType(ds, osType).orElseThrow().getId(), "file1", false, artifactSize)); + new ByteArrayInputStream(random), null, artifactSize, null, + findFirstModuleByType(ds, osType).orElseThrow().getId(), "file1", false)); assignDistributionSet(ds, targets); @@ -163,8 +164,10 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest { @Test @WithUser(principal = "4712", authorities = "ROLE_CONTROLLER", allSpPermissions = true) void downloadArtifactThroughFileName() throws Exception { - downloadProgress = 1; - shippedBytes = 0; + synchronized (DdiArtifactDownloadTest.class) { + downloadProgress = 1; + shippedBytes = 0; + } assertThat(softwareModuleManagement.findAll(PAGE)).isEmpty(); // create target @@ -177,8 +180,9 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest { // create artifact final int artifactSize = (int) quotaManagement.getMaxArtifactSize(); final byte[] random = nextBytes(artifactSize); - final Artifact artifact = artifactManagement.create(new ArtifactUpload(new ByteArrayInputStream(random), - findFirstModuleByType(ds, osType).orElseThrow().getId(), "file1", false, artifactSize)); + final Artifact artifact = artifactManagement.create(new ArtifactUpload( + new ByteArrayInputStream(random), null, artifactSize, null, + findFirstModuleByType(ds, osType).orElseThrow().getId(), "file1", false)); // download fails as artifact is not yet assigned mvc.perform(get("/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}", @@ -197,12 +201,13 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest { .andExpect(header().string("Content-Disposition", "attachment;filename=" + artifact.getFilename())) .andReturn(); - assertArrayEquals(result.getResponse().getContentAsByteArray(), random, - "The same file that was uploaded is expected when downloaded"); + assertArrayEquals(result.getResponse().getContentAsByteArray(), random, "The same file that was uploaded is expected when downloaded"); // download complete - assertThat(downloadProgress).isEqualTo(10); - assertThat(shippedBytes).isEqualTo(artifactSize); + synchronized (DdiArtifactDownloadTest.class) { + assertThat(downloadProgress).isEqualTo(10); + assertThat(shippedBytes).isEqualTo(artifactSize); + } } /** @@ -219,8 +224,9 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest { // create artifact final int artifactSize = 5 * 1024; final byte[] random = nextBytes(artifactSize); - final Artifact artifact = artifactManagement.create( - new ArtifactUpload(new ByteArrayInputStream(random), getOsModule(ds), "file1", false, artifactSize)); + final Artifact artifact = artifactManagement.create(new ArtifactUpload( + new ByteArrayInputStream(random), null, artifactSize, null, + getOsModule(ds), "file1", false)); assignDistributionSet(ds, target); @@ -254,8 +260,9 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest { // create artifact final byte[] random = nextBytes(resultLength); - final Artifact artifact = artifactManagement.create( - new ArtifactUpload(new ByteArrayInputStream(random), getOsModule(ds), "file1", false, resultLength)); + final Artifact artifact = artifactManagement.create(new ArtifactUpload( + new ByteArrayInputStream(random), null, resultLength, null, + getOsModule(ds), "file1", false)); assertThat(random).hasSize(resultLength); @@ -379,8 +386,10 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest { @EventListener(classes = DownloadProgressEvent.class) void listen(final DownloadProgressEvent event) { - downloadProgress++; - shippedBytes += event.getShippedBytesSinceLast(); + synchronized (DdiArtifactDownloadTest.class) { + downloadProgress++; + shippedBytes += event.getShippedBytesSinceLast(); + } } } } \ No newline at end of file diff --git a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiCancelActionTest.java b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiCancelActionTest.java index e964a70ba..64a8e648d 100644 --- a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiCancelActionTest.java +++ b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiCancelActionTest.java @@ -139,18 +139,18 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest { .andExpect(status().isOk()); // check database after test - assertThat(deploymentManagement.getAssignedDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).get()) + assertThat(deploymentManagement.findAssignedDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).orElseThrow()) .isEqualTo(ds); - assertThat(deploymentManagement.getInstalledDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).get()) + assertThat(deploymentManagement.findInstalledDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).orElseThrow()) .isEqualTo(ds); assertThat( - targetManagement.getByControllerId(TestdataFactory.DEFAULT_CONTROLLER_ID).get().getInstallationDate()) + targetManagement.getByControllerId(TestdataFactory.DEFAULT_CONTROLLER_ID).getInstallationDate()) .isGreaterThanOrEqualTo(current); } /** - * Test for cancel operation of a update action. + * Test for cancel operation of an update action. */ @Test void rootRsCancelAction() throws Exception { @@ -171,7 +171,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest { startsWith("http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" + actionId))); final long timeAfterFirstPoll = System.currentTimeMillis() + 1; - assertThat(targetManagement.getByControllerId(TestdataFactory.DEFAULT_CONTROLLER_ID).get().getLastTargetQuery()) + assertThat(targetManagement.getByControllerId(TestdataFactory.DEFAULT_CONTROLLER_ID).getLastTargetQuery()) .isBetween(timeBeforeFirstPoll, timeAfterFirstPoll); // Retrieved is reported @@ -202,7 +202,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest { equalTo("http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" + cancelAction.getId()))); final long timeAfter2ndPoll = System.currentTimeMillis() + 1; - assertThat(targetManagement.getByControllerId(TestdataFactory.DEFAULT_CONTROLLER_ID).get().getLastTargetQuery()) + assertThat(targetManagement.getByControllerId(TestdataFactory.DEFAULT_CONTROLLER_ID).getLastTargetQuery()) .isBetween(timeBefore2ndPoll, timeAfter2ndPoll); mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" @@ -212,7 +212,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest { .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction.getId())))) .andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(actionId)))); - assertThat(targetManagement.getByControllerId(TestdataFactory.DEFAULT_CONTROLLER_ID).get().getLastTargetQuery()) + assertThat(targetManagement.getByControllerId(TestdataFactory.DEFAULT_CONTROLLER_ID).getLastTargetQuery()) .isLessThanOrEqualTo(System.currentTimeMillis()); // controller confirmed cancelled action, should not be active anymore @@ -226,7 +226,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest { activeActionsByTarget = deploymentManagement.findActiveActionsByTarget(savedTarget.getControllerId(), PAGE) .getContent(); assertThat(activeActionsByTarget).isEmpty(); - final Action canceledAction = deploymentManagement.findAction(cancelAction.getId()).get(); + final Action canceledAction = deploymentManagement.findAction(cancelAction.getId()).orElseThrow(); assertThat(canceledAction.isActive()).isFalse(); assertThat(canceledAction.getStatus()).isEqualTo(Status.CANCELED); @@ -355,6 +355,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest { /** * Tests the feeback chanel of for multiple open cancel operations on the same target. */ + @SuppressWarnings("java:S5961") @Test void multipleCancelActionFeedback() throws Exception { final DistributionSet ds = testdataFactory.createDistributionSet("", true); @@ -363,14 +364,11 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest { final Target savedTarget = testdataFactory.createTarget(); - final Long actionId = getFirstAssignedActionId( - assignDistributionSet(ds.getId(), TestdataFactory.DEFAULT_CONTROLLER_ID)); + final Long actionId = getFirstAssignedActionId(assignDistributionSet(ds.getId(), TestdataFactory.DEFAULT_CONTROLLER_ID)); implicitLock(ds); - final Long actionId2 = getFirstAssignedActionId( - assignDistributionSet(ds2.getId(), TestdataFactory.DEFAULT_CONTROLLER_ID)); + final Long actionId2 = getFirstAssignedActionId(assignDistributionSet(ds2.getId(), TestdataFactory.DEFAULT_CONTROLLER_ID)); implicitLock(ds2); - final Long actionId3 = getFirstAssignedActionId( - assignDistributionSet(ds3.getId(), TestdataFactory.DEFAULT_CONTROLLER_ID)); + final Long actionId3 = getFirstAssignedActionId(assignDistributionSet(ds3.getId(), TestdataFactory.DEFAULT_CONTROLLER_ID)); implicitLock(ds3); assertThat(countActionStatusAll()).isEqualTo(3); @@ -383,8 +381,9 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest { assertThat(deploymentManagement.findActiveActionsByTarget(savedTarget.getControllerId(), PAGE)).hasSize(3); assertThat(deploymentManagement.countActionsByTarget(savedTarget.getControllerId())).isEqualTo(3); - mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" - + cancelAction.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)) + mvc.perform(get( + "/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" + cancelAction.getId(), + tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) @@ -442,8 +441,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest { .andExpect(status().isOk()); assertThat(countActionStatusAll()).isEqualTo(9); - assertThat(deploymentManagement.getAssignedDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).get()) - .isEqualTo(ds3); + assertThat(deploymentManagement.findAssignedDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).orElseThrow()).isEqualTo(ds3); mvc.perform( get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" + actionId3, tenantAware.getCurrentTenant())) @@ -459,11 +457,11 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest { // action is in cancelling state assertThat(deploymentManagement.findActiveActionsByTarget(savedTarget.getControllerId(), PAGE)).hasSize(1); assertThat(deploymentManagement.countActionsByTarget(savedTarget.getControllerId())).isEqualTo(3); - assertThat(deploymentManagement.getAssignedDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).get()) - .isEqualTo(ds3); + assertThat(deploymentManagement.findAssignedDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).orElseThrow()).isEqualTo(ds3); - mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" - + cancelAction3.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)) + mvc.perform(get( + "/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" + cancelAction3.getId(), + tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) diff --git a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiConfigDataTest.java b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiConfigDataTest.java index 33fea117d..a87e739e8 100644 --- a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiConfigDataTest.java +++ b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiConfigDataTest.java @@ -72,11 +72,11 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest { } - @Test /** * We verify that the config data (i.e. device attributes like serial number, hardware revision etc.) are requested only once from the device.") */ @SuppressWarnings("squid:S2925") + @Test void requestConfigDataIfEmpty() throws Exception { final Target savedTarget = testdataFactory.createTarget("4712"); @@ -90,10 +90,10 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest { "http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/4712/configData"))); Thread.sleep(1); // is required: otherwise processing the next line is // often too fast and // the following assert will fail - assertThat(targetManagement.getByControllerId("4712").orElseThrow(NoSuchElementException::new) + assertThat(targetManagement.getByControllerId("4712") .getLastTargetQuery()) .isLessThanOrEqualTo(System.currentTimeMillis()); - assertThat(targetManagement.getByControllerId("4712").orElseThrow(NoSuchElementException::new) + assertThat(targetManagement.getByControllerId("4712") .getLastTargetQuery()) .isGreaterThanOrEqualTo(current); @@ -140,7 +140,7 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest { /** * We verify that the config data (i.e. device attributes like serial number, hardware revision etc.) - * upload quota is enforced to protect the server from malicious attempts.""") + * upload quota is enforced to protect the server from malicious attempts. */ @Test void putTooMuchConfigData() throws Exception { diff --git a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiConfirmationBaseTest.java b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiConfirmationBaseTest.java index fb2adfad1..b0bd6e0a8 100644 --- a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiConfirmationBaseTest.java +++ b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiConfirmationBaseTest.java @@ -113,13 +113,12 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest { .andExpect(jsonPath("$._links.confirmationBase.href", containsString(expectedConfirmationBaseLink))) .andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist()); - assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery()) - .isGreaterThanOrEqualTo(current); - assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery()) + assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).getLastTargetQuery()).isGreaterThanOrEqualTo(current); + assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).getLastTargetQuery()) .isLessThanOrEqualTo(System.currentTimeMillis()); assertThat(actionStatusRepository.count()).isEqualTo(2); - final DistributionSet findDistributionSetByAction = findDsByAction(action.getId()).get(); + final DistributionSet findDistributionSetByAction = findDsByAction(action.getId()).orElseThrow(); getAndVerifyConfirmationBasePayload( DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact, @@ -142,7 +141,7 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest { final Target target = testdataFactory.createTarget(); final DistributionSet distributionSet = testdataFactory.createDistributionSet(""); - final Long softwareModuleId = distributionSet.getModules().stream().findAny().get().getId(); + final Long softwareModuleId = distributionSet.getModules().stream().findAny().orElseThrow().getId(); testdataFactory.createArtifacts(softwareModuleId); assignDistributionSet(distributionSet.getId(), target.getName()); @@ -359,7 +358,7 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest { .andDo(MockMvcResultPrinter.print()) .andExpect(status().isOk()); - assertThat(confirmationManagement.getStatus(controllerId)).hasValueSatisfying(status -> { + assertThat(confirmationManagement.findStatus(controllerId)).hasValueSatisfying(status -> { assertThat(status.getInitiator()).isEqualTo(initiator); assertThat(status.getRemark()).isEqualTo(remark); assertThat(status.getCreatedBy()).isEqualTo("bumlux"); @@ -379,7 +378,7 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest { .andDo(MockMvcResultPrinter.print()) .andExpect(status().isOk()); - assertThat(confirmationManagement.getStatus(controllerId)).isEmpty(); + assertThat(confirmationManagement.findStatus(controllerId)).isEmpty(); } /** diff --git a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java index a3b9bdf0a..b3a3600a2 100644 --- a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java +++ b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java @@ -41,7 +41,6 @@ import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent; import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper; import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository; import org.eclipse.hawkbit.repository.jpa.repository.ActionStatusRepository; -import org.eclipse.hawkbit.repository.jpa.specifications.ActionSpecifications; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.Action.Status; @@ -89,7 +88,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { final Target target = testdataFactory.createTarget(); final DistributionSet distributionSet = testdataFactory.createDistributionSet(""); - final Long softwareModuleId = distributionSet.getModules().stream().findAny().get().getId(); + final Long softwareModuleId = distributionSet.getModules().stream().findAny().orElseThrow().getId(); testdataFactory.createArtifacts(softwareModuleId); assignDistributionSet(distributionSet.getId(), target.getName()); @@ -128,7 +127,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { final Target target = testdataFactory.createTarget(); final DistributionSet distributionSet = testdataFactory.createDistributionSet(""); - final Long softwareModuleId = distributionSet.getModules().stream().findAny().get().getId(); + final Long softwareModuleId = distributionSet.getModules().stream().findAny().orElseThrow().getId(); testdataFactory.createArtifacts(softwareModuleId); assignDistributionSet(distributionSet.getId(), target.getName()); @@ -181,10 +180,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { .andExpect(jsonPath( "$._links.deploymentBase.href", startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString())))); - assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery()) - .isGreaterThanOrEqualTo(current); - assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery()) - .isLessThanOrEqualTo(System.currentTimeMillis()); + assertLastTargetQueryUpdated(current); assertThat(countActionStatusAll()).isEqualTo(2); final DistributionSet findDistributionSetByAction = findDsByAction(action.getId()).get(); @@ -281,10 +277,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$._links.deploymentBase.href", startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString())))); - assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery()) - .isGreaterThanOrEqualTo(current); - assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery()) - .isLessThanOrEqualTo(System.currentTimeMillis()); + assertLastTargetQueryUpdated(current); assertThat(countActionStatusAll()).isEqualTo(2); final DistributionSet findDistributionSetByAction = findDsByAction(action.getId()).get(); @@ -338,10 +331,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$._links.deploymentBase.href", startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString())))); - assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery()) - .isGreaterThanOrEqualTo(current); - assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery()) - .isLessThanOrEqualTo(System.currentTimeMillis()); + assertLastTargetQueryUpdated(current); assertThat(countActionStatusAll()).isEqualTo(2); final DistributionSet findDistributionSetByAction = findDsByAction(action.getId()).get(); @@ -398,15 +388,11 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { // Run test final long current = System.currentTimeMillis(); - performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), - DEFAULT_CONTROLLER_ID) + performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$._links.deploymentBase.href", startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString())))); - assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery()) - .isGreaterThanOrEqualTo(current); - assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery()) - .isLessThanOrEqualTo(System.currentTimeMillis()); + assertLastTargetQueryUpdated(current); assertThat(countActionStatusAll()).isEqualTo(2); final DistributionSet findDistributionSetByAction = findDsByAction(action.getId()).get(); @@ -490,7 +476,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { } /** - * The server protects itself against too large feedback bodies. The test verifies that + * The server protects itself against too large feedback bodies. The test verifies that * it is not possible to exceed the configured maximum number of feedback details. */ @Test @@ -560,7 +546,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { DistributionSet ds = testdataFactory.createDistributionSet(""); final Target savedTarget = testdataFactory.createTarget(DEFAULT_CONTROLLER_ID); - assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getUpdateStatus()).isEqualTo(TargetUpdateStatus.UNKNOWN); + assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).getUpdateStatus()).isEqualTo(TargetUpdateStatus.UNKNOWN); assignDistributionSet(ds, Collections.singletonList(savedTarget)); final Action action = actionRepository .findAll(byDistributionSetId(ds.getId()), PAGE) @@ -576,8 +562,8 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { assertTargetCountByStatus(0, 1, 0); // redo - ds = distributionSetManagement.getWithDetails(ds.getId()).get(); - assignDistributionSet(ds, Collections.singletonList(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get())); + ds = distributionSetManagement.getWithDetails(ds.getId()); + assignDistributionSet(ds, Collections.singletonList(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID))); final Action action2 = deploymentManagement.findActiveActionsByTarget(DEFAULT_CONTROLLER_ID, PAGE).getContent().get(0); postDeploymentFeedback(DEFAULT_CONTROLLER_ID, action2.getId(), getJsonClosedCancelActionFeedback(), status().isOk()); findTargetAndAssertUpdateStatus(Optional.of(ds), TargetUpdateStatus.IN_SYNC, 0, Optional.of(ds)); @@ -741,9 +727,8 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { assignDistributionSet(ds.getId(), "1080"); final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent().get(0); - final String missingFinishedResultInFeedback = getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, - new DdiResult(null, null), - Collections.singletonList("test")); + final String missingFinishedResultInFeedback = getJsonActionFeedback( + DdiStatus.ExecutionStatus.CLOSED, new DdiResult(null, null), Collections.singletonList("test")); postDeploymentFeedback("1080", action.getId(), missingFinishedResultInFeedback, status().isBadRequest()) .andExpect(jsonPath("$.*", hasSize(3))) @@ -766,15 +751,14 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { } private void assertActionStatusCount(final int actionStatusCount, final int minActionStatusCountInPage) { - final Target target = targetManagement.getByControllerId(DdiDeploymentBaseTest.DEFAULT_CONTROLLER_ID).get(); + final Target target = targetManagement.getByControllerId(DdiDeploymentBaseTest.DEFAULT_CONTROLLER_ID); assertThat(target.getUpdateStatus()).isEqualTo(TargetUpdateStatus.PENDING); assertTargetCountByStatus(1, 0, 0); assertThat(deploymentManagement.findActiveActionsByTarget(target.getControllerId(), PAGE)).hasSize(1); assertThat(countActionStatusAll()).isEqualTo(actionStatusCount); - assertThat(findActionStatusAll(PAGE).getContent()) - .haveAtLeast(minActionStatusCountInPage, new ActionStatusCondition(Status.RUNNING)); + assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(minActionStatusCountInPage, new ActionStatusCondition(Status.RUNNING)); } private Target createTargetAndAssertNoActiveActions() { @@ -796,11 +780,11 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { final Optional ds, final TargetUpdateStatus updateStatus, final int activeActions, final Optional installedDs) { - final Target myT = targetManagement.getByControllerId(DdiDeploymentBaseTest.DEFAULT_CONTROLLER_ID).get(); + final Target myT = targetManagement.getByControllerId(DdiDeploymentBaseTest.DEFAULT_CONTROLLER_ID); assertThat(myT.getUpdateStatus()).isEqualTo(updateStatus); assertThat(deploymentManagement.findActiveActionsByTarget(myT.getControllerId(), PAGE)).hasSize(activeActions); - assertThat(deploymentManagement.getAssignedDistributionSet(myT.getControllerId())).isEqualTo(ds); - assertThat(deploymentManagement.getInstalledDistributionSet(myT.getControllerId())).isEqualTo(installedDs); + assertThat(deploymentManagement.findAssignedDistributionSet(myT.getControllerId())).isEqualTo(ds); + assertThat(deploymentManagement.findInstalledDistributionSet(myT.getControllerId())).isEqualTo(installedDs); } private void assertTargetCountByStatus(final int pending, final int error, final int inSync) { @@ -811,16 +795,26 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { private void assertActionStatusCount(final int total, final int running, final int warning, final int finished, final int canceled) { assertThat(countActionStatusAll()).isEqualTo(total); - assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(running, new ActionStatusCondition(Status.RUNNING)); - assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(warning, new ActionStatusCondition(Status.WARNING)); - assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(canceled, new ActionStatusCondition(Status.CANCELED)); - assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(finished, new ActionStatusCondition(Status.FINISHED)); + assertThat(findActionStatusAll(PAGE).getContent()).satisfies(findActionStatusAll -> { + assertThat(findActionStatusAll).haveAtLeast(running, new ActionStatusCondition(Status.RUNNING)); + assertThat(findActionStatusAll).haveAtLeast(warning, new ActionStatusCondition(Status.WARNING)); + assertThat(findActionStatusAll).haveAtLeast(canceled, new ActionStatusCondition(Status.CANCELED)); + assertThat(findActionStatusAll).haveAtLeast(finished, new ActionStatusCondition(Status.FINISHED)); + }); + } + + private void assertLastTargetQueryUpdated(final long current) { + assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID)).satisfies(target -> { + assertThat(target.getLastTargetQuery()).isGreaterThanOrEqualTo(current); + assertThat(target.getLastTargetQuery()).isLessThanOrEqualTo(System.currentTimeMillis()); + }); } private void assertStatusAndActiveActionsCount(final TargetUpdateStatus status, final int activeActions) { - final Target target = targetManagement.getByControllerId(DdiDeploymentBaseTest.DEFAULT_CONTROLLER_ID).get(); - assertThat(target.getUpdateStatus()).isEqualTo(status); - assertThat(deploymentManagement.findActiveActionsByTarget(target.getControllerId(), PAGE)).hasSize(activeActions); + assertThat(targetManagement.getByControllerId(DdiDeploymentBaseTest.DEFAULT_CONTROLLER_ID)).satisfies(target -> { + assertThat(target.getUpdateStatus()).isEqualTo(status); + assertThat(deploymentManagement.findActiveActionsByTarget(target.getControllerId(), PAGE)).hasSize(activeActions); + }); } private Page findActionStatusAll(final Pageable pageable) { diff --git a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiInstalledBaseTest.java b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiInstalledBaseTest.java index 3344491b7..05c3a34cc 100644 --- a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiInstalledBaseTest.java +++ b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiInstalledBaseTest.java @@ -109,7 +109,7 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest { // update assigned version putInstalledBase(target.getControllerId(), getJsonInstalledBase(ds.getName(), ds.getVersion()), status().isCreated()); - assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).get().getId()).isEqualTo(ds.getId()); + assertThat(deploymentManagement.findAssignedDistributionSet(target.getControllerId()).get().getId()).isEqualTo(ds.getId()); // update assigned version while version already assigned putInstalledBase(target.getControllerId(), getJsonInstalledBase(ds.getName(), ds.getVersion()), status().isOk()); @@ -127,7 +127,7 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest { // get installed base putInstalledBase(target.getControllerId(), getJsonInstalledBase(dsName, dsVersion), status().isNotFound()); - assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).isEmpty()).isTrue(); + assertThat(deploymentManagement.findAssignedDistributionSet(target.getControllerId()).isEmpty()).isTrue(); } /** diff --git a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootControllerTest.java b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootControllerTest.java index 32b00ebde..95fc62064 100644 --- a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootControllerTest.java +++ b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootControllerTest.java @@ -10,8 +10,8 @@ package org.eclipse.hawkbit.ddi.rest.resource; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.hawkbit.im.authentication.SpRole.CONTROLLER_ROLE_ANONYMOUS; import static org.eclipse.hawkbit.im.authentication.SpPermission.TENANT_CONFIGURATION; +import static org.eclipse.hawkbit.im.authentication.SpRole.CONTROLLER_ROLE_ANONYMOUS; import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.callAs; import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.getAs; import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.withController; @@ -125,7 +125,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest { final String knownTargetControllerId = "target1"; final String knownCreatedBy = "knownPrincipal"; testdataFactory.createTarget(knownTargetControllerId); - final Target findTargetByControllerID = targetManagement.getByControllerId(knownTargetControllerId).get(); + final Target findTargetByControllerID = targetManagement.getByControllerId(knownTargetControllerId); assertThat(findTargetByControllerID.getCreatedBy()).isEqualTo(knownCreatedBy); // make a poll, audit information should not be changed, run as controller principal! callAs(withController("controller", CONTROLLER_ROLE_ANONYMOUS), @@ -136,7 +136,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest { return null; }); // verify that audit information has not changed - final Target targetVerify = targetManagement.getByControllerId(knownTargetControllerId).get(); + final Target targetVerify = targetManagement.getByControllerId(knownTargetControllerId); assertThat(targetVerify.getCreatedBy()).isEqualTo(findTargetByControllerID.getCreatedBy()); assertThat(targetVerify.getCreatedAt()).isEqualTo(findTargetByControllerID.getCreatedAt()); assertThat(targetVerify.getLastModifiedBy()).isEqualTo(findTargetByControllerID.getLastModifiedBy()); @@ -170,10 +170,10 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest { .andExpect(status().isOk()) .andExpect(content().contentType(MediaTypes.HAL_JSON)) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))); - assertThat(targetManagement.getByControllerId(controllerId).get().getLastTargetQuery()) - .isGreaterThanOrEqualTo(current); - assertThat(targetManagement.getByControllerId(controllerId).get().getUpdateStatus()) - .isEqualTo(TargetUpdateStatus.REGISTERED); + assertThat(targetManagement.getByControllerId(controllerId)).satisfies(target -> { + assertThat(target.getLastTargetQuery()).isGreaterThanOrEqualTo(current); + assertThat(target.getUpdateStatus()).isEqualTo(TargetUpdateStatus.REGISTERED); + }); // not allowed methods mvc.perform(post(CONTROLLER_BASE, "default-tenant", controllerId)) @@ -265,7 +265,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest { .andDo(MockMvcResultPrinter.print()) .andExpect(status().isNotModified()); - final Target target = targetManagement.getByControllerId(controllerId).get(); + final Target target = targetManagement.getByControllerId(controllerId); final DistributionSet ds = testdataFactory.createDistributionSet(""); assignDistributionSet(ds.getId(), controllerId); @@ -338,19 +338,18 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest { void rootRsPreCommissioned() throws Exception { final String controllerId = "4711"; testdataFactory.createTarget(controllerId); - assertThat(targetManagement.getByControllerId(controllerId).get().getUpdateStatus()).isEqualTo(TargetUpdateStatus.UNKNOWN); + assertThat(targetManagement.getByControllerId(controllerId).getUpdateStatus()).isEqualTo(TargetUpdateStatus.UNKNOWN); final long current = System.currentTimeMillis(); mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isOk()) .andExpect(content().contentType(MediaTypes.HAL_JSON)) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))); - assertThat(targetManagement.getByControllerId(controllerId).get().getLastTargetQuery()) - .isLessThanOrEqualTo(System.currentTimeMillis()); - assertThat(targetManagement.getByControllerId(controllerId).get().getLastTargetQuery()) - .isGreaterThanOrEqualTo(current); - assertThat(targetManagement.getByControllerId(controllerId).get().getUpdateStatus()) - .isEqualTo(TargetUpdateStatus.REGISTERED); + assertThat(targetManagement.getByControllerId(controllerId)).satisfies(target -> { + assertThat(target.getLastTargetQuery()).isLessThanOrEqualTo(System.currentTimeMillis()); + assertThat(target.getLastTargetQuery()).isGreaterThanOrEqualTo(current); + assertThat(target.getUpdateStatus()).isEqualTo(TargetUpdateStatus.REGISTERED); + }); } /** @@ -374,12 +373,13 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest { return null; }); // verify - final Target target = targetManagement.getByControllerId(knownControllerId1).get(); - assertThat(target.getAddress()).isEqualTo(IpUtil.createHttpUri("127.0.0.1").toString()); - assertThat(target.getCreatedBy()).isEqualTo("CONTROLLER_PLUG_AND_PLAY"); - assertThat(target.getCreatedAt()).isGreaterThanOrEqualTo(create); - assertThat(target.getLastModifiedBy()).isEqualTo("CONTROLLER_PLUG_AND_PLAY"); - assertThat(target.getLastModifiedAt()).isGreaterThanOrEqualTo(create); + assertThat(targetManagement.getByControllerId(knownControllerId1)).satisfies(target -> { + assertThat(target.getAddress()).isEqualTo(IpUtil.createHttpUri("127.0.0.1").toString()); + assertThat(target.getCreatedBy()).isEqualTo("CONTROLLER_PLUG_AND_PLAY"); + assertThat(target.getCreatedAt()).isGreaterThanOrEqualTo(create); + assertThat(target.getLastModifiedBy()).isEqualTo("CONTROLLER_PLUG_AND_PLAY"); + assertThat(target.getLastModifiedAt()).isGreaterThanOrEqualTo(create); + }); } /** @@ -397,7 +397,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest { .andDo(MockMvcResultPrinter.print()) .andExpect(status().isOk()); // verify - final Target target = targetManagement.getByControllerId(knownControllerId1).get(); + final Target target = targetManagement.getByControllerId(knownControllerId1); assertThat(target.getAddress()).isEqualTo(IpUtil.createHttpUri("***").toString()); securityProperties.getClients().setTrackRemoteIp(true); } diff --git a/hawkbit-ddi/hawkbit-ddi-starter/pom.xml b/hawkbit-ddi/hawkbit-ddi-starter/pom.xml index 17988e48a..501518a02 100644 --- a/hawkbit-ddi/hawkbit-ddi-starter/pom.xml +++ b/hawkbit-ddi/hawkbit-ddi-starter/pom.xml @@ -30,7 +30,7 @@ org.eclipse.hawkbit - hawkbit-artifact-repository-filesystem + hawkbit-artifact-fs ${project.version} diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherService.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherService.java index fd8657ee7..55cd7b74d 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherService.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherService.java @@ -29,6 +29,9 @@ import java.util.stream.StreamSupport; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.IterableUtils; import org.apache.commons.collections4.ListUtils; +import org.eclipse.hawkbit.artifact.urlresolver.ArtifactUrl; +import org.eclipse.hawkbit.artifact.urlresolver.ArtifactUrlResolver; +import org.eclipse.hawkbit.artifact.urlresolver.ArtifactUrlResolver.DownloadDescriptor; import org.eclipse.hawkbit.dmf.amqp.api.EventTopic; import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey; import org.eclipse.hawkbit.dmf.amqp.api.MessageType; @@ -49,23 +52,18 @@ import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement; -import org.eclipse.hawkbit.repository.artifact.urlhandler.ApiType; -import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrl; -import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrlHandler; -import org.eclipse.hawkbit.repository.artifact.urlhandler.URLPlaceholder; -import org.eclipse.hawkbit.repository.artifact.urlhandler.URLPlaceholder.SoftwareData; import org.eclipse.hawkbit.repository.event.remote.CancelTargetAssignmentEvent; +import org.eclipse.hawkbit.repository.event.remote.MultiActionAssignEvent; import org.eclipse.hawkbit.repository.event.remote.MultiActionCancelEvent; +import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent; +import org.eclipse.hawkbit.repository.event.remote.TargetAttributesRequestedEvent; +import org.eclipse.hawkbit.repository.event.remote.TargetDeletedEvent; import org.eclipse.hawkbit.repository.event.remote.service.CancelTargetAssignmentServiceEvent; import org.eclipse.hawkbit.repository.event.remote.service.MultiActionAssignServiceEvent; import org.eclipse.hawkbit.repository.event.remote.service.MultiActionCancelServiceEvent; import org.eclipse.hawkbit.repository.event.remote.service.TargetAssignDistributionSetServiceEvent; import org.eclipse.hawkbit.repository.event.remote.service.TargetAttributesRequestedServiceEvent; import org.eclipse.hawkbit.repository.event.remote.service.TargetDeletedServiceEvent; -import org.eclipse.hawkbit.repository.event.remote.MultiActionAssignEvent; -import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent; -import org.eclipse.hawkbit.repository.event.remote.TargetAttributesRequestedEvent; -import org.eclipse.hawkbit.repository.event.remote.TargetDeletedEvent; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.ActionProperties; import org.eclipse.hawkbit.repository.model.Artifact; @@ -94,7 +92,7 @@ public class AmqpMessageDispatcherService extends BaseAmqpService { private static final int MAX_PROCESSING_SIZE = 1000; - private final ArtifactUrlHandler artifactUrlHandler; + private final ArtifactUrlResolver artifactUrlHandler; private final AmqpMessageSenderService amqpSenderService; private final SystemSecurityContext systemSecurityContext; private final SystemManagement systemManagement; @@ -108,7 +106,7 @@ public class AmqpMessageDispatcherService extends BaseAmqpService { @SuppressWarnings("java:S107") protected AmqpMessageDispatcherService( final RabbitTemplate rabbitTemplate, - final AmqpMessageSenderService amqpSenderService, final ArtifactUrlHandler artifactUrlHandler, + final AmqpMessageSenderService amqpSenderService, final ArtifactUrlResolver artifactUrlHandler, final SystemSecurityContext systemSecurityContext, final SystemManagement systemManagement, final TargetManagement targetManagement, final SoftwareModuleManagement softwareModuleManagement, @@ -138,7 +136,7 @@ public class AmqpMessageDispatcherService extends BaseAmqpService { /** * Method to send a message to a RabbitMQ Exchange after the Distribution set has been assign to a Target. * - * @param targetAssignDistributionSetServiceEvent event to be processed + * @param targetAssignDistributionSetServiceEvent event to be processed */ @EventListener(classes = TargetAssignDistributionSetServiceEvent.class) protected void targetAssignDistributionSet(final TargetAssignDistributionSetServiceEvent targetAssignDistributionSetServiceEvent) { @@ -200,9 +198,7 @@ public class AmqpMessageDispatcherService extends BaseAmqpService { @EventListener(classes = CancelTargetAssignmentServiceEvent.class) protected void targetCancelAssignmentToDistributionSet(final CancelTargetAssignmentServiceEvent cancelTargetAssignmentServiceEvent) { final CancelTargetAssignmentEvent cancelEvent = cancelTargetAssignmentServiceEvent.getRemoteEvent(); - final List eventTargets = partitionedParallelExecution( - cancelEvent.getActions().keySet(), targetManagement::getByControllerId); - + final List eventTargets = partitionedParallelExecution(cancelEvent.getActions().keySet(), targetManagement::findByControllerId); eventTargets.forEach(target -> cancelEvent.getActionPropertiesForController(target.getControllerId()) .map(ActionProperties::getId) @@ -400,7 +396,7 @@ public class AmqpMessageDispatcherService extends BaseAmqpService { private List getTargetsWithoutPendingCancellations(final Set controllerIds) { return partitionedParallelExecution(controllerIds, partition -> - targetManagement.getByControllerId(partition).stream() + targetManagement.findByControllerId(partition).stream() .filter(target -> { if (hasPendingCancellations(target.getId())) { log.debug("Target {} has pending cancellations. Will not send update message to it.", @@ -450,7 +446,7 @@ public class AmqpMessageDispatcherService extends BaseAmqpService { ? Collections.emptyMap() : softwareModuleManagement.findMetaDataBySoftwareModuleIdsAndTargetVisible(allSmIds); - targetManagement.getByControllerId(controllerIds).forEach(target -> + targetManagement.findByControllerId(controllerIds).forEach(target -> sendMultiActionRequestToTarget( target, controllerIdToActions.get(target.getControllerId()), module -> getSoftwareModuleMetadata.get(module.getId()))); } @@ -558,14 +554,12 @@ public class AmqpMessageDispatcherService extends BaseAmqpService { localArtifact.getSize(), localArtifact.getLastModifiedAt(), artifactUrlHandler - .getUrls(new URLPlaceholder( - tenantMetadata.getTenant(), tenantMetadata.getId(), target.getControllerId(), target.getId(), - new SoftwareData( - localArtifact.getSoftwareModule().getId(), localArtifact.getFilename(), localArtifact.getId(), - localArtifact.getSha1Hash())), - ApiType.DMF) + .getUrls(new DownloadDescriptor( + tenantMetadata.getTenant(), target.getControllerId(), + localArtifact.getSoftwareModule().getId(), localArtifact.getFilename(), localArtifact.getSha1Hash()), + ArtifactUrlResolver.ApiType.DMF) .stream() - .collect(Collectors.toMap(ArtifactUrl::getProtocol, ArtifactUrl::getRef)) + .collect(Collectors.toMap(ArtifactUrl::protocol, ArtifactUrl::ref)) ); } diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DmfApiConfiguration.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DmfApiConfiguration.java index 8025ecf33..30e29b9ae 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DmfApiConfiguration.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DmfApiConfiguration.java @@ -18,13 +18,13 @@ import java.util.regex.Pattern; import lombok.ToString; import lombok.extern.slf4j.Slf4j; -import org.eclipse.hawkbit.repository.RepositoryProperties; -import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrlHandler; +import org.eclipse.hawkbit.artifact.urlresolver.ArtifactUrlResolver; import org.eclipse.hawkbit.dmf.amqp.api.AmqpSettings; import org.eclipse.hawkbit.repository.ConfirmationManagement; import org.eclipse.hawkbit.repository.ControllerManagement; import org.eclipse.hawkbit.repository.DeploymentManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement; +import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.TargetManagement; @@ -265,9 +265,10 @@ public class DmfApiConfiguration { @ConditionalOnMissingBean(AmqpMessageDispatcherService.class) AmqpMessageDispatcherService amqpMessageDispatcherService( final RabbitTemplate rabbitTemplate, - final AmqpMessageSenderService amqpSenderService, final ArtifactUrlHandler artifactUrlHandler, + final AmqpMessageSenderService amqpSenderService, final ArtifactUrlResolver artifactUrlHandler, final SystemSecurityContext systemSecurityContext, final SystemManagement systemManagement, - final TargetManagement targetManagement, final DistributionSetManagement distributionSetManagement, + final TargetManagement targetManagement, + final DistributionSetManagement distributionSetManagement, final SoftwareModuleManagement softwareModuleManagement, final DeploymentManagement deploymentManagement, final TenantConfigurationManagement tenantConfigurationManagement, final RepositoryProperties repositoryProperties) { return new AmqpMessageDispatcherService(rabbitTemplate, amqpSenderService, artifactUrlHandler, diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/RequeueExceptionStrategy.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/RequeueExceptionStrategy.java index 387ba449e..6ddf957f4 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/RequeueExceptionStrategy.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/RequeueExceptionStrategy.java @@ -19,7 +19,6 @@ import lombok.extern.slf4j.Slf4j; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; -import org.eclipse.hawkbit.repository.exception.InvalidTargetAddressException; import org.eclipse.hawkbit.repository.exception.InvalidTargetAttributeException; import org.eclipse.hawkbit.repository.exception.TenantNotExistException; import org.springframework.amqp.rabbit.listener.FatalExceptionStrategy; @@ -53,7 +52,7 @@ class RequeueExceptionStrategy implements FatalExceptionStrategy { // is invalid content, repository exception ConstraintViolationException.class, InvalidTargetAttributeException.class, // is invalid content, message exception - InvalidTargetAddressException.class, MessageHandlingException.class + MessageHandlingException.class )); if (!ObjectUtils.isEmpty(fatalExceptionTypes)) { // add explicitly configured fatal exception types diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherServiceTest.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherServiceTest.java index b4e0fe306..18f3a8fc0 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherServiceTest.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherServiceTest.java @@ -15,7 +15,6 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import java.io.File; import java.net.URI; import java.util.ArrayList; import java.util.Collections; @@ -23,28 +22,27 @@ import java.util.List; import java.util.Optional; import java.util.UUID; -import org.eclipse.hawkbit.repository.RepositoryProperties; -import org.eclipse.hawkbit.repository.TargetManagement.Create; -import org.eclipse.hawkbit.repository.artifact.ArtifactFilesystem; -import org.eclipse.hawkbit.repository.artifact.model.AbstractDbArtifact; -import org.eclipse.hawkbit.repository.artifact.model.DbArtifactHash; -import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrl; -import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrlHandler; +import org.eclipse.hawkbit.artifact.model.ArtifactHashes; +import org.eclipse.hawkbit.artifact.model.StoredArtifactInfo; +import org.eclipse.hawkbit.artifact.urlresolver.ArtifactUrl; +import org.eclipse.hawkbit.artifact.urlresolver.ArtifactUrlResolver; import org.eclipse.hawkbit.dmf.amqp.api.EventTopic; import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey; import org.eclipse.hawkbit.dmf.amqp.api.MessageType; import org.eclipse.hawkbit.dmf.json.model.DmfActionRequest; import org.eclipse.hawkbit.dmf.json.model.DmfDownloadAndUpdateRequest; import org.eclipse.hawkbit.dmf.json.model.DmfSoftwareModule; +import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.SystemManagement; +import org.eclipse.hawkbit.repository.TargetManagement.Create; import org.eclipse.hawkbit.repository.event.remote.CancelTargetAssignmentEvent; +import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent; +import org.eclipse.hawkbit.repository.event.remote.TargetAttributesRequestedEvent; +import org.eclipse.hawkbit.repository.event.remote.TargetDeletedEvent; import org.eclipse.hawkbit.repository.event.remote.service.CancelTargetAssignmentServiceEvent; import org.eclipse.hawkbit.repository.event.remote.service.TargetAssignDistributionSetServiceEvent; import org.eclipse.hawkbit.repository.event.remote.service.TargetAttributesRequestedServiceEvent; import org.eclipse.hawkbit.repository.event.remote.service.TargetDeletedServiceEvent; -import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent; -import org.eclipse.hawkbit.repository.event.remote.TargetAttributesRequestedEvent; -import org.eclipse.hawkbit.repository.event.remote.TargetDeletedEvent; import org.eclipse.hawkbit.repository.jpa.JpaRepositoryConfiguration; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Artifact; @@ -105,7 +103,7 @@ class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest { senderService = Mockito.mock(DefaultAmqpMessageSenderService.class); - final ArtifactUrlHandler artifactUrlHandlerMock = Mockito.mock(ArtifactUrlHandler.class); + final ArtifactUrlResolver artifactUrlHandlerMock = Mockito.mock(ArtifactUrlResolver.class); when(artifactUrlHandlerMock.getUrls(any(), any())) .thenReturn(Collections.singletonList(new ArtifactUrl("http", "download", "http://mockurl"))); @@ -178,24 +176,25 @@ class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest { void testSendDownloadRequest() { DistributionSet dsA = testdataFactory.createDistributionSet(UUID.randomUUID().toString()); SoftwareModule module = dsA.getModules().iterator().next(); - final List receivedList = new ArrayList<>(); + final List receivedList = new ArrayList<>(); for (final Artifact artifact : testdataFactory.createArtifacts(module.getId())) { - receivedList.add(new ArtifactFilesystem(new File("./test"), artifact.getSha1Hash(), - new DbArtifactHash(artifact.getSha1Hash(), null, null), artifact.getSize(), null)); + receivedList.add(new StoredArtifactInfo( + null, artifact.getSize(), + new ArtifactHashes(artifact.getSha1Hash(), artifact.getMd5Hash(), artifact.getSha256Hash()))); } - module = softwareModuleManagement.find(module.getId()).get(); - dsA = distributionSetManagement.find(dsA.getId()).get(); + module = softwareModuleManagement.get(module.getId()); + dsA = distributionSetManagement.get(dsA.getId()); final Action action = createAction(dsA); Mockito.when(rabbitTemplate.convertSendAndReceive(any())).thenReturn(receivedList); final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent(action); - final TargetAssignDistributionSetServiceEvent targetAssignDistributionSetServiceEvent = new TargetAssignDistributionSetServiceEvent(targetAssignDistributionSetEvent); + final TargetAssignDistributionSetServiceEvent targetAssignDistributionSetServiceEvent = new TargetAssignDistributionSetServiceEvent( + targetAssignDistributionSetEvent); amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetServiceEvent); final Message sendMessage = getCaptureAddressEvent(targetAssignDistributionSetEvent); - final DmfDownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage, - action.getId()); + final DmfDownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage, action.getId()); assertThat(downloadAndUpdateRequest.getSoftwareModules()) .as("DownloadAndUpdateRequest event should contains 3 software modules") @@ -231,7 +230,7 @@ class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest { void sendUpdateAttributesRequest() { final String amqpUri = "amqp://anyhost"; final TargetAttributesRequestedEvent targetAttributesRequestedEvent = new TargetAttributesRequestedEvent( - TENANT,1L, Target.class, CONTROLLER_ID, amqpUri); + TENANT, 1L, Target.class, CONTROLLER_ID, amqpUri); final TargetAttributesRequestedServiceEvent targetAttributesRequestedServiceEvent = new TargetAttributesRequestedServiceEvent(targetAttributesRequestedEvent); amqpMessageDispatcherService.targetTriggerUpdateAttributes(targetAttributesRequestedServiceEvent); @@ -314,7 +313,7 @@ class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest { } private Message getCaptureAddressEvent(final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent) { - final Target target = targetManagement.getByControllerId(targetAssignDistributionSetEvent.getActions().keySet().iterator().next()).get(); + final Target target = targetManagement.getByControllerId(targetAssignDistributionSetEvent.getActions().keySet().iterator().next()); return createArgumentCapture(IpUtil.addressToUri(target.getAddress())); } diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AbstractAmqpServiceIntegrationTest.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AbstractAmqpServiceIntegrationTest.java index 10f06a1e7..0b7780965 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AbstractAmqpServiceIntegrationTest.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AbstractAmqpServiceIntegrationTest.java @@ -188,7 +188,7 @@ abstract class AbstractAmqpServiceIntegrationTest extends AbstractAmqpIntegratio protected void assertDmfDownloadAndUpdateRequest( final DmfDownloadAndUpdateRequest request, final Set softwareModules, final String controllerId) { assertSoftwareModules(softwareModules, request.getSoftwareModules()); - final Target updatedTarget = waitUntilIsPresent(() -> targetManagement.getByControllerId(controllerId)); + final Target updatedTarget = waitUntilIsPresent(() -> targetManagement.findByControllerId(controllerId)); assertThat(updatedTarget).isNotNull(); assertThat(updatedTarget.getSecurityToken()).isEqualTo(request.getTargetSecurityToken()); } @@ -266,8 +266,9 @@ abstract class AbstractAmqpServiceIntegrationTest extends AbstractAmqpIntegratio protected void registerAndAssertTargetWithExistingTenant(final String controllerId, final String name, final int existingTargetsAfterCreation, final TargetUpdateStatus expectedTargetStatus, final String createdBy, final Map attributes) { - registerAndAssertTargetWithExistingTenant(controllerId, name, existingTargetsAfterCreation, - expectedTargetStatus, createdBy, attributes, () -> targetManagement.getByControllerId(controllerId)); + registerAndAssertTargetWithExistingTenant( + controllerId, name, existingTargetsAfterCreation, expectedTargetStatus, createdBy, attributes, + () -> targetManagement.findByControllerId(controllerId)); } protected void registerSameTargetAndAssertBasedOnVersion(final String controllerId, @@ -413,7 +414,7 @@ abstract class AbstractAmqpServiceIntegrationTest extends AbstractAmqpIntegratio protected void assertConfirmRequest(final DmfConfirmRequest request, final Set softwareModules, final String controllerId) { assertSoftwareModules(softwareModules, request.getSoftwareModules()); - final Target updatedTarget = waitUntilIsPresent(() -> targetManagement.getByControllerId(controllerId)); + final Target updatedTarget = waitUntilIsPresent(() -> targetManagement.findByControllerId(controllerId)); assertThat(updatedTarget).isNotNull(); assertThat(updatedTarget.getSecurityToken()).isEqualTo(request.getTargetSecurityToken()); } diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageDispatcherServiceIntegrationTest.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageDispatcherServiceIntegrationTest.java index af7873206..e4a5fb636 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageDispatcherServiceIntegrationTest.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageDispatcherServiceIntegrationTest.java @@ -787,9 +787,8 @@ class AmqpMessageDispatcherServiceIntegrationTest extends AbstractAmqpServiceInt private void waitUntilTargetHasStatus(final String controllerId, final TargetUpdateStatus status) { waitUntil(() -> { - final Optional findTargetByControllerID = targetManagement.getByControllerId(controllerId); - return findTargetByControllerID.isPresent() - && status.equals(findTargetByControllerID.get().getUpdateStatus()); + final Optional findTargetByControllerID = targetManagement.findByControllerId(controllerId); + return findTargetByControllerID.isPresent() && status.equals(findTargetByControllerID.get().getUpdateStatus()); }); } diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageHandlerServiceIntegrationTest.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageHandlerServiceIntegrationTest.java index 2a727f2ec..300044d59 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageHandlerServiceIntegrationTest.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageHandlerServiceIntegrationTest.java @@ -950,7 +950,7 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr amqpMessageHandlerService.setControllerManagement(mockedControllerManagement); createAndSendThingCreated(controllerId); verifyOneDeadLetterMessage(); - assertThat(targetManagement.getByControllerId(controllerId)).isEmpty(); + assertThat(targetManagement.findByControllerId(controllerId)).isEmpty(); } } finally { amqpMessageHandlerService.setControllerManagement(controllerManagement); diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadArtifactResource.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadArtifactResource.java index 177d76699..b314585c4 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadArtifactResource.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadArtifactResource.java @@ -13,8 +13,8 @@ import java.io.InputStream; import jakarta.servlet.http.HttpServletRequest; -import org.eclipse.hawkbit.repository.artifact.exception.ArtifactBinaryNoLongerExistsException; -import org.eclipse.hawkbit.repository.artifact.model.DbArtifact; +import org.eclipse.hawkbit.artifact.exception.ArtifactBinaryNoLongerExistsException; +import org.eclipse.hawkbit.artifact.model.ArtifactStream; import org.eclipse.hawkbit.mgmt.rest.api.MgmtDownloadArtifactRestApi; import org.eclipse.hawkbit.repository.ArtifactManagement; import org.eclipse.hawkbit.repository.SoftwareModuleManagement; @@ -38,7 +38,8 @@ public class MgmtDownloadArtifactResource implements MgmtDownloadArtifactRestApi private final SoftwareModuleManagement softwareModuleManagement; private final ArtifactManagement artifactManagement; - public MgmtDownloadArtifactResource(final SoftwareModuleManagement softwareModuleManagement, final ArtifactManagement artifactManagement) { + public MgmtDownloadArtifactResource(final SoftwareModuleManagement softwareModuleManagement, + final ArtifactManagement artifactManagement) { this.softwareModuleManagement = softwareModuleManagement; this.artifactManagement = artifactManagement; } @@ -60,7 +61,7 @@ public class MgmtDownloadArtifactResource implements MgmtDownloadArtifactRestApi final Artifact artifact = module.getArtifact(artifactId) .orElseThrow(() -> new EntityNotFoundException(Artifact.class, artifactId)); - final DbArtifact file = artifactManagement.loadArtifactBinary(artifact.getSha1Hash(), module.getId(), module.isEncrypted()); + final ArtifactStream file = artifactManagement.getArtifactStream(artifact.getSha1Hash(), module.getId(), module.isEncrypted()); final HttpServletRequest request = RequestResponseContextHolder.getHttpServletRequest(); final String ifMatch = request.getHeader(HttpHeaders.IF_MATCH); if (ifMatch != null && !HttpUtil.matchesHttpHeader(ifMatch, artifact.getSha1Hash())) { diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResource.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResource.java index 073edd3f9..d1a449a23 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResource.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResource.java @@ -106,10 +106,7 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi { @Override public ResponseEntity getRollout(final Long rolloutId) { - final Rollout findRolloutById = rolloutManagement.getWithDetailedStatus(rolloutId) - .orElseThrow(() -> new EntityNotFoundException(Rollout.class, rolloutId)); - - return ResponseEntity.ok(MgmtRolloutMapper.toResponseRollout(findRolloutById, true)); + return ResponseEntity.ok(MgmtRolloutMapper.toResponseRollout(rolloutManagement.getWithDetailedStatus(rolloutId), true)); } @Override @@ -238,8 +235,7 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi { public ResponseEntity getRolloutGroup(final Long rolloutId, final Long groupId) { findRolloutOrThrowException(rolloutId); - final RolloutGroup rolloutGroup = rolloutGroupManagement.getWithDetailedStatus(groupId) - .orElseThrow(() -> new EntityNotFoundException(RolloutGroup.class, rolloutId)); + final RolloutGroup rolloutGroup = rolloutGroupManagement.getWithDetailedStatus(groupId); if (!Objects.equals(rolloutId, rolloutGroup.getRollout().getId())) { throw new EntityNotFoundException(RolloutGroup.class, groupId); } @@ -273,8 +269,7 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi { @Override public ResponseEntity retryRollout(final Long rolloutId) { - final Rollout rolloutForRetry = rolloutManagement.find(rolloutId) - .orElseThrow(() -> new EntityNotFoundException(Rollout.class, rolloutId)); + final Rollout rolloutForRetry = rolloutManagement.get(rolloutId); if (rolloutForRetry.isDeleted()) { throw new EntityNotFoundException(Rollout.class, rolloutId); } diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java index 14446f206..5e5242ea7 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java @@ -22,7 +22,6 @@ import java.util.Optional; import jakarta.validation.ValidationException; import lombok.extern.slf4j.Slf4j; -import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrlHandler; import org.eclipse.hawkbit.audit.AuditLog; import org.eclipse.hawkbit.mgmt.json.model.PagedList; import org.eclipse.hawkbit.mgmt.json.model.artifact.MgmtArtifact; @@ -39,6 +38,8 @@ import org.eclipse.hawkbit.repository.ArtifactManagement; import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; import org.eclipse.hawkbit.repository.SystemManagement; +import org.eclipse.hawkbit.artifact.model.ArtifactHashes; +import org.eclipse.hawkbit.artifact.urlresolver.ArtifactUrlResolver; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.ArtifactUpload; @@ -65,7 +66,7 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi { private final ArtifactManagement artifactManagement; private final SoftwareModuleManagement softwareModuleManagement; private final SoftwareModuleTypeManagement softwareModuleTypeManagement; - private final ArtifactUrlHandler artifactUrlHandler; + private final ArtifactUrlResolver artifactUrlHandler; private final MgmtSoftwareModuleMapper mgmtSoftwareModuleMapper; private final SystemManagement systemManagement; @@ -73,7 +74,7 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi { final ArtifactManagement artifactManagement, final SoftwareModuleManagement softwareModuleManagement, final SoftwareModuleTypeManagement softwareModuleTypeManagement, - final ArtifactUrlHandler artifactUrlHandler, + final ArtifactUrlResolver artifactUrlHandler, final MgmtSoftwareModuleMapper mgmtSoftwareModuleMapper, final SystemManagement systemManagement) { this.artifactManagement = artifactManagement; @@ -98,14 +99,17 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi { } try (final InputStream in = file.getInputStream()) { - final Artifact result = artifactManagement.create(new ArtifactUpload(in, softwareModuleId, fileName, - md5Sum == null ? null : md5Sum.toLowerCase(), sha1Sum == null ? null : sha1Sum.toLowerCase(), - sha256Sum == null ? null : sha256Sum.toLowerCase(), false, file.getContentType(), file.getSize())); + final Artifact result = artifactManagement.create(new ArtifactUpload( + in, file.getContentType(), file.getSize(), + new ArtifactHashes( + sha1Sum == null ? null : sha1Sum.toLowerCase(), + md5Sum == null ? null : md5Sum.toLowerCase(), + sha256Sum == null ? null : sha256Sum.toLowerCase()), + softwareModuleId, fileName, false)); - final MgmtArtifact reponse = MgmtSoftwareModuleMapper.toResponse(result); - MgmtSoftwareModuleMapper.addLinks(result, reponse); - - return ResponseEntity.status(HttpStatus.CREATED).body(reponse); + final MgmtArtifact response = MgmtSoftwareModuleMapper.toResponse(result); + MgmtSoftwareModuleMapper.addLinks(result, response); + return ResponseEntity.status(HttpStatus.CREATED).body(response); } catch (final IOException e) { log.error("Failed to store artifact", e); return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSystemManagementResource.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSystemManagementResource.java index d5a32f6a4..38ec62fab 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSystemManagementResource.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSystemManagementResource.java @@ -20,8 +20,8 @@ import org.eclipse.hawkbit.mgmt.json.model.systemmanagement.MgmtSystemStatistics import org.eclipse.hawkbit.mgmt.json.model.systemmanagement.MgmtSystemTenantServiceUsage; import org.eclipse.hawkbit.mgmt.rest.api.MgmtSystemManagementRestApi; import org.eclipse.hawkbit.repository.SystemManagement; -import org.eclipse.hawkbit.repository.report.model.SystemUsageReportWithTenants; -import org.eclipse.hawkbit.repository.report.model.TenantUsage; +import org.eclipse.hawkbit.repository.model.report.SystemUsageReportWithTenants; +import org.eclipse.hawkbit.repository.model.report.TenantUsage; import org.springframework.cache.CacheManager; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResource.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResource.java index 198e2e91a..619d64705 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResource.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResource.java @@ -108,7 +108,7 @@ public class MgmtTargetResource implements MgmtTargetRestApi { @Override public ResponseEntity getTarget(final String targetId) { - final Target findTarget = findTargetWithExceptionIfNotFound(targetId); + final Target findTarget = targetManagement.getByControllerId(targetId); // to single response include poll status final MgmtTarget response = MgmtTargetMapper.toResponse(findTarget, tenantConfigHelper, null); MgmtTargetMapper.addTargetLinks(response); @@ -142,11 +142,10 @@ public class MgmtTargetResource implements MgmtTargetRestApi { @Override @AuditLog(entity = "Target", type = AuditLog.Type.UPDATE, description = "Update Target") public ResponseEntity updateTarget(final String targetId, final MgmtTargetRequestBody targetRest) { - if (targetRest.getRequestAttributes() != null && !Boolean.TRUE.equals(targetRest.getRequestAttributes())) { + if (targetRest.getRequestAttributes() != null && !targetRest.getRequestAttributes()) { return ResponseEntity.badRequest().build(); } - final Target targetToUpdate = targetManagement.getByControllerId(targetId) - .orElseThrow(() -> new EntityNotFoundException(Target.class, targetId)); + final Target targetToUpdate = targetManagement.getByControllerId(targetId); final TargetType targetType = Optional.ofNullable(targetRest.getTargetType()) .map(targetTypeId -> { if (targetTypeId == -1L) { @@ -211,7 +210,7 @@ public class MgmtTargetResource implements MgmtTargetRestApi { public ResponseEntity> getActionHistory( final String targetId, final String rsqlParam, final int pagingOffsetParam, final int pagingLimitParam, final String sortParam) { - findTargetWithExceptionIfNotFound(targetId); + targetManagement.getByControllerId(targetId); final Pageable pageable = PagingUtility.toPageable(pagingOffsetParam, pagingLimitParam, sanitizeActionSortParam(sortParam)); final Slice activeActions; @@ -331,7 +330,7 @@ public class MgmtTargetResource implements MgmtTargetRestApi { public ResponseEntity> getActionStatusList( final String targetId, final Long actionId, final int pagingOffsetParam, final int pagingLimitParam, final String sortParam) { - final Target target = findTargetWithExceptionIfNotFound(targetId); + final Target target = targetManagement.getByControllerId(targetId); final Action action = deploymentManagement.findAction(actionId) .orElseThrow(() -> new EntityNotFoundException(Action.class, actionId)); @@ -350,7 +349,7 @@ public class MgmtTargetResource implements MgmtTargetRestApi { @Override public ResponseEntity getAssignedDistributionSet(final String targetId) { - final MgmtDistributionSet distributionSetRest = deploymentManagement.getAssignedDistributionSet(targetId) + final MgmtDistributionSet distributionSetRest = deploymentManagement.findAssignedDistributionSet(targetId) .map(ds -> { final MgmtDistributionSet response = MgmtDistributionSetMapper.toResponse(ds); MgmtDistributionSetMapper.addLinks(ds, response); @@ -375,7 +374,7 @@ public class MgmtTargetResource implements MgmtTargetRestApi { return ResponseEntity.ok(mgmtDistributionSetMapper .toResponse(deploymentManagement.offlineAssignedDistributionSets(offlineAssignments))); } - findTargetWithExceptionIfNotFound(targetId); + targetManagement.getByControllerId(targetId); final List deploymentRequests = dsAssignments.stream().map(dsAssignment -> { final boolean isConfirmationRequired = dsAssignment.getConfirmationRequired() == null @@ -392,19 +391,14 @@ public class MgmtTargetResource implements MgmtTargetRestApi { @Override public ResponseEntity getInstalledDistributionSet(final String targetId) { - final MgmtDistributionSet distributionSetRest = deploymentManagement.getInstalledDistributionSet(targetId) + return deploymentManagement.findInstalledDistributionSet(targetId) .map(set -> { final MgmtDistributionSet response = MgmtDistributionSetMapper.toResponse(set); MgmtDistributionSetMapper.addLinks(set, response); - return response; - }).orElse(null); - - if (distributionSetRest == null) { - return ResponseEntity.noContent().build(); - } - - return ResponseEntity.ok(distributionSetRest); + }) + .map(distributionSetRest -> ResponseEntity.ok(distributionSetRest)) + .orElseGet(() -> ResponseEntity.noContent().build()); } @Override @@ -467,11 +461,6 @@ public class MgmtTargetResource implements MgmtTargetRestApi { return new ResponseEntity<>(HttpStatus.OK); } - private Target findTargetWithExceptionIfNotFound(final String targetId) { - return targetManagement.getByControllerId(targetId) - .orElseThrow(() -> new EntityNotFoundException(Target.class, targetId)); - } - private R getNullIfEmpty(final T object, final Function extractMethod) { return object == null ? null : extractMethod.apply(object); } diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtSoftwareModuleMapper.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtSoftwareModuleMapper.java index 36a5851c4..5e7194729 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtSoftwareModuleMapper.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtSoftwareModuleMapper.java @@ -20,6 +20,9 @@ import java.util.stream.Collectors; import jakarta.validation.ValidationException; +import org.eclipse.hawkbit.artifact.urlresolver.ArtifactUrl; +import org.eclipse.hawkbit.artifact.urlresolver.ArtifactUrlResolver; +import org.eclipse.hawkbit.artifact.urlresolver.ArtifactUrlResolver.DownloadDescriptor; import org.eclipse.hawkbit.mgmt.json.model.artifact.MgmtArtifact; import org.eclipse.hawkbit.mgmt.json.model.artifact.MgmtArtifactHash; import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModule; @@ -33,10 +36,6 @@ import org.eclipse.hawkbit.mgmt.rest.resource.MgmtSoftwareModuleResource; import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; import org.eclipse.hawkbit.repository.SystemManagement; -import org.eclipse.hawkbit.repository.artifact.urlhandler.ApiType; -import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrl; -import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrlHandler; -import org.eclipse.hawkbit.repository.artifact.urlhandler.URLPlaceholder; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.SoftwareModule; @@ -157,13 +156,13 @@ public final class MgmtSoftwareModuleMapper { } public static void addLinks(final Artifact artifact, final MgmtArtifact response, - final ArtifactUrlHandler artifactUrlHandler, final SystemManagement systemManagement) { + final ArtifactUrlResolver artifactUrlHandler, final SystemManagement systemManagement) { final List urls = artifactUrlHandler.getUrls( - new URLPlaceholder(systemManagement.getTenantMetadata().getTenant(), - systemManagement.getTenantMetadata().getId(), null, null, - new URLPlaceholder.SoftwareData(artifact.getSoftwareModule().getId(), artifact.getFilename(), - artifact.getId(), artifact.getSha1Hash())), ApiType.MGMT, null); - urls.forEach(entry -> response.add(Link.of(entry.getRef()).withRel(entry.getRel()).expand())); + new DownloadDescriptor( + systemManagement.getTenantMetadata().getTenant(), null, + artifact.getSoftwareModule().getId(), artifact.getFilename(), artifact.getSha1Hash()), + ArtifactUrlResolver.ApiType.MGMT, null); + urls.forEach(entry -> response.add(Link.of(entry.ref()).withRel(entry.rel()).expand())); } private SoftwareModuleManagement.Create fromRequest( diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtTargetMapper.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtTargetMapper.java index 889417825..5894cde84 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtTargetMapper.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtTargetMapper.java @@ -331,9 +331,9 @@ public final class MgmtTargetMapper { if (pollStatus != null) { final MgmtPollStatus pollStatusRest = new MgmtPollStatus(); pollStatusRest.setLastRequestAt( - Date.from(pollStatus.getLastPollDate().atZone(ZoneId.systemDefault()).toInstant()).getTime()); + Date.from(pollStatus.lastPollDate().atZone(ZoneId.systemDefault()).toInstant()).getTime()); pollStatusRest.setNextExpectedRequestAt( - Date.from(pollStatus.getNextPollDate().atZone(ZoneId.systemDefault()).toInstant()).getTime()); + Date.from(pollStatus.nextPollDate().atZone(ZoneId.systemDefault()).toInstant()).getTime()); pollStatusRest.setOverdue(pollStatus.isOverdue()); targetRest.setPollStatus(pollStatusRest); } diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResourceTest.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResourceTest.java index 05a3162f3..39e951e91 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResourceTest.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResourceTest.java @@ -10,6 +10,7 @@ package org.eclipse.hawkbit.mgmt.rest.resource; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.hasSize; @@ -858,7 +859,7 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe .version("anotherVersion").requiredMigrationStep(true).build()); // load also lazy stuff - set = distributionSetManagement.getWithDetails(set.getId()).get(); + set = distributionSetManagement.getWithDetails(set.getId()); assertThat(distributionSetManagement.findAll(PAGE)).hasSize(1); @@ -943,11 +944,11 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe testdataFactory.generateDistributionSet("three", "three", standardDsType, List.of(os, jvm, ah), true)); final DistributionSet one = distributionSetManagement - .getWithDetails(distributionSetManagement.findByRsql("name==one", PAGE).getContent().get(0).getId()).orElseThrow(); + .getWithDetails(distributionSetManagement.findByRsql("name==one", PAGE).getContent().get(0).getId()); final DistributionSet two = distributionSetManagement - .getWithDetails(distributionSetManagement.findByRsql("name==two", PAGE).getContent().get(0).getId()).orElseThrow(); + .getWithDetails(distributionSetManagement.findByRsql("name==two", PAGE).getContent().get(0).getId()); final DistributionSet three = distributionSetManagement - .getWithDetails(distributionSetManagement.findByRsql("name==three", PAGE).getContent().get(0).getId()).orElseThrow(); + .getWithDetails(distributionSetManagement.findByRsql("name==three", PAGE).getContent().get(0).getId()); assertThat((Object) JsonPath.compile("[0]_links.self.href").read(mvcResult.getResponse().getContentAsString())) .hasToString("http://localhost/rest/v1/distributionsets/" + one.getId()); @@ -1702,11 +1703,11 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe assertThat(targetFilterQueryManagement.find(targetFilterQuery.getId()).get().getAutoAssignDistributionSet()) .isNull(); - assertThat(rolloutManagement.find(rollout.getId()).get().getStatus()).isIn(RolloutStatus.STOPPING, + assertThat(rolloutManagement.get(rollout.getId()).getStatus()).isIn(RolloutStatus.STOPPING, RolloutStatus.STOPPED); //then enforce executor to stop the rollout and check rolloutHandler.handleAll(); - assertThat(rolloutManagement.find(rollout.getId()).get().getStatus()).isIn(RolloutStatus.STOPPED); + assertThat(rolloutManagement.get(rollout.getId()).getStatus()).isIn(RolloutStatus.STOPPED); for (final Target target : targets) { assertThat(targetManagement.find(target.getId()).get().getUpdateStatus()) @@ -1735,17 +1736,16 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe .content(jsonObject.toString()).contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()); - assertThat(targetFilterQueryManagement.find(targetFilterQuery.getId()).get().getAutoAssignDistributionSet()) - .isNull(); - assertThat(rolloutManagement.find(rollout.getId()).get().getStatus()).isIn(RolloutStatus.DELETING, - RolloutStatus.DELETED); + assertThat(targetFilterQueryManagement.find(targetFilterQuery.getId()).get().getAutoAssignDistributionSet()).isNull(); + final Long rolloutId = rollout.getId(); + assertThat(rolloutManagement.get(rolloutId).getStatus()).isIn(RolloutStatus.DELETING, RolloutStatus.DELETED); //then enforce executor to stop the rollout and check rolloutHandler.handleAll(); // assert rollout is deleted - assertThat(rolloutManagement.find(rollout.getId())).isEmpty(); + assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(() -> rolloutManagement.get(rolloutId)); for (final Target target : targets) { - assertThat(targetManagement.find(target.getId()).get().getUpdateStatus()) + assertThat(targetManagement.get(target.getId()).getUpdateStatus()) .isEqualTo(TargetUpdateStatus.IN_SYNC); assertThat(deploymentManagement.findActionsByTarget(target.getControllerId(), PageRequest.of(0, 100)) .getNumberOfElements()).isEqualTo(1); @@ -1769,11 +1769,10 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe .content(jsonObject.toString()).contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()); - assertThat(rolloutManagement.find(rollout.getId()).get().getStatus()).isIn(RolloutStatus.RUNNING); + assertThat(rolloutManagement.get(rollout.getId()).getStatus()).isIn(RolloutStatus.RUNNING); for (final Target target : targets) { - assertThat(targetManagement.find(target.getId()).get().getUpdateStatus()) - .isEqualTo(TargetUpdateStatus.PENDING); + assertThat(targetManagement.get(target.getId()).getUpdateStatus()).isEqualTo(TargetUpdateStatus.PENDING); assertThat(deploymentManagement.findActionsByTarget(target.getControllerId(), PageRequest.of(0, 100)) .getNumberOfElements()).isEqualTo(1); assertThat(deploymentManagement.findActionsByTarget(target.getControllerId(), PageRequest.of(0, 100)) diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResourceTest.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResourceTest.java index e487b05c4..1ce1068bd 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResourceTest.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResourceTest.java @@ -30,13 +30,13 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.NoSuchElementException; -import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.stream.Stream; import org.awaitility.Awaitility; import org.awaitility.core.ConditionFactory; import org.eclipse.hawkbit.exception.SpServerError; +import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutResponseBody; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; import org.eclipse.hawkbit.mgmt.rest.resource.mapper.MgmtRestModelMapper; import org.eclipse.hawkbit.repository.DistributionSetManagement; @@ -74,6 +74,7 @@ import org.springframework.data.domain.Sort.Direction; import org.springframework.hateoas.MediaTypes; import org.springframework.http.MediaType; import org.springframework.test.context.TestPropertySource; +import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.ResultMatcher; /** @@ -238,9 +239,10 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { final List allTargets = new ArrayList<>(successTargets); allTargets.addAll(failedTargets); - postRollout("rolloutToBeRetried", 1, dsA.getId(), "id==retryRolloutTarget*", 10, Action.ActionType.FORCED); + final long rolloutToBeRetriedId = postRollout("rolloutToBeRetried", 1, dsA.getId(), "id==retryRolloutTarget*", 10, + Action.ActionType.FORCED); - Rollout rollout = rolloutManagement.getByName("rolloutToBeRetried").orElseThrow(); + Rollout rollout = rolloutManagement.get(rolloutToBeRetriedId); // no scheduler so invoke here rolloutHandler.handleAll(); @@ -265,13 +267,18 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { } } - //retry rollout - mvc.perform(post("/rest/v1/rollouts/{rolloutId}/retry", rollout.getId())) + // retry rollout + final MvcResult result = mvc.perform(post("/rest/v1/rollouts/{rolloutId}/retry", rollout.getId())) .andDo(MockMvcResultPrinter.print()) - .andExpect(status().is(201)); + .andExpect(status().is(201)) + .andReturn(); + final long rolloutRetryId = OBJECT_MAPPER + .readerFor(MgmtRolloutResponseBody.class) + . readValue(result.getResponse().getContentAsString()) + .getId(); //search for _retried suffix - Rollout retriedRollout = rolloutManagement.getByName(rollout.getName() + "_retry").orElseThrow(); + Rollout retriedRollout = rolloutManagement.get(rolloutRetryId); //assert 4 targets involved rolloutHandler.handleAll(); @@ -303,8 +310,9 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { void retryNotFinishedRolloutShouldNotBeAllowed() throws Exception { final DistributionSet dsA = testdataFactory.createDistributionSet(""); testdataFactory.createTargets("retryRolloutTarget-", 10); - postRollout("rolloutToBeRetried", 1, dsA.getId(), "id==retryRolloutTarget*", 10, Action.ActionType.FORCED); - Rollout rollout = rolloutManagement.getByName("rolloutToBeRetried").orElseThrow(); + final long rolloutToBeRetried = postRollout("rolloutToBeRetried", 1, dsA.getId(), "id==retryRolloutTarget*", 10, + Action.ActionType.FORCED); + Rollout rollout = rolloutManagement.get(rolloutToBeRetried); // no scheduler so invoke here rolloutHandler.handleAll(); rolloutManagement.start(rollout.getId()); @@ -1072,7 +1080,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { final DistributionSet dsA = testdataFactory.createDistributionSetLocked(""); // create rollout including the created targets with prefix 'rollout' - final Rollout rollout1 = createRollout("rollout1", 4, dsA, "controllerId==rollout*",false); + final Rollout rollout1 = createRollout("rollout1", 4, dsA, "controllerId==rollout*", false); final Rollout rollout2 = createRollout("rollout2", 1, dsA, "controllerId==rollout*", false); rolloutManagement.start(rollout1.getId()); @@ -1946,7 +1954,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { private void awaitRunningState(final Long rolloutId) { awaitRollout().until(() -> SecurityContextSwitch - .callAsPrivileged(() -> rolloutManagement.find(rolloutId).orElseThrow(NoSuchElementException::new)) + .callAsPrivileged(() -> rolloutManagement.get(rolloutId)) .getStatus().equals(RolloutStatus.RUNNING)); } @@ -1966,22 +1974,21 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { } private void assertStatusIs(final Rollout rollout, final RolloutStatus expected) { - final Optional updatedRollout = rolloutManagement.find(rollout.getId()); - assertThat(updatedRollout).get().extracting(Rollout::getStatus).isEqualTo(expected); + assertThat(rolloutManagement.get(rollout.getId()).getStatus()).isEqualTo(expected); } - private void postRollout(final String name, final int groupSize, final Long distributionSetId, + private long postRollout(final String name, final int groupSize, final Long distributionSetId, final String targetFilterQuery, final int targets, final Action.ActionType type) throws Exception { - postRollout(name, groupSize, distributionSetId, targetFilterQuery, targets, type, null, null); + return postRollout(name, groupSize, distributionSetId, targetFilterQuery, targets, type, null, null); } - private void postRollout(final String name, final int groupSize, final Long distributionSetId, + private long postRollout(final String name, final int groupSize, final Long distributionSetId, final String targetFilterQuery, final int targets, final Action.ActionType type, final Long startTime, final Long forceTime) throws Exception { - postRollout(name, groupSize, distributionSetId, targetFilterQuery, targets, type, startTime, forceTime, false, null, 0); + return postRollout(name, groupSize, distributionSetId, targetFilterQuery, targets, type, startTime, forceTime, false, null, 0); } - private void postRollout(final String name, final int groupSize, final Long distributionSetId, + private long postRollout(final String name, final int groupSize, final Long distributionSetId, final String targetFilterQuery, final int targets, final Action.ActionType type, final Long startTime, final Long forceTime, boolean isDynamic, String dynamicGroupSuffix, int dynamicGroupTargetsCount) throws Exception { final String actionType = MgmtRestModelMapper.convertActionType(type).getName(); @@ -1989,7 +1996,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { new RolloutGroupConditionBuilder().withDefaults().build(), null, actionType, null, startTime, forceTime, null, isDynamic, dynamicGroupSuffix, dynamicGroupTargetsCount); - mvc.perform(post("/rest/v1/rollouts").content(rollout).contentType(MediaType.APPLICATION_JSON) + final MvcResult result = mvc.perform(post("/rest/v1/rollouts").content(rollout).contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isCreated()) @@ -2004,10 +2011,8 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { .andExpect(jsonPath("$.lastModifiedBy", equalTo("bumlux"))) .andExpect(jsonPath("$.lastModifiedAt", not(equalTo(0)))) .andExpect(jsonPath("$.totalTargets", equalTo(targets))) - .andExpect(startTime != null ? jsonPath("$.startAt", equalTo(startTime.intValue())) - : jsonPath("$.startAt").doesNotExist()) - .andExpect(forceTime != null ? jsonPath("$.forcetime", equalTo(forceTime.intValue())) - : jsonPath("$.forcetime", equalTo(0))) + .andExpect(startTime != null ? jsonPath("$.startAt", equalTo(startTime.intValue())) : jsonPath("$.startAt").doesNotExist()) + .andExpect(forceTime != null ? jsonPath("$.forcetime", equalTo(forceTime.intValue())) : jsonPath("$.forcetime", equalTo(0))) .andExpect(jsonPath("$.totalTargetsPerStatus.running", equalTo(0))) .andExpect(jsonPath("$.totalTargetsPerStatus.notstarted", equalTo(targets))) .andExpect(jsonPath("$.totalTargetsPerStatus.scheduled", equalTo(0))) @@ -2019,8 +2024,12 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { .andExpect(jsonPath("$._links.pause.href", allOf(startsWith(HREF_ROLLOUT_PREFIX), endsWith("/pause")))) .andExpect(jsonPath("$.dynamic", equalTo(isDynamic))) .andExpect(jsonPath("$._links.resume.href", allOf(startsWith(HREF_ROLLOUT_PREFIX), endsWith("/resume")))) - .andExpect(jsonPath( - "$._links.groups.href", allOf(startsWith(HREF_ROLLOUT_PREFIX), containsString("/deploygroups")))); + .andExpect(jsonPath("$._links.groups.href", allOf(startsWith(HREF_ROLLOUT_PREFIX), containsString("/deploygroups")))) + .andReturn(); + return OBJECT_MAPPER + .readerFor(MgmtRolloutResponseBody.class) + . readValue(result.getResponse().getContentAsString()) + .getId(); } private Rollout createRollout( @@ -2039,7 +2048,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { // Run here, because Scheduler is disabled during tests rolloutHandler.handleAll(); - return rolloutManagement.find(rollout.getId()).orElseThrow(NoSuchElementException::new); + return rolloutManagement.get(rollout.getId()); } private void triggerNextGroupAndExpect(final Rollout rollout, final ResultMatcher expect) throws Exception { diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java index 032885470..832952060 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java @@ -31,13 +31,16 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import java.io.ByteArrayInputStream; import java.io.IOException; -import java.io.InputStream; import java.util.Collections; import java.util.List; import java.util.Optional; import com.jayway.jsonpath.JsonPath; import org.apache.commons.io.IOUtils; +import org.eclipse.hawkbit.artifact.exception.ArtifactBinaryNotFoundException; +import org.eclipse.hawkbit.artifact.exception.FileSizeQuotaExceededException; +import org.eclipse.hawkbit.artifact.exception.StorageQuotaExceededException; +import org.eclipse.hawkbit.artifact.model.ArtifactStream; import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.mgmt.json.model.artifact.MgmtArtifact; import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModule; @@ -47,13 +50,9 @@ import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; import org.eclipse.hawkbit.mgmt.rest.resource.util.ResourceUtility; import org.eclipse.hawkbit.repository.Constants; import org.eclipse.hawkbit.repository.SoftwareModuleManagement; -import org.eclipse.hawkbit.repository.artifact.exception.ArtifactBinaryNotFoundException; -import org.eclipse.hawkbit.repository.artifact.model.DbArtifact; -import org.eclipse.hawkbit.repository.artifact.model.DbArtifactHash; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; -import org.eclipse.hawkbit.repository.exception.FileSizeQuotaExceededException; -import org.eclipse.hawkbit.repository.exception.StorageQuotaExceededException; +import org.eclipse.hawkbit.repository.jpa.repository.LocalArtifactRepository; import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.ArtifactUpload; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -94,6 +93,8 @@ import org.springframework.web.bind.annotation.RestController; "hawkbit.server.security.dos.maxArtifactStorage=500000" }) class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTest { + private LocalArtifactRepository localArtifactRepository; + @BeforeEach public void assertPreparationOfRepo() { assertThat(softwareModuleManagement.findAll(PAGE)).as("no softwaremodule should be founded").isEmpty(); @@ -145,7 +146,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes final byte[] random = randomBytes(5); - artifactManagement.create(new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file1", false, 0)); + artifactManagement.create(new ArtifactUpload(new ByteArrayInputStream(random), null, 0, null, sm.getId(), "file1", false)); mvc.perform(get(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/artifacts", sm.getId()) .param("representation", MgmtRepresentationMode.FULL.toString()) @@ -515,8 +516,10 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes .andExpect(jsonPath("$.providedFilename", equalTo("customFilename"))) .andExpect(status().isCreated()) .andDo(result -> { - final MgmtArtifact mgmtArtifact = OBJECT_MAPPER.readerFor(MgmtArtifact.class).readValue(result.getResponse().getContentAsString()); - assertThat(artifactManagement.loadArtifactBinary(mgmtArtifact.getHashes().getSha1(), sm.getId(), sm.isEncrypted())).isNotNull(); + final MgmtArtifact mgmtArtifact = OBJECT_MAPPER.readerFor(MgmtArtifact.class) + .readValue(result.getResponse().getContentAsString()); + assertThat(artifactManagement.getArtifactStream(mgmtArtifact.getHashes().getSha1(), sm.getId(), + sm.isEncrypted())).isNotNull(); }); } @@ -687,9 +690,9 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes final byte[] random = randomBytes(artifactSize); final Artifact artifact = artifactManagement.create( - new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file1", false, artifactSize)); + new ArtifactUpload(new ByteArrayInputStream(random), null, artifactSize, null, sm.getId(), "file1", false)); final Artifact artifact2 = artifactManagement.create( - new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file2", false, artifactSize)); + new ArtifactUpload(new ByteArrayInputStream(random), null, artifactSize, null, sm.getId(), "file2", false)); downloadAndVerify(sm, random, artifact); downloadAndVerify(sm, random, artifact2); @@ -707,7 +710,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes final byte[] random = randomBytes(artifactSize); final Artifact artifact = artifactManagement - .create(new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file1", false, artifactSize)); + .create(new ArtifactUpload(new ByteArrayInputStream(random), null, artifactSize, null, sm.getId(), "file1", false)); // perform test mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts/{artId}", sm.getId(), artifact.getId()) @@ -722,11 +725,9 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes .andExpect(jsonPath("$.hashes.sha256", equalTo(artifact.getSha256Hash()))) .andExpect(jsonPath("$.providedFilename", equalTo("file1"))) .andExpect(jsonPath("$._links.download.href", - equalTo("http://localhost/rest/v1/softwaremodules/%s/artifacts/%s/download" - .formatted(sm.getId(), artifact.getId())))) + equalTo("http://localhost/rest/v1/softwaremodules/%s/artifacts/%s/download".formatted(sm.getId(), artifact.getId())))) .andExpect(jsonPath("$._links.self.href", - equalTo("http://localhost/rest/v1/softwaremodules/%s/artifacts/%s".formatted(sm.getId(), - artifact.getId())))); + equalTo("http://localhost/rest/v1/softwaremodules/%s/artifacts/%s".formatted(sm.getId(), artifact.getId())))); } /** @@ -742,7 +743,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes final byte[] random = randomBytes(artifactSize); final Artifact artifact = artifactManagement - .create(new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file1", false, artifactSize)); + .create(new ArtifactUpload(new ByteArrayInputStream(random), null, artifactSize, null, sm.getId(), "file1", false)); // perform test mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts/{artId}", sm.getId(), artifact.getId()) @@ -806,9 +807,9 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes final byte[] random = randomBytes(artifactSize); final Artifact artifact = artifactManagement.create( - new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file1", false, artifactSize)); + new ArtifactUpload(new ByteArrayInputStream(random), null, artifactSize, null, sm.getId(), "file1", false)); final Artifact artifact2 = artifactManagement.create( - new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file2", false, artifactSize)); + new ArtifactUpload(new ByteArrayInputStream(random), null, artifactSize, null, sm.getId(), "file2", false)); mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).accept(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print()) @@ -844,9 +845,9 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes final byte[] random = randomBytes(artifactSize); final Artifact artifact = artifactManagement - .create(new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file1", false, artifactSize)); + .create(new ArtifactUpload(new ByteArrayInputStream(random), null, artifactSize, null, sm.getId(), "file1", false)); final Artifact artifact2 = artifactManagement - .create(new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file2", false, artifactSize)); + .create(new ArtifactUpload(new ByteArrayInputStream(random), null, artifactSize, null, sm.getId(), "file2", false)); mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()) .param("representation", MgmtRepresentationMode.FULL.toString()) @@ -910,7 +911,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes // SM does not exist artifactManagement - .create(new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file1", false, artifactSize)); + .create(new ArtifactUpload(new ByteArrayInputStream(random), null, artifactSize, null, sm.getId(), "file1", false)); mvc.perform(get("/rest/v1/softwaremodules/1234567890/artifacts")) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isNotFound()); @@ -954,10 +955,10 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes final long moduleId = sm.getId(); final byte[] random = randomBytes(artifactSize); final Artifact artifact = artifactManagement.create( - new ArtifactUpload(new ByteArrayInputStream(random), moduleId, "file1", false, artifactSize)); + new ArtifactUpload(new ByteArrayInputStream(random), null, artifactSize, null, moduleId, "file1", false)); final byte[] random2 = randomBytes(artifactSize); artifactManagement.create( - new ArtifactUpload(new ByteArrayInputStream(random2), moduleId, "file2", false, artifactSize)); + new ArtifactUpload(new ByteArrayInputStream(random2), null, artifactSize, null, moduleId, "file2", false)); // check repo before delete assertThat(softwareModuleManagement.findAll(PAGE)).hasSize(1); @@ -974,7 +975,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes final boolean encrypted = sm.isEncrypted(); final String sha1Hash = artifact.getSha1Hash(); assertThatExceptionOfType(ArtifactBinaryNotFoundException.class) - .isThrownBy(() -> artifactManagement.loadArtifactBinary(sha1Hash, moduleId, encrypted)); + .isThrownBy(() -> artifactManagement.getArtifactStream(sha1Hash, moduleId, encrypted)); assertThat(softwareModuleManagement.find(moduleId).get().getArtifacts()) .as("After delete artifact should available for marked as deleted sm's").hasSize(1); } @@ -1344,14 +1345,14 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes final byte[] random = randomBytes(artifactSize); final Artifact artifact = artifactManagement.create( - new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file1", false, artifactSize)); + new ArtifactUpload(new ByteArrayInputStream(random), null, artifactSize, null, sm.getId(), "file1", false)); assertThat(softwareModuleManagement.findAll(PAGE)).as("Softwaremoudle size is wrong").hasSize(1); final Long smId = sm.getId(); final String sha1Hash = artifact.getSha1Hash(); final boolean encrypted = sm.isEncrypted(); - assertThat(artifactManagement.loadArtifactBinary(sha1Hash, smId, encrypted)).isNotNull(); + assertThat(artifactManagement.getArtifactStream(sha1Hash, smId, encrypted)).isNotNull(); mvc.perform(delete("/rest/v1/softwaremodules/{smId}", sm.getId())) .andDo(MockMvcResultPrinter.print()) @@ -1359,7 +1360,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes assertThat(softwareModuleManagement.findAll(PAGE)).as("After delete no softwarmodule should be available").isEmpty(); assertThatExceptionOfType(EntityNotFoundException.class) // sm doesn't exists - .isThrownBy(() -> artifactManagement.loadArtifactBinary(sha1Hash, smId, encrypted)); + .isThrownBy(() -> artifactManagement.getArtifactStream(sha1Hash, smId, encrypted)); } /** @@ -1376,12 +1377,12 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes final Long appTypeSmId = appTypeSm.getId(); final Artifact artifact = artifactManagement.create( - new ArtifactUpload(new ByteArrayInputStream(random), appTypeSmId, "file1", false, artifactSize)); + new ArtifactUpload(new ByteArrayInputStream(random), null, artifactSize, null, appTypeSmId, "file1", false)); assertThat(softwareModuleManagement.count()).isEqualTo(3); final String sha1Hash = artifact.getSha1Hash(); final boolean encrypted = appTypeSm.isEncrypted(); - assertThat(artifactManagement.loadArtifactBinary(sha1Hash, appTypeSmId, encrypted)).isNotNull(); + assertThat(artifactManagement.getArtifactStream(sha1Hash, appTypeSmId, encrypted)).isNotNull(); mvc.perform(get("/rest/v1/softwaremodules/{smId}", appTypeSmId)) .andDo(MockMvcResultPrinter.print()) @@ -1399,7 +1400,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes assertThat(softwareModuleManagement.count()).isEqualTo(2); assertThatExceptionOfType(ArtifactBinaryNotFoundException.class) - .isThrownBy(() -> artifactManagement.loadArtifactBinary(sha1Hash, appTypeSmId, encrypted)); + .isThrownBy(() -> artifactManagement.getArtifactStream(sha1Hash, appTypeSmId, encrypted)); } /** @@ -1526,19 +1527,13 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes } private void assertArtifact(final SoftwareModule sm, final byte[] random) throws IOException { - final DbArtifact artifact = artifactManagement - .loadArtifactBinary( - softwareModuleManagement.find( - sm.getId()).orElseThrow().getArtifacts().get(0).getSha1Hash(), sm.getId(), sm.isEncrypted()); // binary - try (final InputStream fileInputStream = artifact.getFileInputStream()) { - assertTrue(IOUtils.contentEquals(new ByteArrayInputStream(random), fileInputStream), - "Wrong artifact content"); + try (final ArtifactStream artifact = artifactManagement.getArtifactStream( + softwareModuleManagement.find(sm.getId()).orElseThrow().getArtifacts().get(0).getSha1Hash(), sm.getId(), sm.isEncrypted())) { + assertTrue(IOUtils.contentEquals(new ByteArrayInputStream(random), artifact), "Wrong artifact content"); + // hashes + assertThat(artifact.getSha1Hash()).as("Wrong sha1 hash").isEqualTo(HashGeneratorUtils.generateSHA1(random)); } - - // hashes - final DbArtifactHash hash = artifact.getHashes(); - assertThat(hash.getSha1()).as("Wrong sha1 hash").isEqualTo(HashGeneratorUtils.generateSHA1(random)); // metadata assertThat(softwareModuleManagement.find(sm.getId()).orElseThrow().getArtifacts().get(0).getFilename()) .as("wrong metadata of the filename").isEqualTo("origFilename"); diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java index eae80ef15..145e3c3f3 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java @@ -538,8 +538,8 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { // action has not been cancelled confirmed from controller, so DS // remains assigned until // confirmation - assertThat(deploymentManagement.getAssignedDistributionSet(tA.getControllerId())).isPresent(); - assertThat(deploymentManagement.getInstalledDistributionSet(tA.getControllerId())).isNotPresent(); + assertThat(deploymentManagement.findAssignedDistributionSet(tA.getControllerId())).isPresent(); + assertThat(deploymentManagement.findInstalledDistributionSet(tA.getControllerId())).isNotPresent(); } /** @@ -619,7 +619,7 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { mvc.perform(delete(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownControllerId)) .andExpect(status().isOk()); - assertThat(targetManagement.getByControllerId(knownControllerId)).isNotPresent(); + assertThat(targetManagement.findByControllerId(knownControllerId)).isNotPresent(); } /** @@ -667,9 +667,10 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { .andExpect(jsonPath("$.description", equalTo(knownNewDescription))) .andExpect(jsonPath("$.name", equalTo(knownNameNotModify))); - final Target findTargetByControllerID = targetManagement.getByControllerId(knownControllerId).get(); - assertThat(findTargetByControllerID.getDescription()).isEqualTo(knownNewDescription); - assertThat(findTargetByControllerID.getName()).isEqualTo(knownNameNotModify); + assertThat(targetManagement.getByControllerId(knownControllerId)).satisfies(findTargetByControllerID -> { + assertThat(findTargetByControllerID.getDescription()).isEqualTo(knownNewDescription); + assertThat(findTargetByControllerID.getName()).isEqualTo(knownNameNotModify); + }); } /** @@ -691,8 +692,7 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { .andDo(MockMvcResultPrinter.print()) .andExpect(status().isBadRequest()); - final Target findTargetByControllerID = targetManagement.getByControllerId(knownControllerId).get(); - assertThat(findTargetByControllerID.getDescription()).isEqualTo("old description"); + assertThat(targetManagement.getByControllerId(knownControllerId).getDescription()).isEqualTo("old description"); } /** @@ -716,9 +716,10 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { .andExpect(jsonPath("$.securityToken", equalTo(knownNewToken))) .andExpect(jsonPath("$.name", equalTo(knownNameNotModify))); - final Target findTargetByControllerID = targetManagement.getByControllerId(knownControllerId).get(); - assertThat(findTargetByControllerID.getSecurityToken()).isEqualTo(knownNewToken); - assertThat(findTargetByControllerID.getName()).isEqualTo(knownNameNotModify); + assertThat(targetManagement.getByControllerId(knownControllerId)).satisfies(findTargetByControllerID -> { + assertThat(findTargetByControllerID.getSecurityToken()).isEqualTo(knownNewToken); + assertThat(findTargetByControllerID.getName()).isEqualTo(knownNameNotModify); + }); } /** @@ -742,9 +743,10 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { .andExpect(jsonPath("$.address", equalTo(knownNewAddress))) .andExpect(jsonPath("$.name", equalTo(knownNameNotModify))); - final Target findTargetByControllerID = targetManagement.getByControllerId(knownControllerId).get(); - assertThat(findTargetByControllerID.getAddress()).hasToString(knownNewAddress); - assertThat(findTargetByControllerID.getName()).isEqualTo(knownNameNotModify); + assertThat(targetManagement.getByControllerId(knownControllerId)).satisfies(findTargetByControllerID -> { + assertThat(findTargetByControllerID.getAddress()).hasToString(knownNewAddress); + assertThat(findTargetByControllerID.getName()).isEqualTo(knownNameNotModify); + }); } /** @@ -1027,7 +1029,7 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { .andExpect(jsonPath("[0].controllerId", equalTo(randomString))) .andExpect(jsonPath("[0].name", equalTo(expectedTargetName))); - assertThat(targetManagement.getByControllerId(randomString).get().getName()).isEqualTo(expectedTargetName); + assertThat(targetManagement.getByControllerId(randomString).getName()).isEqualTo(expectedTargetName); } /** @@ -1638,8 +1640,8 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { .andExpect(jsonPath("total", equalTo(1))); implicitLock(set); - assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).get()).isEqualTo(set); - target = targetManagement.getByControllerId(target.getControllerId()).get(); + assertThat(deploymentManagement.findAssignedDistributionSet(target.getControllerId()).get()).isEqualTo(set); + target = targetManagement.getByControllerId(target.getControllerId()); // repeating DS assignment leads again to OK mvc.perform(post(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + target.getControllerId() + "/assignedDS") @@ -1651,7 +1653,7 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { .andExpect(jsonPath("total", equalTo(1))); // ...but does not change the target - assertThat(targetManagement.getByControllerId(target.getControllerId()).get()).isEqualTo(target); + assertThat(targetManagement.findByControllerId(target.getControllerId()).get()).isEqualTo(target); } /** @@ -1683,7 +1685,7 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { .andExpect(jsonPath("total", equalTo(1))); implicitLock(set); - assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).get()).isEqualTo(set); + assertThat(deploymentManagement.findAssignedDistributionSet(target.getControllerId()).get()).isEqualTo(set); assertThat( actionRepository @@ -1716,7 +1718,7 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { .andExpect(jsonPath("total", equalTo(1))); implicitLock(set); - assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).get()).isEqualTo(set); + assertThat(deploymentManagement.findAssignedDistributionSet(target.getControllerId()).get()).isEqualTo(set); final Slice actions = deploymentManagement.findActionsByTarget("targetExist", PageRequest.of(0, 100)); assertThat(actions).isNotEmpty().filteredOn(a -> a.getDistributionSet().equals(set)) .extracting(Action::getActionType).containsOnly(ActionType.DOWNLOAD_ONLY); @@ -1741,9 +1743,9 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { .andExpect(jsonPath("total", equalTo(1))); implicitLock(set); - assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).get()).isEqualTo(set); - assertThat(deploymentManagement.getInstalledDistributionSet(target.getControllerId()).get()).isEqualTo(set); - target = targetManagement.getByControllerId(target.getControllerId()).get(); + assertThat(deploymentManagement.findAssignedDistributionSet(target.getControllerId()).get()).isEqualTo(set); + assertThat(deploymentManagement.findInstalledDistributionSet(target.getControllerId()).get()).isEqualTo(set); + target = targetManagement.getByControllerId(target.getControllerId()); assertThat(target.getUpdateStatus()).isEqualTo(TargetUpdateStatus.IN_SYNC); // repeating DS assignment leads again to OK @@ -1757,7 +1759,7 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { .andExpect(jsonPath("total", equalTo(1))); // ...but does not change the target - assertThat(targetManagement.getByControllerId(target.getControllerId()).get()).isEqualTo(target); + assertThat(targetManagement.getByControllerId(target.getControllerId())).isEqualTo(target); } @Test @@ -1780,7 +1782,7 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { assertThat(findActiveActionsByTarget).hasSize(1); assertThat(findActiveActionsByTarget.get(0).getActionType()).isEqualTo(ActionType.TIMEFORCED); assertThat(findActiveActionsByTarget.get(0).getForcedTime()).isEqualTo(forceTime); - assertThat(deploymentManagement.getAssignedDistributionSet("fsdfsd").get()).isEqualTo(set); + assertThat(deploymentManagement.findAssignedDistributionSet("fsdfsd").get()).isEqualTo(set); } /** @@ -2038,7 +2040,7 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { knownControllerAttrs.put("b.2", "2"); testdataFactory.createTarget(knownTargetId); controllerManagement.updateControllerAttributes(knownTargetId, knownControllerAttrs, null); - assertThat(targetManagement.getByControllerId(knownTargetId).orElseThrow().isRequestControllerAttributes()).isFalse(); + assertThat(targetManagement.getByControllerId(knownTargetId).isRequestControllerAttributes()).isFalse(); verifyAttributeUpdateCanBeRequested(knownTargetId); verifyRequestAttributesAttributeIsOptional(knownTargetId); @@ -2539,8 +2541,7 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { .andExpect(jsonPath("[0].controllerId", equalTo("targetcontroller"))) .andExpect(jsonPath("[0].targetType", equalTo(targetTypes.get(0).getId().intValue()))); - assertThat(targetManagement.getByControllerId("targetcontroller").get().getTargetType().getId()) - .isEqualTo(targetTypes.get(0).getId()); + assertThat(targetManagement.getByControllerId("targetcontroller").getTargetType().getId()).isEqualTo(targetTypes.get(0).getId()); } /** @@ -2610,8 +2611,7 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { .andDo(MockMvcResultPrinter.print()) .andExpect(status().isOk()); - assertThat(targetManagement.getByControllerId(targetControllerId).get().getTargetType().getId()) - .isEqualTo(targetType.getId()); + assertThat(targetManagement.getByControllerId(targetControllerId).getTargetType().getId()).isEqualTo(targetType.getId()); } /** @@ -2669,7 +2669,7 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()); - assertThat(targetManagement.getByControllerId(targetControllerId).get().getTargetType()).isNull(); + assertThat(targetManagement.getByControllerId(targetControllerId).getTargetType()).isNull(); } @Test @@ -2873,12 +2873,11 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { } private Target assertTarget(final String controllerId, final String name, final String description) { - final Optional target1 = targetManagement.getByControllerId(controllerId); - assertThat(target1).isPresent(); - final Target t = target1.get(); - assertThat(t.getName()).isEqualTo(name); - assertThat(t.getDescription()).isEqualTo(description); - return t; + final Target target = targetManagement.getByControllerId(controllerId); + assertThat(target).isNotNull(); + assertThat(target.getName()).isEqualTo(name); + assertThat(target.getDescription()).isEqualTo(description); + return target; } private void getActions(final boolean withExternalRef) throws Exception { @@ -2986,7 +2985,7 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { .andDo(MockMvcResultPrinter.print()) .andExpect(status().isOk()); - assertThat(targetManagement.getByControllerId(knownTargetId).orElseThrow().isRequestControllerAttributes()).isTrue(); + assertThat(targetManagement.getByControllerId(knownTargetId).isRequestControllerAttributes()).isTrue(); } private void verifyRequestAttributesAttributeIsOptional(final String knownTargetId) throws Exception { @@ -3006,7 +3005,7 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { .andDo(MockMvcResultPrinter.print()) .andExpect(status().isBadRequest()); - assertThat(targetManagement.getByControllerId(knownTargetId).orElseThrow().isRequestControllerAttributes()).isTrue(); + assertThat(targetManagement.getByControllerId(knownTargetId).isRequestControllerAttributes()).isTrue(); } private String getCreateTargetsListJsonString(final String controllerId, final String name, final String description) { @@ -3048,7 +3047,7 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { // verify active action final Slice actionsByTarget = deploymentManagement.findActionsByTarget(tA.getControllerId(), PAGE); assertThat(actionsByTarget.getContent()).hasSize(1); - return targetManagement.getByControllerId(tA.getControllerId()).get(); + return targetManagement.getByControllerId(tA.getControllerId()); } private void setupTargetWithMetadata(final String knownControllerId, final String knownKey, final String knownValue) { diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTypeResourceTest.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTypeResourceTest.java index af47fcafc..5d1a086f6 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTypeResourceTest.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTypeResourceTest.java @@ -722,7 +722,7 @@ class MgmtTargetTypeResourceTest extends AbstractManagementApiIntegrationTest { for (int index = 0; index < size; index++) { String name = "TestTypePOST" + index; - final TargetType created = targetTypeManagement.getByName(name).get(); + final TargetType created = findTargetTypeByName(name); assertThat(JsonPath.compile("$[ ?(@.name=='" + name + "') ].id") .read(mvcResult.getResponse().getContentAsString()).toString()).contains(String.valueOf(created.getId())); diff --git a/hawkbit-mgmt/hawkbit-mgmt-starter/pom.xml b/hawkbit-mgmt/hawkbit-mgmt-starter/pom.xml index 8ce183e46..98ffca23e 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-starter/pom.xml +++ b/hawkbit-mgmt/hawkbit-mgmt-starter/pom.xml @@ -30,7 +30,7 @@ org.eclipse.hawkbit - hawkbit-artifact-repository-filesystem + hawkbit-artifact-fs ${project.version} diff --git a/hawkbit-monolith/hawkbit-update-server/src/main/resources/application.properties b/hawkbit-monolith/hawkbit-update-server/src/main/resources/application.properties index 231c7d905..ca483e525 100644 --- a/hawkbit-monolith/hawkbit-update-server/src/main/resources/application.properties +++ b/hawkbit-monolith/hawkbit-update-server/src/main/resources/application.properties @@ -39,7 +39,7 @@ hawkbit.server.ddi.security.authentication.gatewaytoken.enabled=false # Cache configuration, # disable expiration since monolith is expected to be used as an all-in-one hawkBit instance, # i.e. no microservices and 1 replica, then evict should do work -hawkbit.cache.global.ttl=0 +hawkbit.cache.ttl=0 # Optional events hawkbit.server.repository.publish-target-poll-event=false diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java index 6069b91d1..6e1d44040 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java @@ -14,13 +14,15 @@ import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; +import org.eclipse.hawkbit.artifact.exception.ArtifactUploadFailedException; +import org.eclipse.hawkbit.artifact.model.ArtifactStream; +import org.eclipse.hawkbit.artifact.model.StoredArtifactInfo; import org.eclipse.hawkbit.im.authentication.SpPermission; -import org.eclipse.hawkbit.repository.artifact.model.DbArtifact; import org.eclipse.hawkbit.im.authentication.SpringEvalExpressions; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; -import org.eclipse.hawkbit.repository.exception.InvalidMD5HashException; -import org.eclipse.hawkbit.repository.exception.InvalidSHA1HashException; +import org.eclipse.hawkbit.repository.exception.InvalidMd5HashException; +import org.eclipse.hawkbit.repository.exception.InvalidSha1HashException; import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.ArtifactUpload; import org.eclipse.hawkbit.repository.model.SoftwareModule; @@ -44,24 +46,24 @@ public interface ArtifactManagement extends PermissionSupport { * @return uploaded {@link Artifact} * @throws EntityNotFoundException if given software module does not exist * @throws EntityAlreadyExistsException if File with that name already exists in the Software Module - * @throws org.eclipse.hawkbit.repository.artifact.exception.ArtifactUploadFailedException if upload fails with internal server errors - * @throws InvalidMD5HashException if check against provided MD5 checksum failed - * @throws InvalidSHA1HashException if check against provided SHA1 checksum failed + * @throws ArtifactUploadFailedException if upload fails with internal server errors + * @throws InvalidMd5HashException if check against provided MD5 checksum failed + * @throws InvalidSha1HashException if check against provided SHA1 checksum failed * @throws ConstraintViolationException if {@link ArtifactUpload} contains invalid values */ @PreAuthorize(SpringEvalExpressions.HAS_CREATE_REPOSITORY) Artifact create(@NotNull @Valid ArtifactUpload artifactUpload); /** - * Loads {@link DbArtifact} from store for given {@link Artifact}. + * Loads {@link StoredArtifactInfo} from store for given {@link Artifact}. * * @param sha1Hash to search for * @param softwareModuleId software module id. * @param isEncrypted flag to indicate if artifact is encrypted. - * @return loaded {@link DbArtifact} + * @return loaded {@link StoredArtifactInfo} */ @PreAuthorize("hasAuthority('" + SpPermission.DOWNLOAD_REPOSITORY_ARTIFACT + "')" + " or " + SpringEvalExpressions.IS_CONTROLLER) - DbArtifact loadArtifactBinary(@NotEmpty String sha1Hash, long softwareModuleId, final boolean isEncrypted); + ArtifactStream getArtifactStream(@NotEmpty String sha1Hash, long softwareModuleId, final boolean isEncrypted); /** * Deletes {@link Artifact} based on given id. diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ConfirmationManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ConfirmationManagement.java index 7e195a559..4e2eb0de0 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ConfirmationManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ConfirmationManagement.java @@ -82,7 +82,7 @@ public interface ConfirmationManagement extends PermissionSupport { * @return instance of {@link AutoConfirmationStatus} wrapped in an {@link Optional}. Present if active and empty if disabled. */ @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY + " or " + SpringEvalExpressions.IS_CONTROLLER) - Optional getStatus(@NotEmpty String controllerId); + Optional findStatus(@NotEmpty String controllerId); /** * Find active actions in the {@link Action.Status#WAIT_FOR_CONFIRMATION} state for a specific target with a specified controllerId. diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java index 160d1b575..869e5015a 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java @@ -65,7 +65,7 @@ public interface ControllerManagement { * @return {@link SoftwareModule} identified by ID */ @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER) - Optional getSoftwareModule(long moduleId); + SoftwareModule getSoftwareModule(long moduleId); /** * Retrieves software module metadata where isTargetVisible. @@ -115,8 +115,7 @@ public interface ControllerManagement { Optional findActiveActionWithHighestWeight(@NotEmpty String controllerId); /** - * Retrieves active {@link Action}s with highest weight that are assigned to - * a {@link Target}. + * Retrieves active {@link Action}s with the highest weight that are assigned to a {@link Target}. * * @param controllerId identifies the target to retrieve the action from * @param maxActionCount max size of returned list @@ -182,7 +181,7 @@ public interface ControllerManagement { * @throws EntityNotFoundException if target with given ID does not exist */ @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER) - Optional getActionForDownloadByTargetAndSoftwareModule(@NotEmpty String controllerId, long moduleId); + Action getActionForDownloadByTargetAndSoftwareModule(@NotEmpty String controllerId, long moduleId); /** * Returns configured polling interval at which the controller polls hawkBit server. @@ -317,15 +316,6 @@ public interface ControllerManagement { @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER) void updateActionExternalRef(long actionId, @NotEmpty String externalRef); - /** - * Retrieves an {@link Action} using {@link Action#getExternalRef()} - * - * @param externalRef of the action. See {@link Action#getExternalRef()} - * @return {@link Action} or {@code null} if it does not exist - */ - @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER) - Optional getActionByExternalRef(@NotEmpty String externalRef); - /** * Delete a single target. * @@ -340,7 +330,7 @@ public interface ControllerManagement { * @param target the target the action is assigned to */ @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER) - Optional getInstalledActionByTarget(@NotNull Target target); + Optional findInstalledActionByTarget(@NotNull Target target); /** * Activate auto confirmation for a given controllerId diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java index 7a04c776e..c39e7f836 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java @@ -351,7 +351,7 @@ public interface DeploymentManagement extends PermissionSupport { * @throws EntityNotFoundException if target with given ID does not exist */ @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) - Optional getAssignedDistributionSet(@NotEmpty String controllerId); + Optional findAssignedDistributionSet(@NotEmpty String controllerId); /** * Returns {@link DistributionSet} that is installed on given {@link Target}. @@ -361,7 +361,7 @@ public interface DeploymentManagement extends PermissionSupport { * @throws EntityNotFoundException if target with given ID does not exist */ @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) - Optional getInstalledDistributionSet(@NotEmpty String controllerId); + Optional findInstalledDistributionSet(@NotEmpty String controllerId); /** * Deletes actions which match one of the given action status and which have not been modified since the given (absolute) time-stamp. diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java index 83aa21f05..9455620ff 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java @@ -66,7 +66,7 @@ public interface DistributionSetManagement * @return {@link DistributionSet} */ @PreAuthorize(HAS_READ_REPOSITORY) - Optional getWithDetails(long id); + T getWithDetails(long id); @PreAuthorize(HAS_READ_REPOSITORY) boolean shouldLockImplicitly(final DistributionSet distributionSet); @@ -169,7 +169,7 @@ public interface DistributionSetManagement * @return the page with the found {@link DistributionSet} */ @PreAuthorize(HAS_READ_REPOSITORY) - Optional findByNameAndVersion(@NotEmpty String distributionName, @NotEmpty String version); + T findByNameAndVersion(@NotEmpty String distributionName, @NotEmpty String version); /** * Retrieves {@link DistributionSet}s by filtering on the given parameters. diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTypeManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTypeManagement.java index b53488a4a..b625605e3 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTypeManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTypeManagement.java @@ -47,9 +47,6 @@ public interface DistributionSetTypeManagement @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) Optional findByKey(@NotEmpty String key); - @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) - Optional findByName(@NotEmpty String name); - /** * Assigns {@link DistributionSetType#getMandatoryModuleTypes()}. * diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutGroupManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutGroupManagement.java index ea28601cc..f6a571c16 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutGroupManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutGroupManagement.java @@ -55,7 +55,16 @@ public interface RolloutGroupManagement extends PermissionSupport { * @return the found {@link RolloutGroup} by its ID or {@code null} if it does not exist */ @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) - Optional get(long rolloutGroupId); + RolloutGroup get(long rolloutGroupId); + + /** + * Get {@link RolloutGroup} by id. + * + * @param rolloutGroupId rollout group id + * @return rolloutGroup with details of targets count for different statuses + */ + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) + RolloutGroup getWithDetailedStatus(long rolloutGroupId); /** * Retrieves a page of {@link RolloutGroup}s filtered by a given {@link Rollout} and an RSQL filter. @@ -120,15 +129,6 @@ public interface RolloutGroupManagement extends PermissionSupport { @PreAuthorize(HAS_READ_ROLLOUT_AND_READ_TARGET) Page findTargetsOfRolloutGroupByRsql(long rolloutGroupId, @NotNull String rsql, @NotNull Pageable pageable); - /** - * Get {@link RolloutGroup} by id. - * - * @param rolloutGroupId rollout group id - * @return rolloutGroup with details of targets count for different statuses - */ - @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) - Optional getWithDetailedStatus(long rolloutGroupId); - /** * Count targets of rollout group. * diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java index 9acac1e55..7410011dc 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java @@ -208,6 +208,15 @@ public interface RolloutManagement extends PermissionSupport { @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) List findActiveRollouts(); + /** + * Retrieves a specific rollout by its ID. Throws exception if not found. + * + * @param rolloutId the ID of the rollout to retrieve + * @return the found rollout or empty if rollout with given ID does not exist + */ + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) + Rollout get(long rolloutId); + /** * Retrieves a specific rollout by its ID. * @@ -217,15 +226,6 @@ public interface RolloutManagement extends PermissionSupport { @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) Optional find(long rolloutId); - /** - * Retrieves a specific rollout by its name. - * - * @param rolloutName the name of the rollout to retrieve - * @return the found rollout or empty if rollout with given ID does not exist - */ - @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) - Optional getByName(@NotEmpty String rolloutName); - /** * Get count of targets in different status in rollout. * @@ -233,7 +233,7 @@ public interface RolloutManagement extends PermissionSupport { * @return rollout details of targets count for different statuses */ @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) - Optional getWithDetailedStatus(long rolloutId); + Rollout getWithDetailedStatus(long rolloutId); /** * Checks if rollout with given ID exists. diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SizeConversionHelper.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SizeConversionHelper.java deleted file mode 100644 index eac5aa4c4..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SizeConversionHelper.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (c) 2019 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository; - -/** - * Helper class that provides simple conversion of byte values to readable - * strings - */ -public final class SizeConversionHelper { - - private static final String KB = "KB"; - private static final String MB = "MB"; - - // do not allow to create instances - private SizeConversionHelper() { - } - - /** - * Convert byte values to human readable strings with units - * - * @param byteValue Value to convert in bytes - */ - public static String byteValueToReadableString(final long byteValue) { - double outputValue = byteValue / 1024.0; - String unit = KB; - if (outputValue >= 1024) { - outputValue = outputValue / 1024.0; - unit = MB; - } - // We cut decimal places to avoid localization handling - return (long) outputValue + " " + unit; - } -} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleTypeManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleTypeManagement.java index fd82a9f6d..739f0a7d6 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleTypeManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleTypeManagement.java @@ -45,13 +45,6 @@ public interface SoftwareModuleTypeManagement @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) Optional findByKey(@NotEmpty String key); - /** - * @param name to search for - * @return all {@link SoftwareModuleType}s in the repository with given {@link SoftwareModuleType#getName()} - */ - @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) - Optional findByName(@NotEmpty String name); - @SuperBuilder @Getter @EqualsAndHashCode(callSuper = true) diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java index 3d65dec2c..04bccfbdb 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java @@ -18,8 +18,8 @@ import org.eclipse.hawkbit.im.authentication.SpringEvalExpressions; import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.model.TenantMetaData; -import org.eclipse.hawkbit.repository.report.model.SystemUsageReport; -import org.eclipse.hawkbit.repository.report.model.SystemUsageReportWithTenants; +import org.eclipse.hawkbit.repository.model.report.SystemUsageReport; +import org.eclipse.hawkbit.repository.model.report.SystemUsageReportWithTenants; import org.eclipse.hawkbit.tenancy.TenantAware; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java index b34bb78fb..1882e5336 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java @@ -91,6 +91,18 @@ public interface TargetManagement boolean isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable( @NotNull String controllerId, long distributionSetId, @NotNull String targetFilterQuery); + @PreAuthorize(HAS_READ_REPOSITORY) + Target getByControllerId(@NotEmpty String controllerId); + + /** + * Find a {@link Target} based a given ID. + * + * @param controllerId to look for. + * @return {@link Target} + */ + @PreAuthorize(HAS_READ_REPOSITORY) + Optional findByControllerId(@NotEmpty String controllerId); + /** * Find {@link Target}s based a given IDs. * @@ -98,7 +110,7 @@ public interface TargetManagement * @return List of found{@link Target}s */ @PreAuthorize(HAS_READ_REPOSITORY) - List getByControllerId(@NotEmpty Collection controllerIDs); + List findByControllerId(@NotEmpty Collection controllerIDs); /** * Gets a {@link Target} based a given controller id and includes the details specified by the details key. @@ -190,85 +202,14 @@ public interface TargetManagement * @param rsql the specification to filter the result set * @param pageable page parameter * @return the found {@link Target}s, never {@code null} - * @throws RSQLParameterUnsupportedFieldException if a field in the RSQL string is used but not provided - * by the given {@code fieldNameProvider} + * @throws RSQLParameterUnsupportedFieldException if a field in the RSQL string is used but not provided by the given + * {@code fieldNameProvider} * @throws RSQLParameterSyntaxException if the RSQL syntax is wrong * @throws EntityNotFoundException if distribution set with given ID does not exist */ @PreAuthorize(HAS_READ_TARGET_AND_READ_DISTRIBUTION_SET) Page findByAssignedDistributionSetAndRsql(long distributionSetId, @NotNull String rsql, @NotNull Pageable pageable); - /** - * Count all targets for given {@link TargetFilterQuery} and that are compatible - * with the passed {@link DistributionSetType}. - * - * @param rsql filter definition in RSQL syntax - * @param distributionSetIdTypeId ID of the {@link DistributionSetType} the targets need to be - * compatible with - * @return the found number of{@link Target}s - */ - @PreAuthorize(HAS_READ_REPOSITORY) - long countByRsqlAndCompatible(@NotEmpty String rsql, @NotNull Long distributionSetIdTypeId); - - /** - * Count all targets with failed actions for specific Rollout and that are compatible with the passed {@link DistributionSetType} and - * created after given timestamp - * - * @param rolloutId rolloutId of the rollout to be retried. - * @param dsTypeId ID of the {@link DistributionSetType} the targets need to be compatible with - * @return the found number of{@link Target}s - */ - @PreAuthorize(HAS_READ_REPOSITORY) - long countByFailedInRollout(@NotEmpty String rolloutId, @NotNull Long dsTypeId); - - /** - * Counts all targets for all the given parameter {@link TargetFilterQuery} and that don't have the specified distribution set in their - * action history and are compatible with the passed {@link DistributionSetType}. - * - * @param distributionSetId id of the {@link DistributionSet} - * @param rsql filter definition in RSQL syntax - * @return the count of found {@link Target}s - * @throws EntityNotFoundException if distribution set with given ID does not exist - */ - @PreAuthorize(HAS_READ_TARGET_AND_READ_DISTRIBUTION_SET) - long countByRsqlAndNonDsAndCompatibleAndUpdatable(long distributionSetId, @NotNull String rsql); - - /** - * Counts all targets for all the given parameter {@link TargetFilterQuery} and that are not assigned to one of the {@link RolloutGroup}s - * and are compatible with the passed {@link DistributionSetType}. - * - * @param rsql filter definition in RSQL syntax - * @param groups the list of {@link RolloutGroup}s - * @param distributionSetType type of the {@link DistributionSet} the targets must be compatible with - * @return count of the found {@link Target}s - */ - @PreAuthorize(HAS_READ_TARGET_AND_READ_ROLLOUT) - long countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable( - @NotNull String rsql, @NotEmpty Collection groups, @NotNull DistributionSetType distributionSetType); - - /** - * Counts all targets with failed actions for specific Rollout and that are not assigned to one of the {@link RolloutGroup}s and are - * compatible with the passed {@link DistributionSetType}. - * - * @param rolloutId rolloutId of the rollout to be retried. - * @param groups the list of {@link RolloutGroup}s - * @return count of the found {@link Target}s - */ - @PreAuthorize(HAS_READ_TARGET_AND_READ_ROLLOUT) - long countByFailedRolloutAndNotInRolloutGroups(@NotNull String rolloutId, @NotEmpty Collection groups); - - @PreAuthorize(HAS_READ_TARGET_AND_READ_ROLLOUT) - long countByActionsInRolloutGroup(final long rolloutGroupId); - - /** - * Find a {@link Target} based a given ID. - * - * @param controllerId to look for. - * @return {@link Target} - */ - @PreAuthorize(HAS_READ_REPOSITORY) - Optional getByControllerId(@NotEmpty String controllerId); - /** * retrieves {@link Target}s by the installed {@link DistributionSet}. * @@ -322,6 +263,65 @@ public interface TargetManagement @PreAuthorize(HAS_READ_REPOSITORY) Page findByRsqlAndTag(@NotNull String rsql, long tagId, @NotNull Pageable pageable); + /** + * Count all targets for given {@link TargetFilterQuery} and that are compatible with the passed {@link DistributionSetType}. + * + * @param rsql filter definition in RSQL syntax + * @param distributionSetIdTypeId ID of the {@link DistributionSetType} the targets need to be compatible with + * @return the found number of{@link Target}s + */ + @PreAuthorize(HAS_READ_REPOSITORY) + long countByRsqlAndCompatible(@NotEmpty String rsql, @NotNull Long distributionSetIdTypeId); + + /** + * Count all targets with failed actions for specific Rollout and that are compatible with the passed {@link DistributionSetType} and + * created after given timestamp + * + * @param rolloutId rolloutId of the rollout to be retried. + * @param dsTypeId ID of the {@link DistributionSetType} the targets need to be compatible with + * @return the found number of{@link Target}s + */ + @PreAuthorize(HAS_READ_REPOSITORY) + long countByFailedInRollout(@NotEmpty String rolloutId, @NotNull Long dsTypeId); + + /** + * Counts all targets for all the given parameter {@link TargetFilterQuery} and that don't have the specified distribution set in their + * action history and are compatible with the passed {@link DistributionSetType}. + * + * @param distributionSetId id of the {@link DistributionSet} + * @param rsql filter definition in RSQL syntax + * @return the count of found {@link Target}s + * @throws EntityNotFoundException if distribution set with given ID does not exist + */ + @PreAuthorize(HAS_READ_TARGET_AND_READ_DISTRIBUTION_SET) + long countByRsqlAndNonDsAndCompatibleAndUpdatable(long distributionSetId, @NotNull String rsql); + + /** + * Counts all targets for all the given parameter {@link TargetFilterQuery} and that are not assigned to one of the {@link RolloutGroup}s + * and are compatible with the passed {@link DistributionSetType}. + * + * @param rsql filter definition in RSQL syntax + * @param groups the list of {@link RolloutGroup}s + * @param distributionSetType type of the {@link DistributionSet} the targets must be compatible with + * @return count of the found {@link Target}s + */ + @PreAuthorize(HAS_READ_TARGET_AND_READ_ROLLOUT) + long countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable( + @NotNull String rsql, @NotEmpty Collection groups, @NotNull DistributionSetType distributionSetType); + + /** + * Counts all targets with failed actions for specific Rollout and that are not assigned to one of the {@link RolloutGroup}s and are + * compatible with the passed {@link DistributionSetType}. + * + * @param rolloutId rolloutId of the rollout to be retried. + * @param groups the list of {@link RolloutGroup}s + * @return count of the found {@link Target}s + */ + @PreAuthorize(HAS_READ_TARGET_AND_READ_ROLLOUT) + long countByFailedRolloutAndNotInRolloutGroups(@NotNull String rolloutId, @NotEmpty Collection groups); + + @PreAuthorize(HAS_READ_TARGET_AND_READ_ROLLOUT) + long countByActionsInRolloutGroup(final long rolloutGroupId); /** * Deletes target with the given controller ID. diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetTypeManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetTypeManagement.java index ee7f6baeb..0b1fa5c22 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetTypeManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetTypeManagement.java @@ -51,14 +51,7 @@ public interface TargetTypeManagement * @return {@link TargetType} */ @PreAuthorize(HAS_READ_REPOSITORY) - Optional getByKey(@NotEmpty String key); - - /** - * @param name as {@link TargetType#getName()} - * @return {@link TargetType} - */ - @PreAuthorize(HAS_READ_REPOSITORY) - Optional getByName(@NotEmpty String name); + Optional findByKey(@NotEmpty String key); /** * @param id Target type ID diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TenantStatsManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TenantStatsManagement.java index 2d3a7efd5..0c6a36df8 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TenantStatsManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TenantStatsManagement.java @@ -11,7 +11,7 @@ package org.eclipse.hawkbit.repository; import org.eclipse.hawkbit.im.authentication.SpRole; import org.eclipse.hawkbit.im.authentication.SpringEvalExpressions; -import org.eclipse.hawkbit.repository.report.model.TenantUsage; +import org.eclipse.hawkbit.repository.model.report.TenantUsage; import org.springframework.security.access.prepost.PreAuthorize; /** diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/autoassign/AutoAssignExecutor.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/autoassign/AutoAssignExecutor.java index d1857dbb3..e13b3dafa 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/autoassign/AutoAssignExecutor.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/autoassign/AutoAssignExecutor.java @@ -10,15 +10,13 @@ package org.eclipse.hawkbit.repository.autoassign; /** - * An interface declaration which contains the check for the auto assignment - * logic. + * An interface declaration which contains the check for the auto assignment logic. */ public interface AutoAssignExecutor { /** - * Checks all target filter queries with an auto assign distribution set and - * triggers the check and assignment to targets that don't have the design DS - * yet + * Checks all target filter queries with an auto assign distribution set and triggers the check and assignment to targets that don't have + * the design DS yet */ void checkAllTargets(); diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/TenantAwareEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/TenantAwareEvent.java index c32f86996..604a6a7c6 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/TenantAwareEvent.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/TenantAwareEvent.java @@ -10,8 +10,8 @@ package org.eclipse.hawkbit.repository.event; /** - * An event declaration which holds an revision for each event so consumers have - * the chance to know if they might already retrieved a newer event. + * An event declaration which holds a revision for each event so consumers have + * the chance to know if they might already have been retrieved a newer event. */ @FunctionalInterface public interface TenantAwareEvent { diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/entity/EntityCreatedEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/entity/EntityCreatedEvent.java index b966a8638..31460f919 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/entity/EntityCreatedEvent.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/entity/EntityCreatedEvent.java @@ -10,6 +10,6 @@ package org.eclipse.hawkbit.repository.event.entity; /** - * Marker interface to indicate event has created a newly entity. + * Marker interface to indicate an event for a newly created entity. */ public interface EntityCreatedEvent extends EntityIdEvent {} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/entity/EntityDeletedEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/entity/EntityDeletedEvent.java index 67722a67a..0a7ad2468 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/entity/EntityDeletedEvent.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/entity/EntityDeletedEvent.java @@ -10,6 +10,6 @@ package org.eclipse.hawkbit.repository.event.entity; /** - * Marker interface to indicate event has deleted an entity. + * Marker interface to indicate an event for a deleted entity. */ public interface EntityDeletedEvent extends EntityIdEvent {} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/entity/EntityIdEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/entity/EntityIdEvent.java index 6b49e6180..0930b7dea 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/entity/EntityIdEvent.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/entity/EntityIdEvent.java @@ -12,7 +12,7 @@ package org.eclipse.hawkbit.repository.event.entity; import org.eclipse.hawkbit.repository.event.TenantAwareEvent; /** - * Interface to indicate an entity event which contains at least an entity id. + * Marker interface to indicate an event which contains at least an entity id. */ public interface EntityIdEvent extends TenantAwareEvent { @@ -21,11 +21,6 @@ public interface EntityIdEvent extends TenantAwareEvent { */ String getEntityClass(); - /** - * @return the class of entities interface - */ - String getInterfaceClass(); - /** * @return the ID of the entity of this event. */ diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/entity/EntityUpdatedEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/entity/EntityUpdatedEvent.java index 39a46774c..09d47e7e5 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/entity/EntityUpdatedEvent.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/entity/EntityUpdatedEvent.java @@ -10,6 +10,6 @@ package org.eclipse.hawkbit.repository.event.entity; /** - * Marker interface to indicate event has updated an entity. + * Marker interface to indicate an event for an updated entity. */ public interface EntityUpdatedEvent extends EntityIdEvent {} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/AbstractRemoteEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/AbstractRemoteEvent.java index cd558577e..61503e170 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/AbstractRemoteEvent.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/AbstractRemoteEvent.java @@ -15,6 +15,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonTypeInfo; import lombok.EqualsAndHashCode; import lombok.Getter; +import lombok.NoArgsConstructor; import org.springframework.context.ApplicationEvent; @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") @@ -25,6 +26,7 @@ public abstract class AbstractRemoteEvent extends ApplicationEvent { private final String id; + // for serialization libs like jackson protected AbstractRemoteEvent() { this("_empty_default_"); } diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/DistributionSetTagDeletedEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/DistributionSetTagDeletedEvent.java index a6119a12c..d84e34d11 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/DistributionSetTagDeletedEvent.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/DistributionSetTagDeletedEvent.java @@ -17,7 +17,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSetTag; import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity; /** - * Defines the the remote event of delete a {@link DistributionSetTag}. + * Defines the remote event of delete a {@link DistributionSetTag}. */ @NoArgsConstructor // for serialization libs like jackson public class DistributionSetTagDeletedEvent extends RemoteIdEvent implements EntityDeletedEvent { diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/DownloadProgressEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/DownloadProgressEvent.java index 0f2eda908..66d99dcf4 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/DownloadProgressEvent.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/DownloadProgressEvent.java @@ -11,6 +11,7 @@ package org.eclipse.hawkbit.repository.event.remote; import java.io.Serial; +import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import org.eclipse.hawkbit.repository.model.ActionStatus; @@ -19,14 +20,15 @@ import org.eclipse.hawkbit.repository.model.ActionStatus; * TenantAwareEvent that contains an updated download progress for a given * ActionStatus that was written for a download request. */ +@NoArgsConstructor(force = true) // for serialization libs like jackson +@Data @EqualsAndHashCode(callSuper = true) -@NoArgsConstructor // for serialization libs like jackson public class DownloadProgressEvent extends RemoteTenantAwareEvent { @Serial private static final long serialVersionUID = 1L; - private long shippedBytesSinceLast; + private final long shippedBytesSinceLast; /** * Constructor. @@ -39,8 +41,4 @@ public class DownloadProgressEvent extends RemoteTenantAwareEvent { super(tenant, actionStatusId); this.shippedBytesSinceLast = shippedBytesSinceLast; } - - public long getShippedBytesSinceLast() { - return shippedBytesSinceLast; - } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/MultiActionCancelEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/MultiActionCancelEvent.java index 90c0e3d6f..68bb2abed 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/MultiActionCancelEvent.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/MultiActionCancelEvent.java @@ -16,11 +16,9 @@ import lombok.NoArgsConstructor; import org.eclipse.hawkbit.repository.model.Action; /** - * Generic deployment event for the Multi-Assignments feature. The event extends - * the {@link MultiActionEvent} and holds a list of controller IDs to identify - * the targets which are affected by a deployment action and a list of - * actionIds containing the identifiers of the affected actions - * as payload. This event is only published in case of an cancellation. + * Generic deployment event for the Multi-Assignments feature. The event extends the {@link MultiActionEvent} and holds a list of controller IDs + * to identify the targets which are affected by a deployment action and a list of actionIds containing the identifiers of the affected actions + * as payload. This event is only published in case of a cancellation. */ @NoArgsConstructor // for serialization libs like jackson public class MultiActionCancelEvent extends MultiActionEvent { diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/MultiActionEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/MultiActionEvent.java index d0febd56c..b6171724b 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/MultiActionEvent.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/MultiActionEvent.java @@ -18,6 +18,7 @@ import lombok.AccessLevel; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.NonNull; import lombok.ToString; import org.eclipse.hawkbit.repository.Identifiable; import org.eclipse.hawkbit.repository.model.Action; @@ -46,6 +47,7 @@ public abstract class MultiActionEvent extends RemoteTenantAwareEvent implements } @Override + @NonNull public Iterator iterator() { return controllerIds.iterator(); } diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/RemoteIdEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/RemoteIdEvent.java index 02719047d..aff76f944 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/RemoteIdEvent.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/RemoteIdEvent.java @@ -10,7 +10,6 @@ package org.eclipse.hawkbit.repository.event.remote; import java.io.Serial; -import java.util.Arrays; import lombok.AccessLevel; import lombok.EqualsAndHashCode; @@ -20,30 +19,23 @@ import lombok.ToString; import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity; /** - * An base definition class for an event which contains an id. + * A base definition class for an event which contains an id. */ @NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class RemoteIdEvent extends RemoteTenantAwareEvent { +public abstract class RemoteIdEvent extends RemoteTenantAwareEvent { @Serial private static final long serialVersionUID = 1L; private Long entityId; private String entityClass; - private String interfaceClass; protected RemoteIdEvent(final String tenant, final Long entityId, final Class entityClass) { super(tenant, entityId); this.entityClass = entityClass.getName(); - this.interfaceClass = entityClass.isInterface() ? entityClass.getName() : getInterfaceEntity(entityClass).getName(); this.entityId = entityId; } - - private static Class getInterfaceEntity(final Class baseEntity) { - final Class[] interfaces = baseEntity.getInterfaces(); - return Arrays.stream(interfaces).filter(TenantAwareBaseEntity.class::isAssignableFrom).findFirst().orElse(baseEntity); - } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/TargetAssignDistributionSetEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/TargetAssignDistributionSetEvent.java index 04ff6aa62..bd1f4c621 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/TargetAssignDistributionSetEvent.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/TargetAssignDistributionSetEvent.java @@ -44,8 +44,7 @@ public class TargetAssignDistributionSetEvent extends AbstractAssignmentEvent { */ public TargetAssignDistributionSetEvent( final String tenant, final long distributionSetId, final List a, final boolean maintenanceWindowAvailable) { - super(tenant, distributionSetId, - a.stream().filter(action -> action.getDistributionSet().getId().longValue() == distributionSetId).toList()); + super(tenant, distributionSetId, a.stream().filter(action -> action.getDistributionSet().getId() == distributionSetId).toList()); this.distributionSetId = distributionSetId; this.maintenanceWindowAvailable = maintenanceWindowAvailable; } diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/TargetPollEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/TargetPollEvent.java index af4769f65..69f489429 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/TargetPollEvent.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/TargetPollEvent.java @@ -39,6 +39,6 @@ public class TargetPollEvent extends RemoteTenantAwareEvent { public TargetPollEvent(final Target target) { this(target.getControllerId(), target.getTenant()); - this.targetAddress = target.getAddress().toString(); + this.targetAddress = target.getAddress(); } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/entity/AbstractActionEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/entity/AbstractActionEvent.java index e56530bae..9016e596c 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/entity/AbstractActionEvent.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/entity/AbstractActionEvent.java @@ -13,6 +13,7 @@ import java.io.Serial; import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; import lombok.ToString; import org.eclipse.hawkbit.repository.model.Action; import org.springframework.lang.Nullable; @@ -20,6 +21,7 @@ import org.springframework.lang.Nullable; /** * Defines the remote event of creating a new {@link Action}. */ +@NoArgsConstructor(force = true) // for serialization libs like jackson @Data @EqualsAndHashCode(callSuper = true) @ToString @@ -32,15 +34,6 @@ public abstract class AbstractActionEvent extends RemoteEntityEvent { private final Long rolloutId; private final Long rolloutGroupId; - /** - * Default constructor for serialization libs like jackson. - */ - protected AbstractActionEvent() { - this.targetId = null; - this.rolloutId = null; - this.rolloutGroupId = null; - } - protected AbstractActionEvent( final Action action, @Nullable final Long targetId, @Nullable final Long rolloutId, @Nullable final Long rolloutGroupId) { super(action); diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/entity/AbstractRolloutGroupEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/entity/AbstractRolloutGroupEvent.java index bc39fa323..14c0db324 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/entity/AbstractRolloutGroupEvent.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/entity/AbstractRolloutGroupEvent.java @@ -10,13 +10,18 @@ package org.eclipse.hawkbit.repository.event.remote.entity; import java.io.Serial; -import java.util.Objects; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; import org.eclipse.hawkbit.repository.model.RolloutGroup; /** * Event which is published in case a {@linkplain RolloutGroup} is created or updated */ +@NoArgsConstructor(force = true)// for serialization libs like jackson +@Data +@EqualsAndHashCode(callSuper = true) public abstract class AbstractRolloutGroupEvent extends RemoteEntityEvent { @Serial @@ -24,39 +29,8 @@ public abstract class AbstractRolloutGroupEvent extends RemoteEntityEvent implements EntityCreatedEvent { diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/entity/DistributionSetUpdatedEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/entity/DistributionSetUpdatedEvent.java index f7255a5d7..29c65ca87 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/entity/DistributionSetUpdatedEvent.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/entity/DistributionSetUpdatedEvent.java @@ -11,6 +11,7 @@ package org.eclipse.hawkbit.repository.event.remote.entity; import java.io.Serial; +import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import org.eclipse.hawkbit.repository.event.entity.EntityUpdatedEvent; @@ -20,6 +21,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSet; * Defines the remote event for updating a {@link DistributionSet}. */ @NoArgsConstructor // for serialization libs like jackson +@Data @EqualsAndHashCode(callSuper = true) public class DistributionSetUpdatedEvent extends RemoteEntityEvent implements EntityUpdatedEvent { @@ -38,11 +40,4 @@ public class DistributionSetUpdatedEvent extends RemoteEntityEventtrue if {@link DistributionSet} is after the update {@link DistributionSet#isComplete()} - */ - public boolean isComplete() { - return complete; - } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/service/AbstractServiceRemoteEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/service/AbstractServiceRemoteEvent.java index 28ff47690..a77f45ced 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/service/AbstractServiceRemoteEvent.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/event/remote/service/AbstractServiceRemoteEvent.java @@ -9,10 +9,12 @@ */ package org.eclipse.hawkbit.repository.event.remote.service; +import lombok.EqualsAndHashCode; import lombok.Getter; import org.eclipse.hawkbit.repository.event.remote.AbstractRemoteEvent; @Getter +@EqualsAndHashCode(callSuper = true) public abstract class AbstractServiceRemoteEvent extends AbstractRemoteEvent { private final T remoteEvent; @@ -21,5 +23,4 @@ public abstract class AbstractServiceRemoteEvent super(remoteEvent == null ? "_empty_source_" : remoteEvent.getSource()); this.remoteEvent = remoteEvent; } - -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/AssignmentQuotaExceededException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/AssignmentQuotaExceededException.java index 526226fa9..bf20ee98a 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/AssignmentQuotaExceededException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/AssignmentQuotaExceededException.java @@ -25,89 +25,37 @@ public class AssignmentQuotaExceededException extends AbstractServerRtException private static final String ASSIGNMENT_QUOTA_EXCEEDED_MESSAGE = "Quota exceeded: Cannot assign %s more %s entities to %s '%s'. The maximum is %s."; private static final SpServerError errorType = SpServerError.SP_QUOTA_EXCEEDED; - /** - * Creates a new AssignmentQuotaExceededException with - * {@link SpServerError#SP_QUOTA_EXCEEDED} error. - */ public AssignmentQuotaExceededException() { super(errorType); } - /** - * Creates a new AssignmentQuotaExceededException with a custom error - * message. - * - * @param message The custom error message. - */ public AssignmentQuotaExceededException(final String message) { - super(message, errorType); + super(errorType, message); } - /** - * Creates a AssignmentQuotaExceededException with a custom error message - * and a root cause. - * - * @param message The custom error message. - * @param cause for the exception - */ public AssignmentQuotaExceededException(final String message, final Throwable cause) { - super(message, errorType, cause); + super(errorType, message, cause); } - /** - * @param type that hit quota - * @param inserted cause for the hit - * @param quota that is defined by the repository - */ - public AssignmentQuotaExceededException(final Class type, final long inserted, - final int quota) { + public AssignmentQuotaExceededException(final Class type, final long inserted, final int quota) { this(type.getSimpleName(), inserted, quota); } - /** - * @param type that hit quota - * @param inserted cause for the hit - * @param quota that is defined by the repository - */ public AssignmentQuotaExceededException(final String type, final long inserted, final int quota) { - super("Request contains too many entries of {" + type + "}. {" + inserted + "} is beyond the permitted {" - + quota + "}.", errorType); + super(errorType, "Request contains too many entries of {" + type + "}. {" + inserted + "} is beyond the permitted {" + quota + "}."); } - /** - * Creates a AssignmentQuotaExceededException which is to be thrown when an - * assignment quota is exceeded. - * - * @param type The type of the entities that shall be assigned to the - * specified parent entity. - * @param parentType The type of the parent entity. - * @param parentId The ID of the parent entity. - * @param requested The number of entities that shall be assigned to the specified - * parent entity. - * @param quota The maximum number of entities that can be assigned to the - * parent entity. - */ public AssignmentQuotaExceededException(final Class type, final Class parentType, final Long parentId, final long requested, final long quota) { this(type.getSimpleName(), parentType.getSimpleName(), parentId, requested, quota); } - /** - * Creates a AssignmentQuotaExceededException which is to be thrown when an - * assignment quota is exceeded. - * - * @param type The type of the entities that shall be assigned to the - * specified parent entity. - * @param parentType The type of the parent entity. - * @param parentId The ID of the parent entity. - * @param requested The number of entities that shall be assigned to the specified - * parent entity. - * @param quota The maximum number of entities that can be assigned to the - * parent entity. - */ - public AssignmentQuotaExceededException(final String type, final String parentType, final Object parentId, - final long requested, final long quota) { - super(String.format(ASSIGNMENT_QUOTA_EXCEEDED_MESSAGE, requested, type, parentType, - parentId != null ? String.valueOf(parentId) : "", quota), errorType); + public AssignmentQuotaExceededException( + final String type, final String parentType, final Object parentId, final long requested, final long quota) { + super( + errorType, String.format( + ASSIGNMENT_QUOTA_EXCEEDED_MESSAGE, + requested, type, parentType, parentId != null ? String.valueOf(parentId) : "", quota) + ); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/AutoConfirmationAlreadyActiveException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/AutoConfirmationAlreadyActiveException.java index d762d69c0..a709efdd1 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/AutoConfirmationAlreadyActiveException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/AutoConfirmationAlreadyActiveException.java @@ -29,30 +29,7 @@ public class AutoConfirmationAlreadyActiveException extends AbstractServerRtExce private static final SpServerError THIS_ERROR = SpServerError.SP_REPO_AUTO_CONFIRMATION_ALREADY_ACTIVE; - /** - * Default constructor. - */ - public AutoConfirmationAlreadyActiveException() { - super(THIS_ERROR); - } - - /** - * Parameterized constructor. - * - * @param cause of the exception - */ - public AutoConfirmationAlreadyActiveException(final Throwable cause) { - super(THIS_ERROR, cause); - } - - /** - * Parameterized constructor for auto confirmation is already active for given - * controller ID - * - * @param controllerId of affected device - */ public AutoConfirmationAlreadyActiveException(final String controllerId) { - super("Auto confirmation is already active for device " + controllerId, THIS_ERROR); + super(THIS_ERROR, "Auto confirmation is already active for device " + controllerId); } - -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/CancelActionNotAllowedException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/CancelActionNotAllowedException.java index 6b710d5c6..7db92e8cb 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/CancelActionNotAllowedException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/CancelActionNotAllowedException.java @@ -27,25 +27,7 @@ public final class CancelActionNotAllowedException extends AbstractServerRtExcep @Serial private static final long serialVersionUID = 1L; - /** - * Creates a new CancelActionNotAllowed with - * {@link SpServerError#SP_ACTION_NOT_CANCELABLE} error. - */ - public CancelActionNotAllowedException() { - super(SpServerError.SP_ACTION_NOT_CANCELABLE); - } - - /** - * @param cause for the exception - */ - public CancelActionNotAllowedException(final Throwable cause) { - super(SpServerError.SP_ACTION_NOT_CANCELABLE, cause); - } - - /** - * @param message of the error - */ public CancelActionNotAllowedException(final String message) { - super(message, SpServerError.SP_ACTION_NOT_CANCELABLE); + super(SpServerError.SP_ACTION_NOT_CANCELABLE, message); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ConcurrentModificationException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ConcurrentModificationException.java deleted file mode 100644 index 9c9d377dd..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ConcurrentModificationException.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.exception; - -import java.io.Serial; - -import lombok.EqualsAndHashCode; -import lombok.ToString; -import org.eclipse.hawkbit.exception.AbstractServerRtException; -import org.eclipse.hawkbit.exception.SpServerError; - -/** - * {@link ConcurrentModificationException} is thrown when a given entity in's actual and cannot be stored within the current session. - * Reason could be that it has been changed within another session. - */ -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class ConcurrentModificationException extends AbstractServerRtException { - - @Serial - private static final long serialVersionUID = 1L; - private static final SpServerError THIS_ERROR = SpServerError.SP_REPO_CONCURRENT_MODIFICATION; - - /** - * Constructor. - */ - public ConcurrentModificationException() { - super(THIS_ERROR); - } - - /** - * Parameterized constructor. - * - * @param cause of the exception - */ - public ConcurrentModificationException(final Throwable cause) { - super(THIS_ERROR, cause); - } - - /** - * Parameterized constructor. - * - * @param message custom error message - * @param cause of the exception - */ - public ConcurrentModificationException(final String message, final Throwable cause) { - super(message, THIS_ERROR, cause); - } - - /** - * Parameterized constructor. - * - * @param message custom error message - */ - public ConcurrentModificationException(final String message) { - super(message, THIS_ERROR); - } - -} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/DeletedException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/DeletedException.java index 2dee20093..576ed848d 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/DeletedException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/DeletedException.java @@ -29,9 +29,7 @@ public class DeletedException extends AbstractServerRtException { private static final SpServerError THIS_ERROR = SpServerError.SP_DELETED; - public DeletedException( - final Class type, final Object entityId) { - super(type.getSimpleName() + " with given identifier {" + entityId + "} is soft-deleted!", - THIS_ERROR); + public DeletedException(final Class type, final Object entityId) { + super(THIS_ERROR, type.getSimpleName() + " with given identifier {" + entityId + "} is soft-deleted!"); } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/DistributionSetTypeUndefinedException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/DistributionSetTypeUndefinedException.java index 3453d2d83..60d158744 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/DistributionSetTypeUndefinedException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/DistributionSetTypeUndefinedException.java @@ -28,25 +28,7 @@ public class DistributionSetTypeUndefinedException extends AbstractServerRtExcep @Serial private static final long serialVersionUID = 1L; - /** - * Creates a new FileUploadFailedException with - * {@link SpServerError#SP_DS_TYPE_UNDEFINED} error. - */ public DistributionSetTypeUndefinedException() { super(SpServerError.SP_DS_TYPE_UNDEFINED); } - - /** - * @param cause for the exception - */ - public DistributionSetTypeUndefinedException(final Throwable cause) { - super(SpServerError.SP_DS_TYPE_UNDEFINED, cause); - } - - /** - * @param message of the error - */ - public DistributionSetTypeUndefinedException(final String message) { - super(message, SpServerError.SP_DS_TYPE_UNDEFINED); - } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityAlreadyExistsException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityAlreadyExistsException.java index 0ee046d5e..3089ee1a3 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityAlreadyExistsException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityAlreadyExistsException.java @@ -29,38 +29,19 @@ public class EntityAlreadyExistsException extends AbstractServerRtException { private static final SpServerError THIS_ERROR = SpServerError.SP_REPO_ENTITY_ALREADY_EXISTS; - /** - * Default constructor. - */ public EntityAlreadyExistsException() { super(THIS_ERROR); } - /** - * Parameterized constructor. - * - * @param cause of the exception - */ public EntityAlreadyExistsException(final Throwable cause) { super(THIS_ERROR, cause); } - /** - * Parameterized constructor. - * - * @param message of the exception - * @param cause of the exception - */ public EntityAlreadyExistsException(final String message, final Throwable cause) { - super(message, THIS_ERROR, cause); + super(THIS_ERROR, message, cause); } - /** - * Parameterized constructor. - * - * @param message of the exception - */ public EntityAlreadyExistsException(final String message) { - super(message, THIS_ERROR); + super(THIS_ERROR, message); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityNotFoundException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityNotFoundException.java index b86c021a0..8e0fe4a4d 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityNotFoundException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityNotFoundException.java @@ -39,77 +39,38 @@ public class EntityNotFoundException extends AbstractServerRtException { private static final SpServerError THIS_ERROR = SpServerError.SP_REPO_ENTITY_NOT_EXISTS; private static final int ENTITY_STRING_MAX_LENGTH = 100; - /** - * Default constructor. - */ public EntityNotFoundException() { super(THIS_ERROR); } - /** - * Parameterized constructor. - * - * @param cause of the exception - */ public EntityNotFoundException(final Throwable cause) { super(THIS_ERROR, cause); } - /** - * Parameterized constructor. - * - * @param message of the exception - * @param cause of the exception - */ public EntityNotFoundException(final String message, final Throwable cause) { - super(message, THIS_ERROR, cause); + super(THIS_ERROR, message, cause); } - /** - * Parameterized constructor. - * - * @param message of the exception - */ protected EntityNotFoundException(final String message) { - super(message, THIS_ERROR); + super(THIS_ERROR, message); } - /** - * Parameterized constructor for {@link BaseEntity} not found. - * - * @param type of the entity that was not found - * @param entityId of the {@link BaseEntity} - */ public EntityNotFoundException(final String type, final Object entityId) { - super(type + " with given identifier {" + entityId + "} does not exist.", THIS_ERROR, Map.of(TYPE, type, ENTITY_ID, entityId)); + super(THIS_ERROR, type + " with given identifier {" + entityId + "} does not exist.", Map.of(TYPE, type, ENTITY_ID, entityId)); } - /** - * Parameterized constructor for {@link BaseEntity} not found. - * - * @param type of the entity that was not found - * @param entityId of the {@link BaseEntity} - */ public EntityNotFoundException(final Class type, final Object entityId) { this(type.getSimpleName(), entityId); } - /** - * Parameterized constructor for a list of {@link BaseEntity}s not found. - * - * @param type of the entity that was not found - * @param expected collection of the {@link BaseEntity#getId()}s - * @param found collection of the {@link BaseEntity#getId()}s - */ public EntityNotFoundException(final Class type, final Collection expected, final Collection found) { super( - String.format("%ss with given identifiers {%s} do not exist.", + THIS_ERROR, String.format("%ss with given identifiers {%s} do not exist.", type.getSimpleName(), toEntityString(expected.stream() .filter(id -> !found.contains(id)) .map(String::valueOf) .collect(Collectors.joining(",")))), - THIS_ERROR, Map.of(TYPE, type.getSimpleName(), ENTITY_ID, expected.stream().filter(id -> !found.contains(id)).map(String::valueOf))); } diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityReadOnlyException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityReadOnlyException.java index c0e022632..4d430362f 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityReadOnlyException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityReadOnlyException.java @@ -17,7 +17,7 @@ import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** - * the {@link EntityReadOnlyException} is thrown when a entity is in read only mode and a user tries to change it. + * the {@link EntityReadOnlyException} is thrown when an entity is in read only mode and a user tries to change it. */ @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) @@ -28,38 +28,19 @@ public class EntityReadOnlyException extends AbstractServerRtException { private static final SpServerError THIS_ERROR = SpServerError.SP_REPO_ENTITY_READ_ONLY; - /** - * Default constructor. - */ public EntityReadOnlyException() { super(THIS_ERROR); } - /** - * Parameterized constructor. - * - * @param cause of the exception - */ public EntityReadOnlyException(final Throwable cause) { super(THIS_ERROR, cause); } - /** - * Parameterized constructor. - * - * @param message of the exception - * @param cause of the exception - */ public EntityReadOnlyException(final String message, final Throwable cause) { - super(message, THIS_ERROR, cause); + super(THIS_ERROR, message, cause); } - /** - * Parameterized constructor. - * - * @param message of the exception - */ public EntityReadOnlyException(final String message) { - super(message, THIS_ERROR); + super(THIS_ERROR, message); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ForceQuitActionNotAllowedException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ForceQuitActionNotAllowedException.java index cc617b773..5bd2a96bc 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ForceQuitActionNotAllowedException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ForceQuitActionNotAllowedException.java @@ -26,25 +26,7 @@ public final class ForceQuitActionNotAllowedException extends AbstractServerRtEx @Serial private static final long serialVersionUID = 1L; - /** - * Creates a new CancelActionNotAllowed with - * {@link SpServerError#SP_ACTION_NOT_CANCELABLE} error. - */ - public ForceQuitActionNotAllowedException() { - super(SpServerError.SP_ACTION_NOT_FORCE_QUITABLE); - } - - /** - * @param cause for the exception - */ - public ForceQuitActionNotAllowedException(final Throwable cause) { - super(SpServerError.SP_ACTION_NOT_FORCE_QUITABLE, cause); - } - - /** - * @param message of the error - */ public ForceQuitActionNotAllowedException(final String message) { - super(message, SpServerError.SP_ACTION_NOT_FORCE_QUITABLE); + super(SpServerError.SP_ACTION_NOT_FORCE_QUITABLE, message); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/IncompatibleTargetTypeException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/IncompatibleTargetTypeException.java index 8941f13e4..66e4d69fb 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/IncompatibleTargetTypeException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/IncompatibleTargetTypeException.java @@ -14,6 +14,7 @@ import java.util.Collection; import java.util.Collections; import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; @@ -25,6 +26,7 @@ import org.eclipse.hawkbit.repository.model.TargetType; * Thrown if user tries to assign a {@link DistributionSet} to a {@link Target} that has an incompatible {@link TargetType} */ @EqualsAndHashCode(callSuper = true) +@Getter @ToString(callSuper = true) public class IncompatibleTargetTypeException extends AbstractServerRtException { @@ -34,41 +36,19 @@ public class IncompatibleTargetTypeException extends AbstractServerRtException { private final Collection targetTypeNames; private final Collection distributionSetTypeNames; - /** - * Creates a new IncompatibleTargetTypeException with - * {@link SpServerError#SP_TARGET_TYPE_INCOMPATIBLE} error. - * - * @param targetTypeName Name of the target type - * @param distributionSetTypeNames Names of the distribution set types - */ - public IncompatibleTargetTypeException(final String targetTypeName, - final Collection distributionSetTypeNames) { - super(String.format("Target of type %s is not compatible with distribution set of types %s", targetTypeName, - distributionSetTypeNames), SpServerError.SP_TARGET_TYPE_INCOMPATIBLE); + public IncompatibleTargetTypeException(final String targetTypeName, final Collection distributionSetTypeNames) { + super(SpServerError.SP_TARGET_TYPE_INCOMPATIBLE, + String.format("Target of type %s is not compatible with distribution set of types %s", targetTypeName, distributionSetTypeNames) + ); this.targetTypeNames = Collections.singleton(targetTypeName); this.distributionSetTypeNames = distributionSetTypeNames; } - /** - * Creates a new IncompatibleTargetTypeException with - * {@link SpServerError#SP_TARGET_TYPE_INCOMPATIBLE} error. - * - * @param targetTypeNames Name of the target types - * @param distributionSetTypeName Name of the distribution set type - */ - public IncompatibleTargetTypeException(final Collection targetTypeNames, - final String distributionSetTypeName) { - super(String.format("Targets of types %s are not compatible with distribution set of type %s", targetTypeNames, - distributionSetTypeName), SpServerError.SP_TARGET_TYPE_INCOMPATIBLE); + public IncompatibleTargetTypeException(final Collection targetTypeNames, final String distributionSetTypeName) { + super(SpServerError.SP_TARGET_TYPE_INCOMPATIBLE, + String.format("Targets of types %s are not compatible with distribution set of type %s", targetTypeNames, + distributionSetTypeName)); this.targetTypeNames = targetTypeNames; this.distributionSetTypeNames = Collections.singleton(distributionSetTypeName); } - - public Collection getTargetTypeNames() { - return targetTypeNames; - } - - public Collection getDistributionSetTypeNames() { - return distributionSetTypeNames; - } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/IncompleteDistributionSetException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/IncompleteDistributionSetException.java index d3158f8fc..b8b44ad22 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/IncompleteDistributionSetException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/IncompleteDistributionSetException.java @@ -26,25 +26,15 @@ public final class IncompleteDistributionSetException extends AbstractServerRtEx @Serial private static final long serialVersionUID = 1L; - /** - * Creates a new IncompleteDistributionSetException with - * {@link SpServerError#SP_DS_INCOMPLETE} error. - */ public IncompleteDistributionSetException() { super(SpServerError.SP_DS_INCOMPLETE); } - /** - * @param cause for the exception - */ public IncompleteDistributionSetException(final Throwable cause) { super(SpServerError.SP_DS_INCOMPLETE, cause); } - /** - * @param message of the error - */ public IncompleteDistributionSetException(final String message) { - super(message, SpServerError.SP_DS_INCOMPLETE); + super(SpServerError.SP_DS_INCOMPLETE, message); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InsufficientPermissionException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InsufficientPermissionException.java index 88296a8f5..3d88d5f84 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InsufficientPermissionException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InsufficientPermissionException.java @@ -31,7 +31,7 @@ public class InsufficientPermissionException extends AbstractServerRtException { } public InsufficientPermissionException(final String message) { - super(message, SpServerError.SP_INSUFFICIENT_PERMISSION); + super(SpServerError.SP_INSUFFICIENT_PERMISSION, message); } public InsufficientPermissionException() { diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidAutoAssignActionTypeException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidAutoAssignActionTypeException.java index fcabaa053..4e3ddf75c 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidAutoAssignActionTypeException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidAutoAssignActionTypeException.java @@ -29,10 +29,7 @@ public class InvalidAutoAssignActionTypeException extends AbstractServerRtExcept private static final SpServerError THIS_ERROR = SpServerError.SP_AUTO_ASSIGN_ACTION_TYPE_INVALID; - /** - * Default constructor. - */ public InvalidAutoAssignActionTypeException() { super(THIS_ERROR); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidConfirmationFeedbackException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidConfirmationFeedbackException.java index a9a4b5567..745931e2b 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidConfirmationFeedbackException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidConfirmationFeedbackException.java @@ -12,6 +12,7 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; @@ -20,6 +21,7 @@ import org.eclipse.hawkbit.exception.SpServerError; * This exception is indicating that the confirmation feedback cannot be processed for a specific actions for different reasons which are * listed as enum {@link Reason}. */ +@Getter @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) public class InvalidConfirmationFeedbackException extends AbstractServerRtException { @@ -31,21 +33,12 @@ public class InvalidConfirmationFeedbackException extends AbstractServerRtExcept private final Reason reason; - protected InvalidConfirmationFeedbackException(final Reason reason) { - super(THIS_ERROR); - this.reason = reason; - } - public InvalidConfirmationFeedbackException(final Reason reason, final String message) { - super(message, THIS_ERROR); + super(THIS_ERROR, message); this.reason = reason; } - public Reason getReason() { - return reason; - } - public enum Reason { ACTION_CLOSED, NOT_AWAITING_CONFIRMATION } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidDistributionSetException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidDistributionSetException.java index 29185f377..31eaf52f4 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidDistributionSetException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidDistributionSetException.java @@ -23,26 +23,15 @@ public class InvalidDistributionSetException extends AbstractServerRtException { @Serial private static final long serialVersionUID = 1L; - /** - * Creates a new InvalidDistributionSetException with - * {@link SpServerError#SP_DS_INVALID} error. - */ public InvalidDistributionSetException() { super(SpServerError.SP_DS_INVALID); } - /** - * @param cause for the exception - */ public InvalidDistributionSetException(final Throwable cause) { super(SpServerError.SP_DS_INVALID, cause); } - /** - * @param message of the error - */ public InvalidDistributionSetException(final String message) { - super(message, SpServerError.SP_DS_INVALID); + super(SpServerError.SP_DS_INVALID, message); } - -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidMD5HashException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidMD5HashException.java deleted file mode 100644 index aca3cd333..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidMD5HashException.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.exception; - -import java.io.Serial; - -import lombok.EqualsAndHashCode; -import lombok.ToString; -import org.eclipse.hawkbit.exception.AbstractServerRtException; -import org.eclipse.hawkbit.exception.SpServerError; - -/** - * Thrown if MD5 checksum check fails. - */ -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class InvalidMD5HashException extends AbstractServerRtException { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * Creates a new FileUploadFailedException with - * {@link SpServerError#SP_ARTIFACT_UPLOAD_FAILED_MD5_MATCH} error. - */ - public InvalidMD5HashException() { - super(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_MD5_MATCH); - } - - /** - * @param message of the error - * @param cause for the exception - */ - public InvalidMD5HashException(final String message, final Throwable cause) { - super(message, SpServerError.SP_ARTIFACT_UPLOAD_FAILED_MD5_MATCH, cause); - } - - /** - * @param message of the error - */ - public InvalidMD5HashException(final String message) { - super(message, SpServerError.SP_ARTIFACT_UPLOAD_FAILED_MD5_MATCH); - } - -} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidMaintenanceScheduleException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidMaintenanceScheduleException.java index 6610eb00f..21284695f 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidMaintenanceScheduleException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidMaintenanceScheduleException.java @@ -12,6 +12,7 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; @@ -21,6 +22,7 @@ import org.eclipse.hawkbit.exception.SpServerError; * schedule, duration and timezone are all null, or are all valid; in which case there should be at least one valid window after the current * time. */ +@Getter @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) public class InvalidMaintenanceScheduleException extends AbstractServerRtException { @@ -30,54 +32,21 @@ public class InvalidMaintenanceScheduleException extends AbstractServerRtExcepti private final int durationErrorIndex; - /** - * Constructor for {@link InvalidMaintenanceScheduleException}. - * - * @param message the message for this exception. - */ public InvalidMaintenanceScheduleException(final String message) { this(message, -1); } - /** - * Constructor for {@link InvalidMaintenanceScheduleException}. - * - * @param message the message for this exception. - * @param errorIndex the error index of maintenance duration. - */ public InvalidMaintenanceScheduleException(final String message, final int errorIndex) { - super(message, SpServerError.SP_MAINTENANCE_SCHEDULE_INVALID); + super(SpServerError.SP_MAINTENANCE_SCHEDULE_INVALID, message); this.durationErrorIndex = errorIndex; } - /** - * Constructor for {@link InvalidMaintenanceScheduleException}. - * - * @param message the message for this exception - * @param cause the cause for this exception. - */ public InvalidMaintenanceScheduleException(final String message, final Throwable cause) { this(message, cause, -1); } - /** - * Constructor for {@link InvalidMaintenanceScheduleException}. - * - * @param message the message for this exception - * @param cause the cause for this exception. - * @param errorIndex the error index of maintenance duration. - */ public InvalidMaintenanceScheduleException(final String message, final Throwable cause, final int errorIndex) { - super(message, SpServerError.SP_MAINTENANCE_SCHEDULE_INVALID, cause); + super(SpServerError.SP_MAINTENANCE_SCHEDULE_INVALID, message, cause); this.durationErrorIndex = errorIndex; } - - /** - * Get the error index position for maintenance window duration. - * - * @return error index. - */ - public int getDurationErrorIndex() { - return durationErrorIndex; - } } diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTargetAddressException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidMd5HashException.java similarity index 51% rename from hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTargetAddressException.java rename to hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidMd5HashException.java index 67955458a..f6fba3e57 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTargetAddressException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidMd5HashException.java @@ -17,27 +17,16 @@ import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** - * Exception which is thrown when trying to set an invalid target address. + * Thrown if MD5 checksum check fails. */ @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class InvalidTargetAddressException extends AbstractServerRtException { +public class InvalidMd5HashException extends AbstractServerRtException { @Serial private static final long serialVersionUID = 1L; - /** - * @param message the message for this exception - */ - public InvalidTargetAddressException(final String message) { - super(message, SpServerError.SP_REPO_INVALID_TARGET_ADDRESS); + public InvalidMd5HashException(final String message, final Throwable cause) { + super(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_MD5_MATCH, message, cause); } - - /** - * @param message the message for this exception - * @param cause the cause for this exception - */ - public InvalidTargetAddressException(final String message, final Throwable cause) { - super(message, SpServerError.SP_REPO_INVALID_TARGET_ADDRESS, cause); - } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSHA1HashException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSha1HashException.java similarity index 54% rename from hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSHA1HashException.java rename to hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSha1HashException.java index 068f2ae39..4dc722b4c 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSHA1HashException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSha1HashException.java @@ -21,32 +21,12 @@ import org.eclipse.hawkbit.exception.SpServerError; */ @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class InvalidSHA1HashException extends AbstractServerRtException { +public class InvalidSha1HashException extends AbstractServerRtException { @Serial private static final long serialVersionUID = 1L; - /** - * Creates a new FileUploadFailedException with - * {@link SpServerError#SP_ARTIFACT_UPLOAD_FAILED_SHA1_MATCH} error. - */ - public InvalidSHA1HashException() { - super(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_SHA1_MATCH); + public InvalidSha1HashException(final String message, final Throwable cause) { + super(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_SHA1_MATCH, message, cause); } - - /** - * @param message of the error - * @param cause for the exception - */ - public InvalidSHA1HashException(final String message, final Throwable cause) { - super(message, SpServerError.SP_ARTIFACT_UPLOAD_FAILED_SHA1_MATCH, cause); - } - - /** - * @param message of the error - */ - public InvalidSHA1HashException(final String message) { - super(message, SpServerError.SP_ARTIFACT_UPLOAD_FAILED_SHA1_MATCH); - } - -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSHA256HashException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSha256HashException.java similarity index 54% rename from hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSHA256HashException.java rename to hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSha256HashException.java index 2c34491b8..d39b440b3 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSHA256HashException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSha256HashException.java @@ -21,32 +21,12 @@ import org.eclipse.hawkbit.exception.SpServerError; */ @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class InvalidSHA256HashException extends AbstractServerRtException { +public class InvalidSha256HashException extends AbstractServerRtException { @Serial private static final long serialVersionUID = 1L; - /** - * Creates a new FileUploadFailedException with - * {@link SpServerError#SP_ARTIFACT_UPLOAD_FAILED_SHA1_MATCH} error. - */ - public InvalidSHA256HashException() { - super(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_SHA256_MATCH); + public InvalidSha256HashException(final String message, final Throwable cause) { + super(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_SHA256_MATCH, message, cause); } - - /** - * @param message of the error - * @param cause for the exception - */ - public InvalidSHA256HashException(final String message, final Throwable cause) { - super(message, SpServerError.SP_ARTIFACT_UPLOAD_FAILED_SHA256_MATCH, cause); - } - - /** - * @param message of the error - */ - public InvalidSHA256HashException(final String message) { - super(message, SpServerError.SP_ARTIFACT_UPLOAD_FAILED_SHA256_MATCH); - } - -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTargetAttributeException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTargetAttributeException.java index 577a33a18..9c8f53d2f 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTargetAttributeException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTargetAttributeException.java @@ -26,10 +26,7 @@ public class InvalidTargetAttributeException extends AbstractServerRtException { private static final SpServerError THIS_ERROR = SpServerError.SP_TARGET_ATTRIBUTES_INVALID; - /** - * Default constructor. - */ public InvalidTargetAttributeException() { super(THIS_ERROR); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTenantConfigurationKeyException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTenantConfigurationKeyException.java index 26c19bd66..d0dc90f34 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTenantConfigurationKeyException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTenantConfigurationKeyException.java @@ -29,6 +29,6 @@ public class InvalidTenantConfigurationKeyException extends AbstractServerRtExce private static final SpServerError THIS_ERROR = SpServerError.SP_CONFIGURATION_KEY_INVALID; public InvalidTenantConfigurationKeyException(final String message) { - super(message, THIS_ERROR); + super(THIS_ERROR, message); } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/LockedException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/LockedException.java index 382fcdea3..698952efb 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/LockedException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/LockedException.java @@ -29,17 +29,15 @@ public class LockedException extends AbstractServerRtException { private static final SpServerError THIS_ERROR = SpServerError.SP_LOCKED; - public LockedException( - final Class type, final Object entityId, final String operation) { - super(type.getSimpleName() + " with given identifier {" + entityId + "} is locked and " + operation + - " is forbidden!", - THIS_ERROR); + public LockedException(final Class type, final Object entityId, final String operation) { + this(type, entityId, operation, null); } public LockedException( final Class type, final Object entityId, final String operation, final String reason) { - super(type.getSimpleName() + " with given identifier {" + entityId + "} is locked and " + operation + - " is forbidden! Reason: " + reason, - THIS_ERROR); + super( + THIS_ERROR, type.getSimpleName() + " with given identifier {" + entityId + "} is locked and " + operation + " is forbidden!" + + (reason == null ? "" : " Reason: " + reason) + ); } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/MethodNotSupportedException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/MethodNotSupportedException.java deleted file mode 100644 index 06102de4a..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/MethodNotSupportedException.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.exception; - -import java.io.Serial; - -import lombok.EqualsAndHashCode; -import lombok.ToString; -import org.eclipse.hawkbit.exception.AbstractServerRtException; -import org.eclipse.hawkbit.exception.SpServerError; - -/** - * Thrown if repository operation is no longer supported. - */ -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public final class MethodNotSupportedException extends AbstractServerRtException { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * Creates a new MethodNotSupportedException with - * {@link SpServerError#SP_REPO_OPERATION_NOT_SUPPORTED} error. - */ - public MethodNotSupportedException() { - super(SpServerError.SP_REPO_OPERATION_NOT_SUPPORTED); - } - - /** - * Creates a new MethodNotSupportedException with - * {@link SpServerError#SP_REPO_OPERATION_NOT_SUPPORTED} error. - * - * @param cause for the exception - */ - public MethodNotSupportedException(final Throwable cause) { - super(SpServerError.SP_REPO_OPERATION_NOT_SUPPORTED, cause); - } - - /** - * Creates a new MethodNotSupportedException with - * {@link SpServerError#SP_REPO_OPERATION_NOT_SUPPORTED} error. - * - * @param message of the error - */ - public MethodNotSupportedException(final String message) { - super(message, SpServerError.SP_REPO_OPERATION_NOT_SUPPORTED); - } -} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/MultiAssignmentIsNotEnabledException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/MultiAssignmentIsNotEnabledException.java index 63170f7e8..5cd7fba44 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/MultiAssignmentIsNotEnabledException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/MultiAssignmentIsNotEnabledException.java @@ -28,38 +28,7 @@ public class MultiAssignmentIsNotEnabledException extends AbstractServerRtExcept private static final SpServerError THIS_ERROR = SpServerError.SP_MULTIASSIGNMENT_NOT_ENABLED; - /** - * Default constructor. - */ public MultiAssignmentIsNotEnabledException() { super(THIS_ERROR); } - - /** - * Parameterized constructor. - * - * @param cause of the exception - */ - public MultiAssignmentIsNotEnabledException(final Throwable cause) { - super(THIS_ERROR, cause); - } - - /** - * Parameterized constructor. - * - * @param message of the exception - * @param cause of the exception - */ - public MultiAssignmentIsNotEnabledException(final String message, final Throwable cause) { - super(message, THIS_ERROR, cause); - } - - /** - * Parameterized constructor. - * - * @param message of the exception - */ - public MultiAssignmentIsNotEnabledException(final String message) { - super(message, THIS_ERROR); - } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/NoWeightProvidedInMultiAssignmentModeException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/NoWeightProvidedInMultiAssignmentModeException.java index d0b35b15d..7f5c7ff79 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/NoWeightProvidedInMultiAssignmentModeException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/NoWeightProvidedInMultiAssignmentModeException.java @@ -28,38 +28,7 @@ public class NoWeightProvidedInMultiAssignmentModeException extends AbstractServ private static final SpServerError THIS_ERROR = SpServerError.SP_NO_WEIGHT_PROVIDED_IN_MULTIASSIGNMENT_MODE; - /** - * Default constructor. - */ public NoWeightProvidedInMultiAssignmentModeException() { super(THIS_ERROR); } - - /** - * Parameterized constructor. - * - * @param cause of the exception - */ - public NoWeightProvidedInMultiAssignmentModeException(final Throwable cause) { - super(THIS_ERROR, cause); - } - - /** - * Parameterized constructor. - * - * @param message of the exception - * @param cause of the exception - */ - public NoWeightProvidedInMultiAssignmentModeException(final String message, final Throwable cause) { - super(message, THIS_ERROR, cause); - } - - /** - * Parameterized constructor. - * - * @param message of the exception - */ - public NoWeightProvidedInMultiAssignmentModeException(final String message) { - super(message, THIS_ERROR); - } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterSyntaxException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterSyntaxException.java index 490667477..a1b063b78 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterSyntaxException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterSyntaxException.java @@ -26,44 +26,19 @@ public class RSQLParameterSyntaxException extends AbstractServerRtException { @Serial private static final long serialVersionUID = 1L; - /** - * Creates a new RSQLSyntaxException with - * {@link SpServerError#SP_REST_RSQL_SEARCH_PARAM_SYNTAX} error. - */ public RSQLParameterSyntaxException() { super(SpServerError.SP_REST_RSQL_SEARCH_PARAM_SYNTAX); } - /** - * Creates a new RSQLParameterSyntaxException with - * {@link SpServerError#SP_REST_RSQL_SEARCH_PARAM_SYNTAX} error. - * - * @param message the message of the exception - */ public RSQLParameterSyntaxException(final String message) { - super(message, SpServerError.SP_REST_RSQL_SEARCH_PARAM_SYNTAX); + super(SpServerError.SP_REST_RSQL_SEARCH_PARAM_SYNTAX, message); } - /** - * Creates a new RSQLSyntaxException with - * {@link SpServerError#SP_REST_RSQL_SEARCH_PARAM_SYNTAX} error. - * - * @param cause the cause of this exception - */ public RSQLParameterSyntaxException(final Throwable cause) { super(SpServerError.SP_REST_RSQL_SEARCH_PARAM_SYNTAX, cause); } - /** - * Creates a new RSQLParameterSyntaxException with - * {@link SpServerError#SP_REST_RSQL_SEARCH_PARAM_SYNTAX} error. - * - * @param message the message of the exception - * @param cause the cause (which is saved for later retrieval by the - * getCause() method). (A null value is permitted, and indicates - * that the cause is nonexistent or unknown.) - */ public RSQLParameterSyntaxException(final String message, final Throwable cause) { - super(message, SpServerError.SP_REST_RSQL_SEARCH_PARAM_SYNTAX, cause); + super(SpServerError.SP_REST_RSQL_SEARCH_PARAM_SYNTAX, message, cause); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterUnsupportedFieldException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterUnsupportedFieldException.java index c5dfe9f39..020ed7734 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterUnsupportedFieldException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterUnsupportedFieldException.java @@ -26,46 +26,19 @@ public class RSQLParameterUnsupportedFieldException extends AbstractServerRtExce @Serial private static final long serialVersionUID = 1L; - /** - * Creates a new RSQLParameterUnsupportedFieldException with - * {@link SpServerError#SP_REST_RSQL_PARAM_INVALID_FIELD} error. - */ public RSQLParameterUnsupportedFieldException() { super(SpServerError.SP_REST_RSQL_PARAM_INVALID_FIELD); } - /** - * Creates a new RSQLParameterUnsupportedFieldException with - * {@link SpServerError#SP_REST_RSQL_PARAM_INVALID_FIELD} error. - * - * @param message the message of the exception - */ public RSQLParameterUnsupportedFieldException(final String message) { - super(message, SpServerError.SP_REST_RSQL_PARAM_INVALID_FIELD); + super(SpServerError.SP_REST_RSQL_PARAM_INVALID_FIELD, message); } - /** - * Creates a new RSQLParameterUnsupportedFieldException with - * {@link SpServerError#SP_REST_RSQL_PARAM_INVALID_FIELD} error. - * - * @param cause the cause (which is saved for later retrieval by the - * getCause() method). (A null value is permitted, and indicates - * that the cause is nonexistent or unknown.) - */ public RSQLParameterUnsupportedFieldException(final Throwable cause) { super(SpServerError.SP_REST_RSQL_PARAM_INVALID_FIELD, cause); } - /** - * Creates a new RSQLParameterUnsupportedFieldException with - * {@link SpServerError#SP_REST_RSQL_PARAM_INVALID_FIELD} error. - * - * @param message the message of the exception - * @param cause the cause (which is saved for later retrieval by the - * getCause() method). (A null value is permitted, and indicates - * that the cause is nonexistent or unknown.) - */ public RSQLParameterUnsupportedFieldException(final String message, final Throwable cause) { - super(message, SpServerError.SP_REST_RSQL_PARAM_INVALID_FIELD, cause); + super(SpServerError.SP_REST_RSQL_PARAM_INVALID_FIELD, message, cause); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RolloutIllegalStateException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RolloutIllegalStateException.java index d624abbc7..e5f082873 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RolloutIllegalStateException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RolloutIllegalStateException.java @@ -17,8 +17,8 @@ import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** - * the {@link RolloutIllegalStateException} is thrown when a rollout is changing it's state which is not valid. E.g. trying to start an already - * running rollout, or trying to resume a already finished rollout. + * The {@link RolloutIllegalStateException} is thrown when a rollout is changing its state which is not valid. E.g. trying to start an already + * running rollout, or trying to resume an already finished rollout. */ @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) @@ -29,38 +29,7 @@ public class RolloutIllegalStateException extends AbstractServerRtException { private static final SpServerError THIS_ERROR = SpServerError.SP_ROLLOUT_ILLEGAL_STATE; - /** - * Default constructor. - */ - public RolloutIllegalStateException() { - super(THIS_ERROR); - } - - /** - * Parameterized constructor. - * - * @param cause of the exception - */ - public RolloutIllegalStateException(final Throwable cause) { - super(THIS_ERROR, cause); - } - - /** - * Parameterized constructor. - * - * @param message of the exception - * @param cause of the exception - */ - public RolloutIllegalStateException(final String message, final Throwable cause) { - super(message, THIS_ERROR, cause); - } - - /** - * Parameterized constructor. - * - * @param message of the exception - */ public RolloutIllegalStateException(final String message) { - super(message, THIS_ERROR); + super(THIS_ERROR, message); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/SoftwareModuleNotAssignedToTargetException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/SoftwareModuleNotAssignedToTargetException.java index da6bd0080..ea90a8e54 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/SoftwareModuleNotAssignedToTargetException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/SoftwareModuleNotAssignedToTargetException.java @@ -10,12 +10,12 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; -import java.lang.annotation.Target; import lombok.EqualsAndHashCode; import lombok.ToString; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.SoftwareModule; +import org.eclipse.hawkbit.repository.model.Target; /** * the {@link SoftwareModuleNotAssignedToTargetException} is thrown when a {@link SoftwareModule} is requested as part of an {@link Action} @@ -28,14 +28,8 @@ public class SoftwareModuleNotAssignedToTargetException extends EntityNotFoundEx @Serial private static final long serialVersionUID = 1L; - /** - * Constructor - * - * @param moduleId that is not assigned to given {@link Target} - * @param controllerId of the {@link Target} where given {@link SoftwareModule} is not part of - */ public SoftwareModuleNotAssignedToTargetException(final Long moduleId, final String controllerId) { - super("No assignment found for " + SoftwareModule.class.getSimpleName() + " with id {" + moduleId + "} to " - + Target.class.getSimpleName() + " with id {" + controllerId + "}."); + super("No assignment found for " + SoftwareModule.class.getSimpleName() + " with id {" + moduleId + "} to " + + Target.class.getSimpleName() + " with id {" + controllerId + "}."); } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/SoftwareModuleTypeNotInDistributionSetTypeException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/SoftwareModuleTypeNotInDistributionSetTypeException.java index 991f11964..00fbc8b19 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/SoftwareModuleTypeNotInDistributionSetTypeException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/SoftwareModuleTypeNotInDistributionSetTypeException.java @@ -28,15 +28,8 @@ public class SoftwareModuleTypeNotInDistributionSetTypeException extends EntityN @Serial private static final long serialVersionUID = 1L; - /** - * Constructor - * - * @param moduleTypeId that is not part of given {@link DistributionSetType} - * @param distributionSetTypeId of the {@link DistributionSetType} where given {@link SoftwareModuleType} is not part of - */ - public SoftwareModuleTypeNotInDistributionSetTypeException(final Long moduleTypeId, - final Long distributionSetTypeId) { - super(SoftwareModuleType.class.getSimpleName() + " with id {" + moduleTypeId + "} is not part of " - + DistributionSetType.class.getSimpleName() + " with id {" + distributionSetTypeId + "}."); + public SoftwareModuleTypeNotInDistributionSetTypeException(final Long moduleTypeId, final Long distributionSetTypeId) { + super(SoftwareModuleType.class.getSimpleName() + " with id {" + moduleTypeId + "} is not part of " + + DistributionSetType.class.getSimpleName() + " with id {" + distributionSetTypeId + "}."); } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/StopRolloutException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/StopRolloutException.java index 7a70eaa9e..41b13ecaa 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/StopRolloutException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/StopRolloutException.java @@ -27,31 +27,7 @@ public class StopRolloutException extends AbstractServerRtException { @Serial private static final long serialVersionUID = 1L; - /** - * Creates a new StopRolloutException with - * {@link SpServerError#SP_STOP_ROLLOUT_FAILED} error. - */ - public StopRolloutException() { - super(SpServerError.SP_STOP_ROLLOUT_FAILED); - } - - /** - * Creates a new StopRolloutException with - * {@link SpServerError#SP_STOP_ROLLOUT_FAILED} error. - * - * @param cause for the exception - */ - public StopRolloutException(final Throwable cause) { - super(SpServerError.SP_STOP_ROLLOUT_FAILED, cause); - } - - /** - * Creates a new StopRolloutException with - * {@link SpServerError#SP_STOP_ROLLOUT_FAILED} error. - * - * @param message of the error - */ public StopRolloutException(final String message) { - super(message, SpServerError.SP_STOP_ROLLOUT_FAILED); + super(SpServerError.SP_STOP_ROLLOUT_FAILED, message); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TargetTypeInUseException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TargetTypeInUseException.java index 07503b614..49beedb51 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TargetTypeInUseException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TargetTypeInUseException.java @@ -28,39 +28,7 @@ public class TargetTypeInUseException extends AbstractServerRtException { private static final SpServerError THIS_ERROR = SpServerError.SP_TARGET_TYPE_IN_USE; - /** - * Default constructor. - */ - public TargetTypeInUseException() { - super(THIS_ERROR); - } - - /** - * Parameterized constructor. - * - * @param cause of the exception - */ - public TargetTypeInUseException(final Throwable cause) { - super(THIS_ERROR, cause); - } - - /** - * Parameterized constructor. - * - * @param message of the exception - * @param cause of the exception - */ - public TargetTypeInUseException(final String message, final Throwable cause) { - super(message, THIS_ERROR, cause); - } - - /** - * Parameterized constructor. - * - * @param message of the exception - */ public TargetTypeInUseException(final String message) { - super(message, THIS_ERROR); + super(THIS_ERROR, message); } -} - +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TargetTypeKeyOrNameRequiredException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TargetTypeKeyOrNameRequiredException.java index e2c3952a3..3cece7c5d 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TargetTypeKeyOrNameRequiredException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TargetTypeKeyOrNameRequiredException.java @@ -28,11 +28,7 @@ public class TargetTypeKeyOrNameRequiredException extends AbstractServerRtExcept private static final SpServerError THIS_ERROR = SpServerError.SP_TARGET_TYPE_KEY_OR_NAME_REQUIRED; - /** - * Default constructor. - */ public TargetTypeKeyOrNameRequiredException(final String message) { - super(message, THIS_ERROR); + super(THIS_ERROR, message); } -} - +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantConfigurationValidatorException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantConfigurationValidatorException.java index 37a067097..3c25b28ac 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantConfigurationValidatorException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantConfigurationValidatorException.java @@ -28,12 +28,7 @@ public class TenantConfigurationValidatorException extends AbstractServerRtExcep private static final SpServerError THIS_ERROR = SpServerError.SP_CONFIGURATION_VALUE_INVALID; - /** - * Parameterized constructor. - * - * @param message of the exception - */ public TenantConfigurationValidatorException(final String message) { - super(message, THIS_ERROR); + super(THIS_ERROR, message); } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantConfigurationValueChangeNotAllowedException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantConfigurationValueChangeNotAllowedException.java index 31578cdbc..9796a754a 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantConfigurationValueChangeNotAllowedException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantConfigurationValueChangeNotAllowedException.java @@ -26,24 +26,7 @@ public class TenantConfigurationValueChangeNotAllowedException extends AbstractS @Serial private static final long serialVersionUID = 1L; - /** - * Creates a new exception for the - * {@link SpServerError#SP_CONFIGURATION_VALUE_CHANGE_NOT_ALLOWED} error - * case. - */ public TenantConfigurationValueChangeNotAllowedException() { super(SpServerError.SP_CONFIGURATION_VALUE_CHANGE_NOT_ALLOWED); } - - /** - * Creates a new exception for the - * {@link SpServerError#SP_CONFIGURATION_VALUE_CHANGE_NOT_ALLOWED} error - * case. - * - * @param message A custom error message. - */ - public TenantConfigurationValueChangeNotAllowedException(final String message) { - super(message, SpServerError.SP_CONFIGURATION_VALUE_CHANGE_NOT_ALLOWED); - } - -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantNotExistException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantNotExistException.java index 7f5be4bb6..4aa3759c4 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantNotExistException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantNotExistException.java @@ -29,38 +29,7 @@ public class TenantNotExistException extends AbstractServerRtException { private static final SpServerError THIS_ERROR = SpServerError.SP_REPO_TENANT_NOT_EXISTS; - /** - * Default constructor. - */ - public TenantNotExistException() { - super(THIS_ERROR); - } - - /** - * Parameterized constructor. - * - * @param cause of the exception - */ - public TenantNotExistException(final Throwable cause) { - super(THIS_ERROR, cause); - } - - /** - * Parameterized constructor. - * - * @param message of the exception - * @param cause of the exception - */ - public TenantNotExistException(final String message, final Throwable cause) { - super(message, THIS_ERROR, cause); - } - - /** - * Parameterized constructor. - * - * @param message of the exception - */ public TenantNotExistException(final String message) { - super(message, THIS_ERROR); + super(THIS_ERROR, message); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/UnsupportedSoftwareModuleForThisDistributionSetException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/UnsupportedSoftwareModuleForThisDistributionSetException.java index 99a5175d3..cd5fda48d 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/UnsupportedSoftwareModuleForThisDistributionSetException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/UnsupportedSoftwareModuleForThisDistributionSetException.java @@ -29,25 +29,7 @@ public class UnsupportedSoftwareModuleForThisDistributionSetException extends Ab @Serial private static final long serialVersionUID = 1L; - /** - * Creates a new UnsupportedSoftwareModuleForThisDistributionSetException - * with {@link SpServerError#SP_DS_MODULE_UNSUPPORTED} error. - */ public UnsupportedSoftwareModuleForThisDistributionSetException() { super(SpServerError.SP_DS_MODULE_UNSUPPORTED); } - - /** - * @param cause for the exception - */ - public UnsupportedSoftwareModuleForThisDistributionSetException(final Throwable cause) { - super(SpServerError.SP_DS_MODULE_UNSUPPORTED, cause); - } - - /** - * @param message of the error - */ - public UnsupportedSoftwareModuleForThisDistributionSetException(final String message) { - super(message, SpServerError.SP_DS_MODULE_UNSUPPORTED); - } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Action.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Action.java index a1cc0c508..7ac691e8d 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Action.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Action.java @@ -88,9 +88,8 @@ public interface Action extends TenantAwareBaseEntity { Target getTarget(); /** - * @return time in {@link TimeUnit#MILLISECONDS} after which - * {@link #isForced()} switches to true in case of - * {@link ActionType#TIMEFORCED}. + * @return time in {@link TimeUnit#MILLISECONDS} after which {@link #isForced()} switches to true in case + * of {@link ActionType#TIMEFORCED}. */ long getForcedTime(); @@ -140,22 +139,17 @@ public interface Action extends TenantAwareBaseEntity { String getInitiatedBy(); /** - * @return the latest action status code. Performance optimization to not - * query the action status table for the last action status code. + * @return the latest action status code. Performance optimization to not query the action status table for the last action status code. */ Optional getLastActionStatusCode(); /** - * checks if the {@link #getForcedTime()} is hit by the given - * {@code hitTimeMillis}, by means if the given milliseconds are greater + * Checks if the {@link #getForcedTime()} is hit by the given {@code hitTimeMillis}, by means if the given milliseconds are greater * than the forcedTime. * - * @param hitTimeMillis the milliseconds, mostly the - * {@link System#currentTimeMillis()} - * @return {@code true} if this {@link #getActionType()} is in - * {@link ActionType#TIMEFORCED} and the given {@code hitTimeMillis} - * is greater than the {@link #getForcedTime()} otherwise - * {@code false} + * @param hitTimeMillis the milliseconds, mostly the {@link System#currentTimeMillis()} + * @return {@code true} if this {@link #getActionType()} is in {@link ActionType#TIMEFORCED} and the given {@code hitTimeMillis} + * is greater than the {@link #getForcedTime()} otherwise {@code false} */ default boolean isHitAutoForceTime(final long hitTimeMillis) { if (ActionType.TIMEFORCED == getActionType()) { @@ -165,23 +159,17 @@ public interface Action extends TenantAwareBaseEntity { } /** - * Check if action type is either forced or time-forced and force-time is - * exceeded. + * Check if action type is either forced or time-forced and force-time is exceeded. * - * @return {@code true} if either the {@link #getActionType()} is - * {@link ActionType#FORCED} or {@link ActionType#TIMEFORCED} but then - * if the {@link #getForcedTime()} has been exceeded otherwise always - * {@code false} + * @return {@code true} if either the {@link #getActionType()} is {@link ActionType#FORCED} or {@link ActionType#TIMEFORCED} but then + * if the {@link #getForcedTime()} has been exceeded otherwise always {@code false} */ default boolean isForcedOrTimeForced() { - switch (getActionType()) { - case FORCED: - return true; - case TIMEFORCED: - return isHitAutoForceTime(System.currentTimeMillis()); - default: - return false; - } + return switch (getActionType()) { + case FORCED -> true; + case TIMEFORCED -> isHitAutoForceTime(System.currentTimeMillis()); + default -> false; + }; } /** @@ -192,15 +180,14 @@ public interface Action extends TenantAwareBaseEntity { } /** - * @return true when action is downloadonly, false otherwise + * @return true when action is download-only, false otherwise */ default boolean isDownloadOnly() { return ActionType.DOWNLOAD_ONLY == getActionType(); } /** - * Returns the start time of next available maintenance window for the - * {@link Action} as {@link ZonedDateTime}. If a maintenance window is + * Returns the start time of next available maintenance window for the {@link Action} as {@link ZonedDateTime}. If a maintenance window is * already active, the start time of currently active window is returned. * * @return the start time as { @link Optional}. @@ -208,32 +195,29 @@ public interface Action extends TenantAwareBaseEntity { Optional getMaintenanceWindowStartTime(); /** - * The method checks whether the action has a maintenance schedule defined - * for it. A maintenance schedule defines a set of maintenance windows - * during which actual update can be performed. A valid schedule defines at - * least one maintenance window. + * The method checks whether the action has a maintenance schedule defined for it. A maintenance schedule defines a set of maintenance + * windows during which actual update can be performed. A valid schedule defines at least one maintenance window. * * @return true if action has a maintenance schedule, else false. */ boolean hasMaintenanceSchedule(); /** - * The method checks whether the maintenance schedule has already lapsed for - * the action, i.e. there are no more windows available for maintenance. - * Controller manager uses the method to check if the maintenance schedule - * has lapsed, and automatically cancels the action if it is lapsed. + * The method checks whether the maintenance schedule has already lapsed for the action, i.e. there are no more windows available for + * maintenance. + * Controller manager uses the method to check if the maintenance schedule has lapsed, and automatically cancels the action if it is lapsed. * * @return true if maintenance schedule has lapsed, else false. */ boolean isMaintenanceScheduleLapsed(); /** - * The method checks whether a maintenance window is available for the - * action to proceed. If it is available, a 'true' value is returned. The - * maintenance window is considered available: 1) If there is no maintenance - * schedule at all, in which case device can start update any time after - * download is finished; or 2) the current time is within a scheduled - * maintenance window start and end time. + * The method checks whether a maintenance window is available for the action to proceed. If it is available, a 'true' value is returned. + * The maintenance window is considered available: + *
    + *
  1. if there is no maintenance schedule at all, in which case device can start update any time after download is finished; or
  2. + *
  3. the current time is within a scheduled maintenance window start and end time + *
* * @return true if maintenance window is available, else false. */ @@ -248,12 +232,12 @@ public interface Action extends TenantAwareBaseEntity { /** * Action status as reported by the controller. - * - * Be aware that JPA is persisting the ordinal number of the enum by means - * the ordered number in the enum. So don't re-order the enums within the - * Status enum declaration! + *

+ * Be aware that JPA is persisting the ordinal number of the enum by means the ordered number in the enum. So don't re-order the enums + * within the Status enum declaration! */ enum Status { + /** * Action is finished successfully for this target. */ @@ -285,7 +269,7 @@ public interface Action extends TenantAwareBaseEntity { CANCELING, /** - * Action has been send to the target. + * Action has been sent to the target. */ RETRIEVED, @@ -295,8 +279,7 @@ public interface Action extends TenantAwareBaseEntity { DOWNLOAD, /** - * Action is in waiting state, e.g. the action is scheduled in a rollout - * but not yet activated. + * Action is in waiting state, e.g. the action is scheduled in a rollout but not yet activated. */ SCHEDULED, @@ -306,8 +289,7 @@ public interface Action extends TenantAwareBaseEntity { CANCEL_REJECTED, /** - * Action has been downloaded by the target and waiting for update to - * start. + * Action has been downloaded by the target and waiting for update to start. */ DOWNLOADED, @@ -321,8 +303,9 @@ public interface Action extends TenantAwareBaseEntity { * The action type for this action relation. */ enum ActionType { + /** - * Forced action execution. Target is advised to executed immediately. + * Forced action execution. Target is advised to be executed immediately. */ FORCED, @@ -332,9 +315,7 @@ public interface Action extends TenantAwareBaseEntity { SOFT, /** - * {@link #SOFT} action execution until - * {@link Action#isHitAutoForceTime(long)} is reached, {@link #FORCED} - * after that. + * {@link #SOFT} action execution until {@link Action#isHitAutoForceTime(long)} is reached, {@link #FORCED} after that. */ TIMEFORCED, diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/ActionCancellationType.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/ActionCancellationType.java index 507bde5f7..e5141e5f7 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/ActionCancellationType.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/ActionCancellationType.java @@ -10,19 +10,22 @@ package org.eclipse.hawkbit.repository.model; /** - * Defines if and how actions should be canceled when : - * - invalidating a distribution set - * - stopping a rollout - * - deleting a rollout + * Defines if and how actions should be canceled when: + *

    + *
  • invalidating a distribution set
  • + *
  • stopping a rollout
  • + *
  • deleting a rollout
  • + *
*/ public enum ActionCancellationType { + /** - * will perform a FORCE action cancellation - will put them in CANCELED state. + * Will perform a FORCE action cancellation - will put them in CANCELED state. */ FORCE, /** - * will perform a SOFT action cancellation - will put them in CANCELING state. + * Will perform a SOFT action cancellation - will put them in CANCELING state. */ SOFT, @@ -30,4 +33,4 @@ public enum ActionCancellationType { * Used in distribution set invalidation - will ONLY invalidate the DS, will not change action status */ NONE -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/ActionProperties.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/ActionProperties.java index 2f93eac57..3f3f9df06 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/ActionProperties.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/ActionProperties.java @@ -14,10 +14,12 @@ import java.io.Serializable; import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.Data; +import lombok.NoArgsConstructor; /** * Holds properties for {@link Action} */ +@NoArgsConstructor // for serialization libs like jackson @Data public class ActionProperties implements Serializable { @@ -31,9 +33,6 @@ public class ActionProperties implements Serializable { private Action.Status status; - public ActionProperties() { - } - /** * Constructor * @@ -51,4 +50,4 @@ public class ActionProperties implements Serializable { public boolean isWaitingConfirmation() { return status == Action.Status.WAIT_FOR_CONFIRMATION; } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/ActionStatus.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/ActionStatus.java index da578ee43..3c0b47f6c 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/ActionStatus.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/ActionStatus.java @@ -21,8 +21,7 @@ import org.eclipse.hawkbit.repository.model.Action.Status; public interface ActionStatus extends TenantAwareBaseEntity { /** - * @return time in {@link TimeUnit#MILLISECONDS} when the status was - * reported. + * @return time in {@link TimeUnit#MILLISECONDS} when the status was reported. */ long getOccurredAt(); @@ -33,7 +32,7 @@ public interface ActionStatus extends TenantAwareBaseEntity { /** * @return the {@link Status} of this {@link ActionStatus}. Caused potentially a transition change of the {@link #getAction()} if - * different from the previous {@link #getStatus()} call. + * different from the previous getStatus call. */ Status getStatus(); diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Artifact.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Artifact.java index c18c38373..a4c414506 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Artifact.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Artifact.java @@ -9,12 +9,9 @@ */ package org.eclipse.hawkbit.repository.model; -import org.eclipse.hawkbit.repository.artifact.model.AbstractDbArtifact; - /** - * Binaries for a {@link SoftwareModule} Note: the decision which artifacts have - * to be downloaded are done on the device side. e.g. Full Package, Signatures, - * binary deltas + * Binaries for a {@link SoftwareModule} Note: the decision which artifacts have to be downloaded are done on the device side. e.g. + * Full Package, Signatures, binary deltas */ public interface Artifact extends TenantAwareBaseEntity { @@ -34,8 +31,7 @@ public interface Artifact extends TenantAwareBaseEntity { String getMd5Hash(); /** - * @return SHA-1 hash of the artifact in Base16 format that identifies the - * {@link AbstractDbArtifact} in the system. + * @return SHA-1 hash of the artifact in Base16 format. */ String getSha1Hash(); diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/ArtifactUpload.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/ArtifactUpload.java index 2718c4263..5365251a9 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/ArtifactUpload.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/ArtifactUpload.java @@ -14,75 +14,16 @@ import java.io.InputStream; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; -import lombok.Data; +import org.eclipse.hawkbit.artifact.model.ArtifactHashes; import org.eclipse.hawkbit.repository.ValidString; /** * Use to create a new artifact. */ -@Data -public class ArtifactUpload { - - @NotNull - private final InputStream inputStream; - - private final long moduleId; - - @NotEmpty - @ValidString - private final String filename; - - private final String providedMd5Sum; - - private final String providedSha1Sum; - - private final String providedSha256Sum; - - private final boolean overrideExisting; - - private final String contentType; - - private final long filesize; - - /** - * Constructor - * - * @param inputStream to read from for artifact binary - * @param moduleId to assign the new artifact to - * @param filename of the artifact - * @param overrideExisting to true if the artifact binary can be overridden - * if it already exists - * @param filesize the size of the file in bytes. - */ - public ArtifactUpload(final InputStream inputStream, final long moduleId, final String filename, - final boolean overrideExisting, final long filesize) { - this(inputStream, moduleId, filename, null, null, null, overrideExisting, null, filesize); - } - - /** - * Constructor - * - * @param inputStream to read from for artifact binary - * @param moduleId to assign the new artifact to - * @param filename of the artifact - * @param providedSha1Sum optional sha1 checksum to check the new file against - * @param providedMd5Sum optional md5 checksum to check the new file against - * @param overrideExisting to true if the artifact binary can be overridden if it already exists - * @param contentType the contentType of the file - * @param filesize the size of the file in bytes. - */ - @SuppressWarnings("java:S107") - public ArtifactUpload(final InputStream inputStream, final long moduleId, final String filename, - final String providedMd5Sum, final String providedSha1Sum, final String providedSha256Sum, - final boolean overrideExisting, final String contentType, final long filesize) { - this.inputStream = inputStream; - this.moduleId = moduleId; - this.filename = filename; - this.providedMd5Sum = providedMd5Sum; - this.providedSha1Sum = providedSha1Sum; - this.providedSha256Sum = providedSha256Sum; - this.overrideExisting = overrideExisting; - this.contentType = contentType; - this.filesize = filesize; - } -} +public record ArtifactUpload( + @NotNull InputStream inputStream, + String contentType, long filesize, + ArtifactHashes hash, + long moduleId, + @NotEmpty @ValidString String filename, + boolean overrideExisting) {} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/AssignedSoftwareModule.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/AssignedSoftwareModule.java deleted file mode 100644 index 69aa58ba6..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/AssignedSoftwareModule.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.model; - -import java.io.Serial; -import java.io.Serializable; - -import lombok.Data; -import org.eclipse.hawkbit.repository.Identifiable; - -/** - * Use to display software modules for the selected distribution. - */ -@Data -public class AssignedSoftwareModule implements Serializable, Identifiable { - - @Serial - private static final long serialVersionUID = 1L; - - private final SoftwareModule softwareModule; - - private final boolean assigned; - - /** - * Constructor. - * - * @param softwareModule entity. - * @param assigned as true if the software module is assigned and false if not - * assigned. - */ - public AssignedSoftwareModule(final SoftwareModule softwareModule, final boolean assigned) { - this.softwareModule = softwareModule; - this.assigned = assigned; - } - - @Override - public Long getId() { - return softwareModule.getId(); - } -} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/AutoConfirmationStatus.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/AutoConfirmationStatus.java index d4d57229f..e6c9214ca 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/AutoConfirmationStatus.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/AutoConfirmationStatus.java @@ -22,9 +22,8 @@ public interface AutoConfirmationStatus extends BaseEntity { Target getTarget(); /** - * The user who initiated the auto confirmation. Will be set on auto - * confirmation activation and could be null. In this case the created_by can be - * considered as initiator. + * The user who initiated the auto confirmation. Will be set on auto confirmation activation and could be null. In this case the created_by + * can be considered as initiator. * * @return the user */ @@ -47,9 +46,7 @@ public interface AutoConfirmationStatus extends BaseEntity { /** * Construct the action message based on the current status. * - * @return the constructed message which can be used for the action status as a - * message + * @return the constructed message which can be used for the action status as a message */ String constructActionMessage(); - -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/BaseEntity.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/BaseEntity.java index 10265016c..473b33cd8 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/BaseEntity.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/BaseEntity.java @@ -39,8 +39,7 @@ public interface BaseEntity extends Serializable, Identifiable { String getLastModifiedBy(); /** - * @return time in {@link TimeUnit#MILLISECONDS} when the {@link BaseEntity} - * was last time changed. + * @return time in {@link TimeUnit#MILLISECONDS} when the {@link BaseEntity} was last time changed. */ long getLastModifiedAt(); diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DeploymentRequest.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DeploymentRequest.java index 14be2a1fe..b0bd25490 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DeploymentRequest.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DeploymentRequest.java @@ -28,43 +28,34 @@ public class DeploymentRequest { private final TargetWithActionType targetWithActionType; /** - * Constructor that also accepts maintenance schedule parameters and checks for - * validity of the specified maintenance schedule. + * Constructor that also accepts maintenance schedule parameters and checks for validity of the specified maintenance schedule. * * @param controllerId for which the action is created. - * @param distributionSetId of the distribution set that that should be assigned to the - * controller. + * @param distributionSetId of the distribution set that that should be assigned to the controller. * @param actionType specified for the action. * @param forceTime at what time the type soft turns into forced. * @param weight the priority of an {@link Action}. - * @param maintenanceSchedule is the cron expression to be used for scheduling maintenance - * windows. Expression has 6 mandatory fields and 1 last optional - * field: "second minute hour dayofmonth month weekday year" - * @param maintenanceWindowDuration in HH:mm:ss format specifying the duration of a maintenance - * window, for example 00:30:00 for 30 minutes - * @param maintenanceWindowTimeZone is the time zone specified as +/-hh:mm offset from UTC, for - * example +02:00 for CET summer time and +00:00 for UTC. The start - * time of a maintenance window calculated based on the cron - * expression is relative to this time zone. - * @param confirmationRequired is a flag whether the confirmation should be required for the - * resulting {@link Action} or not. In case the confirmation is not - * required, the action will be automatically confirmed and put in - * the - * {@link org.eclipse.hawkbit.repository.model.Action.Status#RUNNING} - * state. Otherwise the confirmation flow will be triggered - * and the {@link Action} will stay in the - * {@link org.eclipse.hawkbit.repository.model.Action.Status#WAIT_FOR_CONFIRMATION} - * state until the confirmation is given. (Only considered - * with CONFIRMATION_FLOW active via tenant configuration) + * @param maintenanceSchedule is the cron expression to be used for scheduling maintenance windows. Expression has 6 mandatory + * fields and 1 last optional field: "second minute hour dayofmonth month weekday year" + * @param maintenanceWindowDuration in HH:mm:ss format specifying the duration of a maintenance window, for example 00:30:00 for 30 minutes + * @param maintenanceWindowTimeZone is the time zone specified as +/-hh:mm offset from UTC, for example +02:00 for CET summer time + * and +00:00 for UTC. The start time of a maintenance window calculated based on the cron expression is relative to this time zone. + * @param confirmationRequired is a flag whether the confirmation should be required for the resulting {@link Action} or not. In case the + * confirmation is not required, the action will be automatically confirmed and put in the + * {@link org.eclipse.hawkbit.repository.model.Action.Status#RUNNING} state. Otherwise, the confirmation flow will be triggered + * and the {@link Action} will stay in the {@link org.eclipse.hawkbit.repository.model.Action.Status#WAIT_FOR_CONFIRMATION} + * state until the confirmation is given. (Only considered with CONFIRMATION_FLOW active via tenant configuration) * @throws InvalidMaintenanceScheduleException if the parameters do not define a valid maintenance schedule. */ @SuppressWarnings("java:S107") - public DeploymentRequest(final String controllerId, final Long distributionSetId, final ActionType actionType, - final long forceTime, final Integer weight, final String maintenanceSchedule, - final String maintenanceWindowDuration, final String maintenanceWindowTimeZone, + public DeploymentRequest( + final String controllerId, final Long distributionSetId, final ActionType actionType, final long forceTime, final Integer weight, + final String maintenanceSchedule, final String maintenanceWindowDuration, final String maintenanceWindowTimeZone, final boolean confirmationRequired) { - this.targetWithActionType = new TargetWithActionType(controllerId, actionType, forceTime, weight, - maintenanceSchedule, maintenanceWindowDuration, maintenanceWindowTimeZone, confirmationRequired); + this.targetWithActionType = new TargetWithActionType( + controllerId, actionType, forceTime, weight, + maintenanceSchedule, maintenanceWindowDuration, maintenanceWindowTimeZone, + confirmationRequired); this.distributionSetId = distributionSetId; } @@ -72,13 +63,6 @@ public class DeploymentRequest { return targetWithActionType.getControllerId(); } - /** - * Build a {@link DeploymentRequest} for a target distribution set assignment - * - * @param controllerId ID of target - * @param distributionSetId ID of distribution set - * @return the builder - */ public static DeploymentRequestBuilder builder(final String controllerId, final long distributionSetId) { return new DeploymentRequestBuilder(controllerId, distributionSetId); } @@ -115,15 +99,11 @@ public class DeploymentRequest { /** * Set a maintenanceWindow * - * @param maintenanceSchedule is the cron expression to be used for scheduling maintenance - * windows. Expression has 6 mandatory fields and 1 last optional - * field: "second minute hour dayofmonth month weekday year" - * @param maintenanceWindowDuration in HH:mm:ss format specifying the duration of a maintenance - * window, for example 00:30:00 for 30 minutes - * @param maintenanceWindowTimeZone is the time zone specified as +/-hh:mm offset from UTC, for - * example +02:00 for CET summer time and +00:00 for UTC. The - * start time of a maintenance window calculated based on the - * cron expression is relative to this time zone. + * @param maintenanceSchedule is the cron expression to be used for scheduling maintenance windows. Expression has 6 mandatory fields + * and 1 last optional field: "second minute hour dayofmonth month weekday year" + * @param maintenanceWindowDuration in HH:mm:ss format specifying the duration of a maintenance window, for example 00:30:00 for 30 minutes + * @param maintenanceWindowTimeZone is the time zone specified as +/-hh:mm offset from UTC, for example +02:00 for CET summer time + * and +00:00 for UTC. The start time of a maintenance window calculated based on the cron expression is relative to this time zone. * @return builder */ public DeploymentRequestBuilder maintenance( diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSet.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSet.java index c0e3545d0..064ae03d8 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSet.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSet.java @@ -12,13 +12,10 @@ package org.eclipse.hawkbit.repository.model; import java.util.Set; /** - * A {@link DistributionSet} defines a meta package that combines a set of - * {@link SoftwareModule}s which have to be or are provisioned to a + * A {@link DistributionSet} defines a meta package that combines a set of {@link SoftwareModule}s which have to be or are provisioned to a * {@link Target}. - * *

* A {@link Target} has exactly one target {@link DistributionSet} assigned. - *

*/ public interface DistributionSet extends NamedVersionedEntity { @@ -43,34 +40,30 @@ public interface DistributionSet extends NamedVersionedEntity { Set getModules(); /** - * @return true if all defined - * {@link DistributionSetType#getMandatoryModuleTypes()} of - * {@link #getType()} are present in this {@link DistributionSet}. + * @return true if all defined {@link DistributionSetType#getMandatoryModuleTypes()} of {@link #getType()} are present in + * this {@link DistributionSet}. */ boolean isComplete(); /** - * @return true if this {@link DistributionSet} is locked. If so it's 'functional' - * properties (e.g. software modules) could not be modified anymore. + * @return true if this {@link DistributionSet} is locked. If so it's 'functional' properties (e.g. software modules) could not + * be modified anymore. */ boolean isLocked(); /** - * @return true if this {@link DistributionSet} is deleted and only kept for history - * purposes. + * @return true if this {@link DistributionSet} is deleted and only kept for history purposes. */ boolean isDeleted(); /** - * @return false if this {@link DistributionSet} is - * invalidated. + * @return false if this {@link DistributionSet} is invalidated. */ boolean isValid(); /** - * @return true if {@link DistributionSet} contains a mandatory - * migration step, i.e. unfinished {@link Action}s will kept active - * and not automatically canceled if overridden by a newer update. + * @return true if {@link DistributionSet} contains a mandatory migration step, i.e. unfinished {@link Action}s will be kept + * active and not automatically canceled if overridden by a newer update. */ boolean isRequiredMigrationStep(); } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSetInvalidationCount.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSetInvalidationCount.java index 62a8ffcb0..caf1a9fe9 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSetInvalidationCount.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSetInvalidationCount.java @@ -9,24 +9,8 @@ */ package org.eclipse.hawkbit.repository.model; -import lombok.Data; - /** - * object that holds information about the count of affected rollouts, - * auto-assignments and actions, when a list of distribution sets gets + * Object that holds information about the count of affected rollouts, auto-assignments and actions, when a list of distribution sets gets * invalidated */ -@Data -public class DistributionSetInvalidationCount { - - private final long rolloutsCount; - private final long autoAssignmentCount; - private final long actionCount; - - public DistributionSetInvalidationCount(final long rolloutsCount, final long autoAssignmentCount, - final long actionCount) { - this.rolloutsCount = rolloutsCount; - this.autoAssignmentCount = autoAssignmentCount; - this.actionCount = actionCount; - } -} \ No newline at end of file +public record DistributionSetInvalidationCount(long rolloutsCount, long autoAssignmentCount, long actionCount) {} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSetTag.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSetTag.java index 4473cb71e..603da8ea0 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSetTag.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSetTag.java @@ -12,6 +12,4 @@ package org.eclipse.hawkbit.repository.model; /** * {@link Tag} of a {@link DistributionSet}. */ -public interface DistributionSetTag extends Tag { - -} +public interface DistributionSetTag extends Tag {} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/PollStatus.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/PollStatus.java index dee2e9760..2a0d58727 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/PollStatus.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/PollStatus.java @@ -11,28 +11,11 @@ package org.eclipse.hawkbit.repository.model; import java.time.LocalDateTime; -import lombok.Data; - /** * The poll time object which holds all the necessary information around the target poll time, e.g. the last poll time, the next poll time and * the overdue poll time. */ -@Data -public class PollStatus { - - private final LocalDateTime lastPollDate; - private final LocalDateTime nextPollDate; - private final LocalDateTime overdueDate; - private final LocalDateTime currentDate; - - public PollStatus( - final LocalDateTime lastPollDate, final LocalDateTime nextPollDate, - final LocalDateTime overdueDate, final LocalDateTime currentDate) { - this.lastPollDate = lastPollDate; - this.nextPollDate = nextPollDate; - this.overdueDate = overdueDate; - this.currentDate = currentDate; - } +public record PollStatus(LocalDateTime lastPollDate, LocalDateTime nextPollDate, LocalDateTime overdueDate, LocalDateTime currentDate) { /** * Calculates if the target poll time is overdue and the target has not been polled in the configured poll time interval. diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/RepositoryModelConstants.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/RepositoryModelConstants.java index 7784a4978..fdda7a3ff 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/RepositoryModelConstants.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/RepositoryModelConstants.java @@ -9,18 +9,16 @@ */ package org.eclipse.hawkbit.repository.model; +import lombok.NoArgsConstructor; + /** * Repository model constants. */ +@NoArgsConstructor(access = lombok.AccessLevel.PRIVATE) public final class RepositoryModelConstants { /** - * indicating that target action has no force time which is only needed in - * case of {@link Action.ActionType#TIMEFORCED}. + * Indicating that target action has no force time which is only needed in case of {@link Action.ActionType#TIMEFORCED}. */ public static final Long NO_FORCE_TIME = 0L; - - private RepositoryModelConstants() { - // Utility class. - } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Rollout.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Rollout.java index a9459045a..c1aae72bd 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Rollout.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Rollout.java @@ -16,13 +16,11 @@ import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus.Status; /** - * Software update operations in large scale IoT scenarios with hundred of - * thousands of devices require special handling. - * - * That includes secure handling of large volumes of devices at rollout creation - * time. Monitoring of the rollout progress. Emergency rollout shutdown in case - * of problems on to many devices and reporting capabilities for a complete - * understanding of the rollout progress at each point in time. + * Software update operations in large scale IoT scenarios with hundred of thousands of devices require special handling. + *

+ * That includes secure handling of large volumes of devices at rollout creation time. Monitoring of the rollout progress. Emergency rollout + * shutdown in case of problems on to many devices and reporting capabilities for a complete understanding of the rollout progress at each point + * in time. */ public interface Rollout extends NamedEntity { @@ -48,8 +46,7 @@ public interface Rollout extends NamedEntity { DistributionSet getDistributionSet(); /** - * @return rsql query that identifies the targets that are part of this - * rollout. + * @return rsql query that identifies the targets that are part of this rollout. */ String getTargetFilterQuery(); @@ -64,15 +61,13 @@ public interface Rollout extends NamedEntity { ActionType getActionType(); /** - * @return time in {@link TimeUnit#MILLISECONDS} after which - * {@link #isForced()} switches to true in case of + * @return time in {@link TimeUnit#MILLISECONDS} after which 'is forced' switches to true in case of * {@link ActionType#TIMEFORCED}. */ long getForcedTime(); /** - * @return Timestamp when the rollout should be started automatically. Can - * be null. + * @return Timestamp when the rollout should be started automatically. Can be null. */ Long getStartAt(); @@ -123,7 +118,7 @@ public interface Rollout extends NamedEntity { enum RolloutStatus { /** - * Rollouts is being created. + * Rollout is being created. */ CREATING, @@ -178,9 +173,8 @@ public interface Rollout extends NamedEntity { DELETING, /** - * Rollout has been deleted. This state is only set in case of a - * soft-deletion of the rollout which keeps references, in case of an - * hard-deletion of a rollout the rollout-entry itself is deleted. + * Rollout has been deleted. This state is only set in case of a soft-deletion of the rollout which keeps references, in case of + * a hard-deletion of a rollout the rollout-entry itself is deleted. */ DELETED } @@ -189,8 +183,9 @@ public interface Rollout extends NamedEntity { * Enum that holds all possible approval workflow decisions. */ enum ApprovalDecision { + /** - * Representing an granted approval for a rollout. + * Representing a granted approval for a rollout. */ APPROVED, /** @@ -198,4 +193,4 @@ public interface Rollout extends NamedEntity { */ DENIED } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/RolloutGroup.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/RolloutGroup.java index 993e3c6ba..96c6a7c23 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/RolloutGroup.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/RolloutGroup.java @@ -10,9 +10,8 @@ package org.eclipse.hawkbit.repository.model; /** - * The core functionality of a {@link Rollout} is the cascading processing of - * (sub) deployment groups. The group defines under which conditions the - * following group is processed. + * The core functionality of a {@link Rollout} is the cascading processing of (sub) deployment groups. The group defines under which conditions + * the following group is processed. */ public interface RolloutGroup extends NamedEntity { @@ -27,8 +26,7 @@ public interface RolloutGroup extends NamedEntity { RolloutGroupStatus getStatus(); /** - * @return the parent group of this group, in case the group is the root - * group it does not have a parent and so return {@code null} + * @return the parent group of this group, in case the group is the root group it does not have a parent and so return {@code null} */ RolloutGroup getParent(); @@ -38,56 +36,46 @@ public interface RolloutGroup extends NamedEntity { boolean isDynamic(); /** - * @return the {@link RolloutGroupSuccessCondition} for this group to - * indicate when a group is successful + * @return the {@link RolloutGroupSuccessCondition} for this group to indicate when a group is successful */ RolloutGroupSuccessCondition getSuccessCondition(); /** - * @return a String representation of the expression to be evaluated by the - * {@link RolloutGroupSuccessCondition} to indicate if the condition - * is true, might be {@code null} if no expression must be set for - * the {@link RolloutGroupSuccessCondition} + * @return a String representation of the expression to be evaluated by the {@link RolloutGroupSuccessCondition} to indicate if the + * condition is true, might be {@code null} if no expression must be set for the {@link RolloutGroupSuccessCondition} */ String getSuccessConditionExp(); /** - * @return the {@link RolloutGroupErrorCondition} for this group to indicate - * when a group should marked as failed + * @return the {@link RolloutGroupErrorCondition} for this group to indicate when a group should be marked as failed */ RolloutGroupErrorCondition getErrorCondition(); /** - * @return a String representation of the expression to be evaluated by the - * {@link RolloutGroupErrorCondition} to indicate if the condition - * is true, might be {@code null} if no expression must be set for - * the {@link RolloutGroupErrorCondition} + * @return a String representation of the expression to be evaluated by the {@link RolloutGroupErrorCondition} to indicate if the condition + * is true, might be {@code null} if no expression must be set for the {@link RolloutGroupErrorCondition} */ String getErrorConditionExp(); /** - * @return a {@link RolloutGroupErrorAction} which is executed when the - * given {@link RolloutGroupErrorCondition} is met, might be + * @return a {@link RolloutGroupErrorAction} which is executed when the given {@link RolloutGroupErrorCondition} is met, might be * {@code null} if no error action is set */ RolloutGroupErrorAction getErrorAction(); /** - * @return a String representation of the expression to be evaluated by the - * {@link RolloutGroupErrorAction} might be {@code null} if no + * @return a String representation of the expression to be evaluated by the {@link RolloutGroupErrorAction} might be {@code null} if no * expression must be set for the {@link RolloutGroupErrorAction} */ String getErrorActionExp(); /** - * @return the {@link RolloutGroupSuccessAction} which is executed if the - * {@link RolloutGroupSuccessCondition} is met + * @return the {@link RolloutGroupSuccessAction} which is executed if the {@link RolloutGroupSuccessCondition} is met */ RolloutGroupSuccessAction getSuccessAction(); /** - * @return a String representation of the expression to be evaluated by the - * {@link RolloutGroupSuccessAction} might be {@code null} if no + * @return a String representation of the expression to be evaluated by the {@link RolloutGroupSuccessAction} might be {@code null} if no * expression must be set for the {@link RolloutGroupSuccessAction} */ String getSuccessActionExp(); @@ -103,20 +91,17 @@ public interface RolloutGroup extends NamedEntity { TotalTargetCountStatus getTotalTargetCountStatus(); /** - * @return the target filter query, that is used to assign Targets to this - * Group + * @return the target filter query, that is used to assign Targets to this Group */ String getTargetFilterQuery(); /** - * @return the percentage of matching Targets that should be assigned to - * this Group + * @return the percentage of matching Targets that should be assigned to this Group */ float getTargetPercentage(); /** - * @return if a confirmation is required for the resulting actions (considered - * with confirmation flow active only) + * @return if a confirmation is required for the resulting actions (considered with confirmation flow active only) */ boolean isConfirmationRequired(); @@ -158,14 +143,14 @@ public interface RolloutGroup extends NamedEntity { } /** - * The condition to evaluate if an group is success state. + * The condition to evaluate if a group is success state. */ enum RolloutGroupSuccessCondition { THRESHOLD } /** - * The condition to evaluate if an group is in error state. + * The condition to evaluate if a group is in error state. */ enum RolloutGroupErrorCondition { THRESHOLD @@ -186,4 +171,4 @@ public interface RolloutGroup extends NamedEntity { enum RolloutGroupSuccessAction { NEXTGROUP } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/RolloutGroupsValidation.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/RolloutGroupsValidation.java index 5426f2b7b..0b84c2b64 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/RolloutGroupsValidation.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/RolloutGroupsValidation.java @@ -11,38 +11,13 @@ package org.eclipse.hawkbit.repository.model; import java.util.List; -import jakarta.validation.constraints.NotNull; - -import lombok.Data; - /** - * Represents information to validate the correct distribution of targets to - * rollout groups. + * Represents information to validate the correct distribution of targets into rollout groups. + * + * @param totalTargets The total amount of targets in a {@link Rollout} + * @param targetsPerGroup A list containing the count of targets for each {@link RolloutGroup} */ -@Data -public class RolloutGroupsValidation { - - /** - * The total amount of targets in a {@link Rollout} - */ - private final long totalTargets; - - /** - * A list containing the count of targets for each {@link RolloutGroup} - */ - private final List targetsPerGroup; - - /** - * Instantiates a new validation result - * - * @param totalTargets The total amount of targets in a {@link Rollout} - * @param targetsPerGroup A list containing the count of targets for each - * {@link RolloutGroup} - */ - public RolloutGroupsValidation(final long totalTargets, @NotNull final List targetsPerGroup) { - this.totalTargets = totalTargets; - this.targetsPerGroup = targetsPerGroup; - } +public record RolloutGroupsValidation(long totalTargets, List targetsPerGroup) { /** * @return the count of targets that are in groups diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/SoftwareModuleType.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/SoftwareModuleType.java index 7bcf3b92c..0521b0044 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/SoftwareModuleType.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/SoftwareModuleType.java @@ -10,15 +10,13 @@ package org.eclipse.hawkbit.repository.model; /** - * {@link SoftwareModuleType} is an abstract definition used in - * {@link DistributionSetType}s and includes additional {@link SoftwareModule} + * {@link SoftwareModuleType} is an abstract definition used in {@link DistributionSetType}s and includes additional {@link SoftwareModule} * specific information. */ public interface SoftwareModuleType extends Type { /** - * @return maximum assignments of an {@link SoftwareModule} of this type to - * a {@link DistributionSet}. + * @return maximum assignments of an {@link SoftwareModule} of this type to a {@link DistributionSet}. */ int getMaxAssignments(); } diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Statistic.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Statistic.java index a86e2fdff..9f9668042 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Statistic.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Statistic.java @@ -21,4 +21,4 @@ public interface Statistic { * @return the value of the Statistic entity. */ Object getData(); -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Tag.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Tag.java index e1ff625c0..e80b69692 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Tag.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Tag.java @@ -23,5 +23,4 @@ public interface Tag extends NamedEntity { * @return colour code of the tag used in Management UI. */ String getColour(); - -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Target.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Target.java index 11d8d33bd..db2ebcb87 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Target.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Target.java @@ -66,13 +66,6 @@ public interface Target extends NamedEntity, Identifiable { */ String getSecurityToken(); - /** - * @return {@link TargetWithActionType} with default settings - */ - default TargetWithActionType getTargetWithActionType() { - return new TargetWithActionType(getControllerId()); - } - /** * @return the address under which the target can be reached */ diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetFilterQuery.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetFilterQuery.java index b9af43c03..6eef11b8b 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetFilterQuery.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetFilterQuery.java @@ -18,7 +18,7 @@ import org.eclipse.hawkbit.repository.model.Action.ActionType; /** * Managed filter entity. - * + *

* Supported operators. *

    *
  • {@code Equal to : ==}
  • @@ -93,4 +93,4 @@ public interface TargetFilterQuery extends TenantAwareBaseEntity { * performing the auto-assignment by the scheduler */ Optional getAccessControlContext(); -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetTag.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetTag.java index eb0e3cc02..ec5dc0601 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetTag.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetTag.java @@ -12,6 +12,4 @@ package org.eclipse.hawkbit.repository.model; /** * Target tag element. */ -public interface TargetTag extends Tag { - -} +public interface TargetTag extends Tag {} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetType.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetType.java index c8ee1b18a..4e8810668 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetType.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetType.java @@ -12,13 +12,12 @@ package org.eclipse.hawkbit.repository.model; import java.util.Set; /** - * A {@link TargetType} is an abstract definition for - * {@link Target} + * A {@link TargetType} is an abstract definition for {@link Target} */ public interface TargetType extends Type { /** - * Target type doesn't support soft-delete so all target type instandces re not deleted. + * Target type doesn't support soft-delete so all target type instances are not deleted. * * @return false */ @@ -38,7 +37,6 @@ public interface TargetType extends Type { * Unassigns a {@link DistributionSetType} from {@link TargetType} * * @param dsTypeId that will be removed from {@link TargetType} - * @return the resulting target type */ void removeDistributionSetType(final Long dsTypeId); -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetUpdateStatus.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetUpdateStatus.java index 1b307747c..2cad717b9 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetUpdateStatus.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetUpdateStatus.java @@ -41,4 +41,4 @@ public enum TargetUpdateStatus { * Controller registered at SP but no {@link DistributionSet} assigned. */ REGISTERED -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetWithActionType.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetWithActionType.java index 95b2239af..b94d9599a 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetWithActionType.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetWithActionType.java @@ -34,49 +34,17 @@ public class TargetWithActionType { private final String maintenanceWindowTimeZone; /** - * Constructor that uses {@link ActionType#FORCED} - * - * @param controllerId ID if the controller - */ - public TargetWithActionType(final String controllerId) { - this(controllerId, ActionType.FORCED, 0, null, false); - } - - /** - * Constructor that leaves the maintenance info empty + * Constructor that also accepts maintenance schedule parameters and checks for validity of the specified maintenance schedule. * * @param controllerId for which the action is created. * @param actionType specified for the action. - * @param forceTime after that point in time the action is exposed as forced in case - * the type is {@link ActionType#TIMEFORCED} + * @param forceTime after that point in time the action is exposed as forced in case the type is {@link ActionType#TIMEFORCED} * @param weight the priority of an {@link Action} - * @param confirmationRequired sets the confirmation required flag when starting the - * {@link Action} - */ - public TargetWithActionType( - final String controllerId, final ActionType actionType, final long forceTime, - final Integer weight, final boolean confirmationRequired) { - this(controllerId, actionType, forceTime, weight, null, null, null, confirmationRequired); - } - - /** - * Constructor that also accepts maintenance schedule parameters and checks - * for validity of the specified maintenance schedule. - * - * @param controllerId for which the action is created. - * @param actionType specified for the action. - * @param forceTime after that point in time the action is exposed as forced in - * case the type is {@link ActionType#TIMEFORCED} - * @param weight the priority of an {@link Action} - * @param maintenanceSchedule is the cron expression to be used for scheduling maintenance - * windows. Expression has 6 mandatory fields and 1 last optional - * field: "second minute hour dayofmonth month weekday year" - * @param maintenanceWindowDuration in HH:mm:ss format specifying the duration of a maintenance - * window, for example 00:30:00 for 30 minutes - * @param maintenanceWindowTimeZone is the time zone specified as +/-hh:mm offset from UTC, for - * example +02:00 for CET summer time and +00:00 for UTC. The - * start time of a maintenance window calculated based on the - * cron expression is relative to this time zone. + * @param maintenanceSchedule is the cron expression to be used for scheduling maintenance windows. Expression has 6 mandatory fields + * and 1 last optional field: "second minute hour dayofmonth month weekday year" + * @param maintenanceWindowDuration in HH:mm:ss format specifying the duration of a maintenance window, for example 00:30:00 for 30 minutes + * @param maintenanceWindowTimeZone is the time zone specified as +/-hh:mm offset from UTC, for example +02:00 for CET summer time + * and +00:00 for UTC. The start time of a maintenance window calculated based on the cron expression is relative to this time zone. * @throws InvalidMaintenanceScheduleException if the parameters do not define a valid maintenance schedule. */ @SuppressWarnings("java:S107") @@ -86,13 +54,13 @@ public class TargetWithActionType { final boolean confirmationRequired) { this.controllerId = controllerId; this.actionType = actionType != null ? actionType : ActionType.FORCED; - this.forceTime = actionType == ActionType.TIMEFORCED ? - forceTime : RepositoryModelConstants.NO_FORCE_TIME; + this.forceTime = actionType == ActionType.TIMEFORCED ? forceTime : RepositoryModelConstants.NO_FORCE_TIME; this.weight = weight; - this.confirmationRequired = confirmationRequired; this.maintenanceSchedule = maintenanceSchedule; this.maintenanceWindowDuration = maintenanceWindowDuration; this.maintenanceWindowTimeZone = maintenanceWindowTimeZone; + + this.confirmationRequired = confirmationRequired; } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TenantAwareBaseEntity.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TenantAwareBaseEntity.java index 7973dd2ee..1382ec616 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TenantAwareBaseEntity.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TenantAwareBaseEntity.java @@ -18,4 +18,4 @@ public interface TenantAwareBaseEntity extends BaseEntity { * @return tenant name */ String getTenant(); -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TenantConfiguration.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TenantConfiguration.java index d9c4b27fd..1fbf9e2d0 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TenantConfiguration.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TenantConfiguration.java @@ -10,8 +10,7 @@ package org.eclipse.hawkbit.repository.model; /** - * Unstructured tenant configuration elements. Can be used to store arbitrary - * tenant configuration elements. + * Unstructured tenant configuration elements. Can be used to store arbitrary tenant configuration elements. */ public interface TenantConfiguration extends TenantAwareBaseEntity { diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TenantConfigurationValue.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TenantConfigurationValue.java index 875c21b48..527e6e22a 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TenantConfigurationValue.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TenantConfigurationValue.java @@ -32,5 +32,6 @@ public final class TenantConfigurationValue implements S private String lastModifiedBy; private Long createdAt; private String createdBy; + @Builder.Default private boolean global = true; } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TotalTargetCountActionStatus.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TotalTargetCountActionStatus.java index facaec42a..83ccc5f93 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TotalTargetCountActionStatus.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TotalTargetCountActionStatus.java @@ -31,4 +31,4 @@ public class TotalTargetCountActionStatus { public TotalTargetCountActionStatus(final Action.Status status, final Long count) { this(null, status, count); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TotalTargetCountStatus.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TotalTargetCountStatus.java index 8a586be0b..d84d675a0 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TotalTargetCountStatus.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TotalTargetCountStatus.java @@ -15,8 +15,7 @@ import java.util.List; import java.util.Map; /** - * Store target count of a {@link Rollout} or {@link RolloutGroup} for every - * {@link Status}. + * Store target count of a {@link Rollout} or {@link RolloutGroup} for every {@link Status}. */ public class TotalTargetCountStatus { @@ -31,8 +30,10 @@ public class TotalTargetCountStatus { * @param totalTargetCount the total target count * @param rolloutType the type of the rollout */ - public TotalTargetCountStatus(final List targetCountActionStatus, - final Long totalTargetCount, final Action.ActionType rolloutType) { + public TotalTargetCountStatus( + final List targetCountActionStatus, + final Long totalTargetCount, + final Action.ActionType rolloutType) { this.totalTargetCount = totalTargetCount; this.rolloutType = rolloutType; addToTotalCount(targetCountActionStatus); @@ -48,15 +49,6 @@ public class TotalTargetCountStatus { this(Collections.emptyList(), totalTargetCount, rolloutType); } - /** - * The current state mape which the total target count - * - * @return the statusTotalCountMap the state map - */ - public Map getStatusTotalCountMap() { - return statusTotalCountMap; - } - /** * Gets the total target count from a state. * @@ -75,12 +67,6 @@ public class TotalTargetCountStatus { return ((float) getTotalTargetCountByStatus(TotalTargetCountStatus.Status.FINISHED) / totalTargetCount) * 100; } - /** - * Populate all target status to a the given map - * - * @param statusTotalCountMap the map - * @param rolloutStatusCountItems all target {@link Status} with total count - */ private void addToTotalCount(final List targetCountActionStatus) { if (targetCountActionStatus == null) { statusTotalCountMap.put(TotalTargetCountStatus.Status.NOTSTARTED, totalTargetCount); @@ -100,26 +86,18 @@ public class TotalTargetCountStatus { statusTotalCountMap.merge(status, item.getCount(), Long::sum); } - // Exception squid:MethodCyclomaticComplexity - simple state conversion, not - // really complex. + // Exception squid:MethodCyclomaticComplexity - simple state conversion, not really complex. @SuppressWarnings("squid:MethodCyclomaticComplexity") private Status convertStatus(final Action.Status status) { - switch (status) { - case SCHEDULED: - return Status.SCHEDULED; - case ERROR: - return Status.ERROR; - case FINISHED: - return Status.FINISHED; - case CANCELED: - return Status.CANCELLED; - case RETRIEVED, RUNNING, WARNING, DOWNLOAD, WAIT_FOR_CONFIRMATION, CANCELING: - return Status.RUNNING; - case DOWNLOADED: - return Action.ActionType.DOWNLOAD_ONLY == rolloutType ? Status.FINISHED : Status.RUNNING; - default: - throw new IllegalArgumentException("State " + status + "is not valid"); - } + return switch (status) { + case SCHEDULED -> Status.SCHEDULED; + case ERROR -> Status.ERROR; + case FINISHED -> Status.FINISHED; + case CANCELED -> Status.CANCELLED; + case RETRIEVED, RUNNING, WARNING, DOWNLOAD, WAIT_FOR_CONFIRMATION, CANCELING -> Status.RUNNING; + case DOWNLOADED -> Action.ActionType.DOWNLOAD_ONLY == rolloutType ? Status.FINISHED : Status.RUNNING; + default -> throw new IllegalArgumentException("State " + status + "is not valid"); + }; } /** diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/report/model/SystemUsageReport.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/report/SystemUsageReport.java similarity index 64% rename from hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/report/model/SystemUsageReport.java rename to hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/report/SystemUsageReport.java index 81e2961ce..4b9be5cef 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/report/model/SystemUsageReport.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/report/SystemUsageReport.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others + * Copyright (c) 2025 Contributors to the Eclipse Foundation * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.report.model; +package org.eclipse.hawkbit.repository.model.report; import lombok.Data; @@ -23,16 +23,8 @@ public class SystemUsageReport { private final long overallActions; private final long overallTenants; - /** - * Constructor. - * - * @param overallTargets of the system - * @param overallArtifacts of the system - * @param overallActions of the system - * @param overallArtifactVolumeInBytes of the system - * @param overallTenants of the system - */ - public SystemUsageReport(final long overallTargets, final long overallArtifacts, final long overallActions, + public SystemUsageReport( + final long overallTargets, final long overallArtifacts, final long overallActions, final long overallArtifactVolumeInBytes, final long overallTenants) { this.overallTargets = overallTargets; this.overallArtifacts = overallArtifacts; @@ -40,4 +32,4 @@ public class SystemUsageReport { this.overallArtifactVolumeInBytes = overallArtifactVolumeInBytes; this.overallTenants = overallTenants; } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/report/model/SystemUsageReportWithTenants.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/report/SystemUsageReportWithTenants.java similarity index 65% rename from hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/report/model/SystemUsageReportWithTenants.java rename to hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/report/SystemUsageReportWithTenants.java index f8b282279..e5bffbbb5 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/report/model/SystemUsageReportWithTenants.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/report/SystemUsageReportWithTenants.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others + * Copyright (c) 2025 Contributors to the Eclipse Foundation * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.report.model; +package org.eclipse.hawkbit.repository.model.report; import java.util.ArrayList; import java.util.Collections; @@ -23,31 +23,17 @@ public class SystemUsageReportWithTenants extends SystemUsageReport { private final List tenants = new ArrayList<>(); - /** - * Constructor. - * - * @param overallTargets of the system - * @param overallArtifacts of the system - * @param overallActions of the system - * @param overallArtifactVolumeInBytes of the system - */ - public SystemUsageReportWithTenants(final long overallTargets, final long overallArtifacts, + public SystemUsageReportWithTenants( + final long overallTargets, final long overallArtifacts, final long overallActions, final long overallArtifactVolumeInBytes, final long overallTenants) { super(overallTargets, overallArtifacts, overallActions, overallArtifactVolumeInBytes, overallTenants); } - /** - * @param tenantUsage of one tenant - * @return updated bean - */ public SystemUsageReportWithTenants addTenantData(final TenantUsage tenantUsage) { tenants.add(tenantUsage); return this; } - /** - * @return tenant data - */ public List getTenants() { return Collections.unmodifiableList(tenants); } diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/report/model/TenantUsage.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/report/TenantUsage.java similarity index 73% rename from hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/report/model/TenantUsage.java rename to hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/report/TenantUsage.java index b04215c62..4b71a0c1f 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/report/model/TenantUsage.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/report/TenantUsage.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others + * Copyright (c) 2025 Contributors to the Eclipse Foundation * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -7,7 +7,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.eclipse.hawkbit.repository.report.model; +package org.eclipse.hawkbit.repository.model.report; import java.util.Collections; import java.util.HashMap; @@ -28,11 +28,6 @@ public class TenantUsage { private long overallArtifactVolumeInBytes; private Map usageData; - /** - * Constructor. - * - * @param tenantName name of the tenant - */ public TenantUsage(final String tenantName) { this.tenantName = tenantName; } @@ -41,13 +36,6 @@ public class TenantUsage { return Collections.unmodifiableMap(getLazyUsageData()); } - /** - * Add a key and value as usage data to the system usage stats. - * - * @param key the key to set - * @param value the value to set - * @return tenant stats element with new usage added - */ public TenantUsage addUsageData(final String key, final String value) { getLazyUsageData().put(key, value); return this; diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/utils/TenantConfigHelper.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/utils/TenantConfigHelper.java index 4a8e6a097..59811874f 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/utils/TenantConfigHelper.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/utils/TenantConfigHelper.java @@ -28,7 +28,8 @@ public final class TenantConfigHelper { private final TenantConfigurationManagement tenantConfigurationManagement; private final SystemSecurityContext systemSecurityContext; - private TenantConfigHelper(final SystemSecurityContext systemSecurityContext, + private TenantConfigHelper( + final SystemSecurityContext systemSecurityContext, final TenantConfigurationManagement tenantConfigurationManagement) { this.systemSecurityContext = systemSecurityContext; this.tenantConfigurationManagement = tenantConfigurationManagement; @@ -41,14 +42,14 @@ public final class TenantConfigHelper { * @param tenantConfigurationManagement to get the value from * @return is active */ - public static TenantConfigHelper usingContext(final SystemSecurityContext systemSecurityContext, + public static TenantConfigHelper usingContext( + final SystemSecurityContext systemSecurityContext, final TenantConfigurationManagement tenantConfigurationManagement) { return new TenantConfigHelper(systemSecurityContext, tenantConfigurationManagement); } public T getConfigValue(final String key, final Class valueType) { - return systemSecurityContext - .runAsSystem(() -> tenantConfigurationManagement.getConfigurationValue(key, valueType).getValue()); + return systemSecurityContext.runAsSystem(() -> tenantConfigurationManagement.getConfigurationValue(key, valueType).getValue()); } /** @@ -72,4 +73,4 @@ public final class TenantConfigHelper { public Function pollStatusResolver() { return tenantConfigurationManagement.pollStatusResolver(); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/model/TotalTargetCountStatusTest.java b/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/model/TotalTargetCountStatusTest.java index 7e1918ec0..e3871ee24 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/model/TotalTargetCountStatusTest.java +++ b/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/model/TotalTargetCountStatusTest.java @@ -69,7 +69,7 @@ class TotalTargetCountStatusTest { } /** - * DownloadOnly actions should be displayed as FINISHED when they have ActionStatus.DOWNLOADED + * DownloadOnly actions should be displayed as FINISHED when they have ActionStatus#DOWNLOADED */ @Test void shouldCorrectlyMapActionStatusesInDownloadOnlyCase() { diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/event/EventPublisherConfiguration.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/event/EventPublisherConfiguration.java index 28a8fdd0e..d197cc0ce 100644 --- a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/event/EventPublisherConfiguration.java +++ b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/event/EventPublisherConfiguration.java @@ -128,9 +128,6 @@ public class EventPublisherConfiguration { @ConditionalOnClass({ Schema.class, ProtostuffIOUtil.class }) protected static class EventProtostuffConfiguration { - /** - * @return the protostuff io message converter - */ @Bean public MessageConverter eventProtostuffMessageConverter() { return new EventProtoStuffMessageConverter(); diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/RolloutStatusCache.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/RolloutStatusCache.java index 708506df6..4a465c297 100644 --- a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/RolloutStatusCache.java +++ b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/RolloutStatusCache.java @@ -18,8 +18,8 @@ import java.util.stream.Collectors; import jakarta.validation.constraints.NotNull; import com.github.benmanes.caffeine.cache.Caffeine; -import org.eclipse.hawkbit.cache.TenancyCacheManager; -import org.eclipse.hawkbit.cache.TenantAwareCacheManager; +import org.eclipse.hawkbit.tenancy.cache.TenantCacheManager; +import org.eclipse.hawkbit.tenancy.cache.TenantAwareCacheManager; import org.eclipse.hawkbit.repository.event.remote.RolloutDeletedEvent; import org.eclipse.hawkbit.repository.event.remote.RolloutGroupDeletedEvent; import org.eclipse.hawkbit.repository.event.remote.RolloutStoppedEvent; @@ -41,7 +41,7 @@ public class RolloutStatusCache { private static final String CACHE_GR_NAME = "RolloutGroupStatus"; private static final long DEFAULT_SIZE = 50_000; - private final TenancyCacheManager cacheManager; + private final TenantCacheManager cacheManager; private final TenantAware tenantAware; /** diff --git a/hawkbit-repository/hawkbit-repository-jpa-api/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/ExceptionMapper.java b/hawkbit-repository/hawkbit-repository-jpa-api/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/ExceptionMapper.java index 7488a45d6..3a3a6946b 100644 --- a/hawkbit-repository/hawkbit-repository-jpa-api/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/ExceptionMapper.java +++ b/hawkbit-repository/hawkbit-repository-jpa-api/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/ExceptionMapper.java @@ -18,7 +18,6 @@ import java.util.Map; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.eclipse.hawkbit.exception.GenericSpServerException; -import org.eclipse.hawkbit.repository.exception.ConcurrentModificationException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; import org.springframework.dao.DuplicateKeyException; @@ -46,7 +45,6 @@ public class ExceptionMapper { MAPPED_EXCEPTION_ORDER.add(AccessDeniedException.class); EXCEPTION_MAPPING.put(DuplicateKeyException.class.getName(), EntityAlreadyExistsException.class.getName()); - EXCEPTION_MAPPING.put(OptimisticLockingFailureException.class.getName(), ConcurrentModificationException.class.getName()); EXCEPTION_MAPPING.put(AccessDeniedException.class.getName(), InsufficientPermissionException.class.getName()); EXCEPTION_MAPPING.put("org.hibernate.exception.ConstraintViolationException", EntityAlreadyExistsException.class.getName()); diff --git a/hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java b/hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java index 1b81f67b5..003ffe0cf 100644 --- a/hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java +++ b/hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java @@ -206,6 +206,6 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity { return SecurityContextHolder.getContext().getAuthentication() != null && SecurityContextHolder.getContext().getAuthentication().getDetails() instanceof TenantAwareAuthenticationDetails tenantAwareDetails && - tenantAwareDetails.isController(); + tenantAwareDetails.controller(); } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa-hibernate/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java b/hawkbit-repository/hawkbit-repository-jpa-hibernate/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java index ac3aa51a3..f006881b9 100644 --- a/hawkbit-repository/hawkbit-repository-jpa-hibernate/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java +++ b/hawkbit-repository/hawkbit-repository-jpa-hibernate/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java @@ -206,6 +206,6 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity { return SecurityContextHolder.getContext().getAuthentication() != null && SecurityContextHolder.getContext().getAuthentication() .getDetails() instanceof TenantAwareAuthenticationDetails tenantAwareDetails - && tenantAwareDetails.isController(); + && tenantAwareDetails.controller(); } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/EncryptionAwareDbArtifact.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/EncryptionAwareDbArtifact.java deleted file mode 100644 index 8e9ee5a60..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/EncryptionAwareDbArtifact.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright (c) 2021 Bosch.IO GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.jpa; - -import java.io.InputStream; -import java.util.function.UnaryOperator; - -import org.eclipse.hawkbit.repository.artifact.model.DbArtifact; -import org.eclipse.hawkbit.repository.artifact.model.DbArtifactHash; - -/** - * {@link DbArtifact} implementation that decrypts the underlying artifact - * binary input stream. - */ -public class EncryptionAwareDbArtifact implements DbArtifact { - - private final DbArtifact encryptedDbArtifact; - private final UnaryOperator decryptionFunction; - private final int encryptionOverhead; - - public EncryptionAwareDbArtifact(final DbArtifact encryptedDbArtifact, - final UnaryOperator decryptionFunction) { - this.encryptedDbArtifact = encryptedDbArtifact; - this.decryptionFunction = decryptionFunction; - this.encryptionOverhead = 0; - } - - public EncryptionAwareDbArtifact(final DbArtifact encryptedDbArtifact, - final UnaryOperator decryptionFunction, final int encryptionOverhead) { - this.encryptedDbArtifact = encryptedDbArtifact; - this.decryptionFunction = decryptionFunction; - this.encryptionOverhead = encryptionOverhead; - } - - @Override - public String getArtifactId() { - return encryptedDbArtifact.getArtifactId(); - } - - @Override - public DbArtifactHash getHashes() { - return encryptedDbArtifact.getHashes(); - } - - @Override - public long getSize() { - return encryptedDbArtifact.getSize() - encryptionOverhead; - } - - @Override - public String getContentType() { - return encryptedDbArtifact.getContentType(); - } - - @Override - public InputStream getFileInputStream() { - return decryptionFunction.apply(encryptedDbArtifact.getFileInputStream()); - } -} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRepositoryConfiguration.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRepositoryConfiguration.java index d759796a4..678960198 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRepositoryConfiguration.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRepositoryConfiguration.java @@ -20,6 +20,9 @@ import jakarta.validation.Validation; import io.micrometer.core.instrument.MeterRegistry; import org.aopalliance.intercept.MethodInvocation; import org.eclipse.hawkbit.ContextAware; +import org.eclipse.hawkbit.artifact.encryption.ArtifactEncryption; +import org.eclipse.hawkbit.artifact.encryption.ArtifactEncryptionSecretsStorage; +import org.eclipse.hawkbit.artifact.encryption.ArtifactEncryptionService; import org.eclipse.hawkbit.repository.DeploymentManagement; import org.eclipse.hawkbit.repository.PropertiesQuotaManagement; import org.eclipse.hawkbit.repository.QuotaManagement; @@ -31,13 +34,11 @@ import org.eclipse.hawkbit.repository.RolloutGroupManagement; import org.eclipse.hawkbit.repository.RolloutHandler; import org.eclipse.hawkbit.repository.RolloutManagement; import org.eclipse.hawkbit.repository.RolloutStatusCache; +import org.eclipse.hawkbit.repository.SecurityTokenGeneratorHolder; import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement; -import org.eclipse.hawkbit.repository.artifact.encryption.ArtifactEncryption; -import org.eclipse.hawkbit.repository.artifact.encryption.ArtifactEncryptionSecretsStore; -import org.eclipse.hawkbit.repository.artifact.encryption.ArtifactEncryptionService; import org.eclipse.hawkbit.repository.autoassign.AutoAssignExecutor; import org.eclipse.hawkbit.repository.event.ApplicationEventFilter; import org.eclipse.hawkbit.repository.event.remote.EventEntityManager; @@ -55,7 +56,6 @@ import org.eclipse.hawkbit.repository.jpa.cluster.LockProperties; import org.eclipse.hawkbit.repository.jpa.event.JpaEventEntityManager; import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitDefaultServiceExecutor; import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor; -import org.eclipse.hawkbit.repository.jpa.utils.ExceptionMapper; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.jpa.model.JpaArtifact; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; @@ -66,7 +66,6 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetType; import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder; import org.eclipse.hawkbit.repository.jpa.model.helper.EntityInterceptorHolder; -import org.eclipse.hawkbit.repository.SecurityTokenGeneratorHolder; import org.eclipse.hawkbit.repository.jpa.model.helper.TenantAwareHolder; import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository; import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetRepository; @@ -88,6 +87,7 @@ import org.eclipse.hawkbit.repository.jpa.rollout.condition.StartNextGroupRollou import org.eclipse.hawkbit.repository.jpa.rollout.condition.ThresholdRolloutGroupErrorCondition; import org.eclipse.hawkbit.repository.jpa.rollout.condition.ThresholdRolloutGroupSuccessCondition; import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility; +import org.eclipse.hawkbit.repository.jpa.utils.ExceptionMapper; import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.Target; @@ -525,7 +525,7 @@ public class JpaRepositoryConfiguration { /** * Default artifact encryption service bean that internally uses {@link ArtifactEncryption} and - * {@link ArtifactEncryptionSecretsStore} beans for {@link SoftwareModule} artifacts encryption/decryption + * {@link ArtifactEncryptionSecretsStorage} beans for {@link SoftwareModule} artifacts encryption/decryption * * @return a {@link ArtifactEncryptionService} bean */ diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaArtifactManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaArtifactManagement.java index 32a09c705..3cc83a771 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaArtifactManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaArtifactManagement.java @@ -16,23 +16,22 @@ import java.util.Optional; import jakarta.persistence.EntityManager; import lombok.extern.slf4j.Slf4j; +import org.eclipse.hawkbit.artifact.ArtifactStorage; +import org.eclipse.hawkbit.artifact.encryption.ArtifactEncryptionService; +import org.eclipse.hawkbit.artifact.exception.ArtifactBinaryNotFoundException; +import org.eclipse.hawkbit.artifact.exception.ArtifactDeleteFailedException; +import org.eclipse.hawkbit.artifact.exception.ArtifactStoreException; +import org.eclipse.hawkbit.artifact.exception.ArtifactUploadFailedException; +import org.eclipse.hawkbit.artifact.exception.HashNotMatchException; +import org.eclipse.hawkbit.artifact.model.ArtifactHashes; +import org.eclipse.hawkbit.artifact.model.ArtifactStream; +import org.eclipse.hawkbit.artifact.model.StoredArtifactInfo; import org.eclipse.hawkbit.repository.ArtifactManagement; import org.eclipse.hawkbit.repository.QuotaManagement; -import org.eclipse.hawkbit.repository.artifact.ArtifactRepository; -import org.eclipse.hawkbit.repository.artifact.encryption.ArtifactEncryptionService; -import org.eclipse.hawkbit.repository.artifact.exception.ArtifactBinaryNotFoundException; -import org.eclipse.hawkbit.repository.artifact.exception.ArtifactDeleteFailedException; -import org.eclipse.hawkbit.repository.artifact.exception.ArtifactStoreException; -import org.eclipse.hawkbit.repository.artifact.exception.ArtifactUploadFailedException; -import org.eclipse.hawkbit.repository.artifact.exception.HashNotMatchException; -import org.eclipse.hawkbit.repository.artifact.model.AbstractDbArtifact; -import org.eclipse.hawkbit.repository.artifact.model.DbArtifact; -import org.eclipse.hawkbit.repository.artifact.model.DbArtifactHash; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; -import org.eclipse.hawkbit.repository.exception.InvalidMD5HashException; -import org.eclipse.hawkbit.repository.exception.InvalidSHA1HashException; -import org.eclipse.hawkbit.repository.exception.InvalidSHA256HashException; -import org.eclipse.hawkbit.repository.jpa.EncryptionAwareDbArtifact; +import org.eclipse.hawkbit.repository.exception.InvalidMd5HashException; +import org.eclipse.hawkbit.repository.exception.InvalidSha1HashException; +import org.eclipse.hawkbit.repository.exception.InvalidSha256HashException; import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper; import org.eclipse.hawkbit.repository.jpa.acm.AccessController; import org.eclipse.hawkbit.repository.jpa.configuration.Constants; @@ -69,7 +68,7 @@ import org.springframework.validation.annotation.Validated; public class JpaArtifactManagement implements ArtifactManagement { private final LocalArtifactRepository localArtifactRepository; - private final ArtifactRepository artifactRepository; + private final ArtifactStorage artifactRepository; private final SoftwareModuleRepository softwareModuleRepository; private final EntityManager entityManager; private final PlatformTransactionManager txManager; @@ -78,7 +77,7 @@ public class JpaArtifactManagement implements ArtifactManagement { protected JpaArtifactManagement( final LocalArtifactRepository localArtifactRepository, - final Optional artifactRepository, + final Optional artifactRepository, final SoftwareModuleRepository softwareModuleRepository, final EntityManager entityManager, final PlatformTransactionManager txManager, @@ -102,42 +101,40 @@ public class JpaArtifactManagement implements ArtifactManagement { throw new UnsupportedOperationException(); } - final long moduleId = artifactUpload.getModuleId(); + final long moduleId = artifactUpload.moduleId(); QuotaHelper.assertAssignmentQuota( moduleId, 1, quotaManagement.getMaxArtifactsPerSoftwareModule(), Artifact.class, SoftwareModule.class, // get all artifacts without user context - softwareModuleId -> localArtifactRepository - .count(null, ArtifactSpecifications.bySoftwareModuleId(softwareModuleId))); + softwareModuleId -> localArtifactRepository.count(null, ArtifactSpecifications.bySoftwareModuleId(softwareModuleId))); final JpaSoftwareModule softwareModule = softwareModuleRepository.getById(moduleId); - final String filename = artifactUpload.getFilename(); + final String filename = artifactUpload.filename(); final Artifact existing = softwareModule.getArtifactByFilename(filename).orElse(null); if (existing != null) { - if (artifactUpload.isOverrideExisting()) { + if (artifactUpload.overrideExisting()) { log.debug("overriding existing artifact with new filename {}", filename); } else { throw new EntityAlreadyExistsException("File with that name already exists in the Software Module"); } } - // touch it to update the lock revision because we are modifying the - // DS indirectly, it will, also check UPDATE access + // touch it to update the lock revision because we are modifying the DS indirectly, it will, also check UPDATE access JpaManagementHelper.touch(entityManager, softwareModuleRepository, softwareModule); - final AbstractDbArtifact artifact = storeArtifact(artifactUpload, softwareModule.isEncrypted()); + final StoredArtifactInfo artifact = storeArtifact(artifactUpload, softwareModule.isEncrypted()); try { - return storeArtifactMetadata(softwareModule, filename, artifact, existing); + return storeArtifactMetadata(softwareModule, filename, artifact.getHashes(), artifact.getSize(), existing); } catch (final Exception e) { - artifactRepository.deleteBySha1(tenantAware.getCurrentTenant(), artifact.getHashes().getSha1()); + artifactRepository.deleteBySha1(tenantAware.getCurrentTenant(), artifact.getHashes().sha1()); throw e; } } @SuppressWarnings("java:S2201") // java:S2201 - the idea is to just check if the artifact exists @Override - public DbArtifact loadArtifactBinary(final String sha1Hash, final long softwareModuleId, final boolean isEncrypted) { + public ArtifactStream getArtifactStream(final String sha1Hash, final long softwareModuleId, final boolean isEncrypted) { if (artifactRepository == null) { throw new UnsupportedOperationException(); } @@ -146,8 +143,15 @@ public class JpaArtifactManagement implements ArtifactManagement { // check access to the software module and if artifact belongs to it for (final Artifact artifact : softwareModuleRepository.getById(softwareModuleId).getArtifacts()) { if (artifact.getSha1Hash().equals(sha1Hash)) { - final DbArtifact dbArtifact = artifactRepository.getBySha1(tenant, sha1Hash); - return isEncrypted ? wrapInEncryptionAwareDbArtifact(softwareModuleId, dbArtifact) : dbArtifact; + if (isEncrypted) { + final ArtifactEncryptionService encryptionService = ArtifactEncryptionService.getInstance(); + return new ArtifactStream( + encryptionService.decryptArtifact(softwareModuleId, artifactRepository.getBySha1(tenant, sha1Hash)), + artifact.getSize() - encryptionService.encryptionSizeOverhead(), + artifact.getSha1Hash()); + } else { + return new ArtifactStream(artifactRepository.getBySha1(tenant, sha1Hash), artifact.getSize(), artifact.getSha1Hash()); + } } } throw new ArtifactBinaryNotFoundException(sha1Hash); @@ -208,27 +212,23 @@ public class JpaArtifactManagement implements ArtifactManagement { }); } - private AbstractDbArtifact storeArtifact(final ArtifactUpload artifactUpload, final boolean isSmEncrypted) { - final InputStream stream = artifactUpload.getInputStream(); + private StoredArtifactInfo storeArtifact(final ArtifactUpload artifactUpload, final boolean isSmEncrypted) { + final InputStream stream = artifactUpload.inputStream(); try (final InputStream wrappedStream = wrapInQuotaStream( - isSmEncrypted - ? wrapInEncryptionStream(artifactUpload.getModuleId(), stream) - : stream)) { + isSmEncrypted ? wrapInEncryptionStream(artifactUpload.moduleId(), stream) : stream)) { return artifactRepository.store( - tenantAware.getCurrentTenant(), wrappedStream, artifactUpload.getFilename(), artifactUpload.getContentType(), - new DbArtifactHash( - artifactUpload.getProvidedSha1Sum(), - artifactUpload.getProvidedMd5Sum(), - artifactUpload.getProvidedSha256Sum())); + tenantAware.getCurrentTenant(), + wrappedStream, artifactUpload.filename(), + artifactUpload.contentType(), artifactUpload.hash()); } catch (final ArtifactStoreException | IOException e) { throw new ArtifactUploadFailedException(e); } catch (final HashNotMatchException e) { if (e.getHashFunction().equals(HashNotMatchException.SHA1)) { - throw new InvalidSHA1HashException(e.getMessage(), e); + throw new InvalidSha1HashException(e.getMessage(), e); } else if (e.getHashFunction().equals(HashNotMatchException.SHA256)) { - throw new InvalidSHA256HashException(e.getMessage(), e); + throw new InvalidSha256HashException(e.getMessage(), e); } else { - throw new InvalidMD5HashException(e.getMessage(), e); + throw new InvalidMd5HashException(e.getMessage(), e); } } } @@ -243,33 +243,23 @@ public class JpaArtifactManagement implements ArtifactManagement { final long currentlyUsed = localArtifactRepository.sumOfNonDeletedArtifactSize().orElse(0L); final long maxArtifactSizeTotal = quotaManagement.getMaxArtifactStorage(); - return new FileSizeAndStorageQuotaCheckingInputStream(in, maxArtifactSize, - maxArtifactSizeTotal - currentlyUsed); - } - - private DbArtifact wrapInEncryptionAwareDbArtifact(final long softwareModuleId, final DbArtifact dbArtifact) { - if (dbArtifact == null) { - return null; - } - final ArtifactEncryptionService encryptionService = ArtifactEncryptionService.getInstance(); - return new EncryptionAwareDbArtifact(dbArtifact, - stream -> encryptionService.decryptArtifact(softwareModuleId, stream), - encryptionService.encryptionSizeOverhead()); + return new FileSizeAndStorageQuotaCheckingInputStream(in, maxArtifactSize, maxArtifactSizeTotal - currentlyUsed); } private Artifact storeArtifactMetadata( - final SoftwareModule softwareModule, final String providedFilename, final AbstractDbArtifact result, + final SoftwareModule softwareModule, final String providedFilename, + final ArtifactHashes hash, final long fileSize, final Artifact existing) { final JpaArtifact artifact; if (existing == null) { - artifact = new JpaArtifact(result.getHashes().getSha1(), providedFilename, softwareModule); + artifact = new JpaArtifact(hash.sha1(), providedFilename, softwareModule); } else { artifact = (JpaArtifact) existing; - artifact.setSha1Hash(result.getHashes().getSha1()); + artifact.setSha1Hash(hash.sha1()); } - artifact.setMd5Hash(result.getHashes().getMd5()); - artifact.setSha256Hash(result.getHashes().getSha256()); - artifact.setFileSize(result.getSize()); + artifact.setMd5Hash(hash.md5()); + artifact.setSha256Hash(hash.sha256()); + artifact.setFileSize(fileSize); log.debug("storing new artifact into repository {}", artifact); return localArtifactRepository.save(AccessController.Operation.CREATE, artifact); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaConfirmationManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaConfirmationManagement.java index 8c6ce33ab..f911af3e7 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaConfirmationManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaConfirmationManagement.java @@ -146,7 +146,7 @@ public class JpaConfirmationManagement extends JpaActionManagement implements Co } @Override - public Optional getStatus(final String controllerId) { + public Optional findStatus(final String controllerId) { return Optional.of(targetRepository.getWithDetailsByControllerId(controllerId, JpaTarget_.GRAPH_TARGET_AUTO_CONFIRMATION_STATUS)) .map(JpaTarget::getAutoConfirmationStatus); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java index b094b549f..5e855d6a1 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java @@ -55,7 +55,6 @@ import org.eclipse.hawkbit.repository.RepositoryConstants; import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.SecurityTokenGeneratorHolder; import org.eclipse.hawkbit.repository.SoftwareModuleManagement; -import org.eclipse.hawkbit.repository.TargetTypeManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.UpdateMode; import org.eclipse.hawkbit.repository.event.EventPublisherHolder; @@ -66,6 +65,7 @@ import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.InvalidTargetAttributeException; +import org.eclipse.hawkbit.repository.exception.SoftwareModuleNotAssignedToTargetException; import org.eclipse.hawkbit.repository.jpa.Jpa; import org.eclipse.hawkbit.repository.jpa.acm.AccessController; import org.eclipse.hawkbit.repository.jpa.configuration.Constants; @@ -83,8 +83,10 @@ import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository; import org.eclipse.hawkbit.repository.jpa.repository.ActionStatusRepository; import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository; +import org.eclipse.hawkbit.repository.jpa.repository.TargetTypeRepository; import org.eclipse.hawkbit.repository.jpa.specifications.ActionSpecifications; import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications; +import org.eclipse.hawkbit.repository.jpa.specifications.TargetTypeSpecification; import org.eclipse.hawkbit.repository.jpa.utils.DeploymentHelper; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.model.Action; @@ -138,7 +140,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont // TODO - make it final private TargetRepository targetRepository; - private final TargetTypeManagement targetTypeManagement; + private final TargetTypeRepository targetTypeRepository; private final DeploymentManagement deploymentManagement; private final ConfirmationManagement confirmationManagement; private final SoftwareModuleRepository softwareModuleRepository; @@ -158,7 +160,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont protected JpaControllerManagement( final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository, final QuotaManagement quotaManagement, final RepositoryProperties repositoryProperties, - final TargetRepository targetRepository, final TargetTypeManagement targetTypeManagement, + final TargetRepository targetRepository, final TargetTypeRepository targetTypeRepository, final DeploymentManagement deploymentManagement, final ConfirmationManagement confirmationManagement, final SoftwareModuleRepository softwareModuleRepository, final SoftwareModuleManagement softwareModuleManagement, @@ -171,7 +173,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont super(actionRepository, actionStatusRepository, quotaManagement, repositoryProperties); this.targetRepository = targetRepository; - this.targetTypeManagement = targetTypeManagement; + this.targetTypeRepository = targetTypeRepository; this.deploymentManagement = deploymentManagement; this.confirmationManagement = confirmationManagement; this.softwareModuleRepository = softwareModuleRepository; @@ -270,8 +272,9 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont } @Override - public Optional getSoftwareModule(final long id) { - return softwareModuleRepository.findById(id).map(SoftwareModule.class::cast); + public SoftwareModule getSoftwareModule(final long id) { + return softwareModuleRepository.findById(id).map(SoftwareModule.class::cast) + .orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, id)); } @Override @@ -360,7 +363,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont } @Override - public Optional getActionForDownloadByTargetAndSoftwareModule(final String controllerId, final long moduleId) { + public Action getActionForDownloadByTargetAndSoftwareModule(final String controllerId, final long moduleId) { throwExceptionIfTargetDoesNotExist(controllerId); throwExceptionIfSoftwareModuleDoesNotExist(moduleId); @@ -376,7 +379,8 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont .stream() .anyMatch(module -> module.getId() == moduleId)) .map(Action.class::cast) - .findFirst(); + .findFirst() + .orElseThrow(() -> new SoftwareModuleNotAssignedToTargetException(moduleId, controllerId)); } @Override @@ -542,11 +546,6 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont actionRepository.updateExternalRef(actionId, externalRef); } - @Override - public Optional getActionByExternalRef(@NotEmpty final String externalRef) { - return actionRepository.findByExternalRef(externalRef); - } - @Override public void deleteExistingTarget(@NotEmpty final String controllerId) { final JpaTarget target = targetRepository.getByControllerId(controllerId); @@ -555,7 +554,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont } @Override - public Optional getInstalledActionByTarget(final Target target) { + public Optional findInstalledActionByTarget(final Target target) { final JpaTarget jpaTarget = (JpaTarget) target; return Optional.ofNullable(jpaTarget.getInstalledDistributionSet()) .flatMap(installedDistributionSet -> actionRepository.findFirstByTargetIdAndDistributionSetIdAndStatusOrderByIdDesc( @@ -575,12 +574,9 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont @Override public boolean updateOfflineAssignedVersion(@NotEmpty final String controllerId, final String distributionName, final String version) { List distributionSetAssignmentResults = - systemSecurityContext.runAsSystem(() -> - distributionSetManagement.findByNameAndVersion(distributionName, version) - .map(distributionSet -> deploymentManagement.offlineAssignedDistributionSets( - controllerId, List.of(Map.entry(controllerId, distributionSet.getId())))) - .orElseThrow(() -> - new EntityNotFoundException(DistributionSet.class, Map.entry(distributionName, version)))); + systemSecurityContext.runAsSystem(() -> deploymentManagement.offlineAssignedDistributionSets( + controllerId, + List.of(Map.entry(controllerId, distributionSetManagement.findByNameAndVersion(distributionName, version).getId())))); return distributionSetAssignmentResults.stream() .findFirst() @@ -588,8 +584,8 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont .orElseThrow(); } - Optional getTargetType(String targetTypeName) { - return systemSecurityContext.runAsSystem(() -> targetTypeManagement.getByName(targetTypeName)); + private Optional findTargetType(String targetTypeName) { + return targetTypeRepository.findOne(TargetTypeSpecification.hasName(targetTypeName)).map(TargetType.class::cast); } // for testing @@ -668,7 +664,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont jpaTarget.setAddress(Optional.ofNullable(address).map(URI::toString).orElse(null)); if (StringUtils.hasText(type)) { - var targetTypeOptional = getTargetType(type); + final Optional targetTypeOptional = findTargetType(type); if (targetTypeOptional.isPresent()) { log.debug("Setting target type for thing ID \"{}\" to \"{}\".", controllerId, type); jpaTarget.setTargetType(targetTypeOptional.get()); @@ -772,7 +768,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont if (isTypeChanged(toUpdate.getTargetType(), type)) { if (StringUtils.hasText(type)) { - final Optional targetTypeOptional = getTargetType(type); + final Optional targetTypeOptional = findTargetType(type); if (targetTypeOptional.isPresent()) { log.debug("Updating target type for thing ID \"{}\" to \"{}\".", toUpdate.getControllerId(), type); toUpdate.setTargetType(targetTypeOptional.get()); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java index 3604afda4..bcc189039 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java @@ -464,13 +464,13 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl } @Override - public Optional getAssignedDistributionSet(final String controllerId) { + public Optional findAssignedDistributionSet(final String controllerId) { return targetRepository.findWithDetailsByControllerId(controllerId, JpaTarget_.GRAPH_TARGET_ASSIGNED_DISTRIBUTION_SET) .map(JpaTarget::getAssignedDistributionSet); } @Override - public Optional getInstalledDistributionSet(final String controllerId) { + public Optional findInstalledDistributionSet(final String controllerId) { return targetRepository.findWithDetailsByControllerId(controllerId, JpaTarget_.GRAPH_TARGET_INSTALLED_DISTRIBUTION_SET) .map(JpaTarget::getInstalledDistributionSet); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetManagement.java index b7b7813f0..8c2d0e9ed 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetManagement.java @@ -154,8 +154,9 @@ public class JpaDistributionSetManagement } @Override - public Optional getWithDetails(final long id) { - return jpaRepository.findOne(jpaRepository.byIdSpec(id), JpaDistributionSet_.GRAPH_DISTRIBUTION_SET_DETAIL); + public JpaDistributionSet getWithDetails(final long id) { + return jpaRepository.findOne(jpaRepository.byIdSpec(id), JpaDistributionSet_.GRAPH_DISTRIBUTION_SET_DETAIL) + .orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, id)); } // implicitly lock a distribution set if not already locked and implicit lock is enabled and not to skip @@ -290,8 +291,9 @@ public class JpaDistributionSetManagement } @Override - public Optional findByNameAndVersion(final String distributionName, final String version) { - return jpaRepository.findOne(DistributionSetSpecification.equalsNameAndVersionIgnoreCase(distributionName, version)); + public JpaDistributionSet findByNameAndVersion(final String distributionName, final String version) { + return jpaRepository.findOne(DistributionSetSpecification.equalsNameAndVersionIgnoreCase(distributionName, version)) + .orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, Map.entry(distributionName, version))); } @Override diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetTypeManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetTypeManagement.java index 338eab2b3..315ab4ab2 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetTypeManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetTypeManagement.java @@ -94,11 +94,6 @@ public class JpaDistributionSetTypeManagement return jpaRepository.findOne(DistributionSetTypeSpecification.byKey(key)); } - @Override - public Optional findByName(final String name) { - return jpaRepository.findOne(DistributionSetTypeSpecification.byName(name)); - } - @Override @Transactional @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutGroupManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutGroupManagement.java index d6a5f4377..c4a54890a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutGroupManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutGroupManagement.java @@ -109,8 +109,26 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement { } @Override - public Optional get(final long rolloutGroupId) { - return rolloutGroupRepository.findById(rolloutGroupId).map(RolloutGroup.class::cast); + public RolloutGroup get(final long rolloutGroupId) { + return rolloutGroupRepository.findById(rolloutGroupId).map(RolloutGroup.class::cast) + .orElseThrow(() -> new EntityNotFoundException(RolloutGroup.class, rolloutGroupId)); + } + + @Override + public RolloutGroup getWithDetailedStatus(final long rolloutGroupId) { + final JpaRolloutGroup jpaRolloutGroup = (JpaRolloutGroup) rolloutGroupRepository.findById(rolloutGroupId).map(RolloutGroup.class::cast) + .orElseThrow(() -> new EntityNotFoundException(RolloutGroup.class, rolloutGroupId)); + + List rolloutStatusCountItems = rolloutStatusCache.getRolloutGroupStatus(rolloutGroupId); + if (CollectionUtils.isEmpty(rolloutStatusCountItems)) { + rolloutStatusCountItems = actionRepository.getStatusCountByRolloutGroupId(rolloutGroupId); + rolloutStatusCache.putRolloutGroupStatus(rolloutGroupId, rolloutStatusCountItems); + } + + final TotalTargetCountStatus totalTargetCountStatus = new TotalTargetCountStatus( + rolloutStatusCountItems, (long) jpaRolloutGroup.getTotalTargets(), jpaRolloutGroup.getRollout().getActionType()); + jpaRolloutGroup.setTotalTargetCountStatus(totalTargetCountStatus); + return jpaRolloutGroup; } @Override @@ -185,30 +203,6 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement { return JpaManagementHelper.findAllWithCountBySpec(targetRepository, specList, pageable); } - @Override - public Optional getWithDetailedStatus(final long rolloutGroupId) { - final Optional rolloutGroup = get(rolloutGroupId); - if (rolloutGroup.isEmpty()) { - return rolloutGroup; - } - - final JpaRolloutGroup jpaRolloutGroup = (JpaRolloutGroup) rolloutGroup.get(); - - List rolloutStatusCountItems = rolloutStatusCache - .getRolloutGroupStatus(rolloutGroupId); - - if (CollectionUtils.isEmpty(rolloutStatusCountItems)) { - rolloutStatusCountItems = actionRepository.getStatusCountByRolloutGroupId(rolloutGroupId); - rolloutStatusCache.putRolloutGroupStatus(rolloutGroupId, rolloutStatusCountItems); - } - - final TotalTargetCountStatus totalTargetCountStatus = new TotalTargetCountStatus( - rolloutStatusCountItems, (long) jpaRolloutGroup.getTotalTargets(), jpaRolloutGroup.getRollout().getActionType()); - jpaRolloutGroup.setTotalTargetCountStatus(totalTargetCountStatus); - return rolloutGroup; - - } - @Override public long countTargetsOfRolloutsGroup(final long rolloutGroupId) { throwExceptionIfRolloutGroupDoesNotExist(rolloutGroupId); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java index f45a48955..5ba701616 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java @@ -304,22 +304,21 @@ public class JpaRolloutManagement implements RolloutManagement { return rolloutRepository.findByStatusIn(ACTIVE_ROLLOUTS); } + @Override + public Rollout get(final long rolloutId) { + return rolloutRepository.findById(rolloutId).map(Rollout.class::cast) + .orElseThrow(() -> new EntityNotFoundException(Rollout.class, rolloutId)); + } + @Override public Optional find(final long rolloutId) { return rolloutRepository.findById(rolloutId).map(Rollout.class::cast); } @Override - public Optional getByName(final String rolloutName) { - return rolloutRepository.findByName(rolloutName); - } - - @Override - public Optional getWithDetailedStatus(final long rolloutId) { - final Optional rollout = find(rolloutId); - if (rollout.isEmpty()) { - return rollout; - } + public Rollout getWithDetailedStatus(final long rolloutId) { + final Rollout rollout = rolloutRepository.findById(rolloutId).map(Rollout.class::cast) + .orElseThrow(() -> new EntityNotFoundException(Rollout.class, rolloutId)); List rolloutStatusCountItems = rolloutStatusCache.getRolloutStatus(rolloutId); @@ -329,8 +328,8 @@ public class JpaRolloutManagement implements RolloutManagement { } final TotalTargetCountStatus totalTargetCountStatus = new TotalTargetCountStatus( - rolloutStatusCountItems, rollout.get().getTotalTargets(), rollout.get().getActionType()); - ((JpaRollout) rollout.get()).setTotalTargetCountStatus(totalTargetCountStatus); + rolloutStatusCountItems, rollout.getTotalTargets(), rollout.getActionType()); + ((JpaRollout) rollout).setTotalTargetCountStatus(totalTargetCountStatus); return rollout; } @@ -831,7 +830,7 @@ public class JpaRolloutManagement implements RolloutManagement { if (quotaManagement.getMaxTargetsPerRolloutGroup() > 0) { validateTargetsInGroups( srcGroups, rollout.getTargetFilterQuery(), rollout.getCreatedAt(), - distributionSetType.getId()).getTargetsPerGroup().forEach(this::assertTargetsPerRolloutGroupQuota); + distributionSetType.getId()).targetsPerGroup().forEach(this::assertTargetsPerRolloutGroupQuota); } // create and persist the groups (w/o filling them with targets) diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleManagement.java index 57a68ccc1..5d1686e31 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleManagement.java @@ -22,11 +22,11 @@ import java.util.stream.Collectors; import jakarta.persistence.EntityManager; +import org.eclipse.hawkbit.artifact.encryption.ArtifactEncryptionService; import org.eclipse.hawkbit.repository.ArtifactManagement; import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.SoftwareModuleFields; import org.eclipse.hawkbit.repository.SoftwareModuleManagement; -import org.eclipse.hawkbit.repository.artifact.encryption.ArtifactEncryptionService; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.LockedException; import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper; @@ -53,19 +53,17 @@ import org.springframework.util.ObjectUtils; @Service @ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "software-module-management" }, matchIfMissing = true) -public class JpaSoftwareModuleManagement - extends AbstractJpaRepositoryWithMetadataManagement +public class JpaSoftwareModuleManagement extends + AbstractJpaRepositoryWithMetadataManagement implements SoftwareModuleManagement { private final DistributionSetRepository distributionSetRepository; private final ArtifactManagement artifactManagement; private final QuotaManagement quotaManagement; - protected JpaSoftwareModuleManagement( - final SoftwareModuleRepository softwareModuleRepository, - final EntityManager entityManager, - final DistributionSetRepository distributionSetRepository, - final ArtifactManagement artifactManagement, final QuotaManagement quotaManagement) { + protected JpaSoftwareModuleManagement(final SoftwareModuleRepository softwareModuleRepository, final EntityManager entityManager, + final DistributionSetRepository distributionSetRepository, final ArtifactManagement artifactManagement, + final QuotaManagement quotaManagement) { super(softwareModuleRepository, entityManager); this.distributionSetRepository = distributionSetRepository; this.artifactManagement = artifactManagement; @@ -79,9 +77,7 @@ public class JpaSoftwareModuleManagement if (createdModules.stream().anyMatch(SoftwareModule::isEncrypted)) { // flush sm creation in order to get ids entityManager.flush(); - createdModules.stream() - .filter(SoftwareModule::isEncrypted) - .map(SoftwareModule::getId) + createdModules.stream().filter(SoftwareModule::isEncrypted).map(SoftwareModule::getId) .forEach(encryptedModuleId -> ArtifactEncryptionService.getInstance().addEncryptionSecrets(encryptedModuleId)); } @@ -103,48 +99,39 @@ public class JpaSoftwareModuleManagement @Override protected List softDelete(final Collection toDelete) { - return toDelete.stream() - .filter(swModule -> { - final List assignedTo = swModule.getAssignedTo(); - if (assignedTo != null) { - final List lockedDS = assignedTo.stream() - .filter(DistributionSet::isLocked) - .filter(ds -> !ds.isDeleted()) - .toList(); - if (!lockedDS.isEmpty()) { - final StringBuilder sb = new StringBuilder("Part of "); - if (lockedDS.size() == 1) { - sb.append("a locked distribution set: "); - } else { - sb.append(lockedDS.size()).append(" locked distribution sets: "); - } - for (final DistributionSet ds : lockedDS) { - sb.append(ds.getName()).append(":").append(ds.getVersion()).append(" (").append(ds.getId()).append("), "); - } - sb.delete(sb.length() - 2, sb.length()); - throw new LockedException(JpaSoftwareModule.class, swModule.getId(), "DELETE", sb.toString()); - } + return toDelete.stream().filter(swModule -> { + final List assignedTo = swModule.getAssignedTo(); + if (assignedTo != null) { + final List lockedDS = assignedTo.stream().filter(DistributionSet::isLocked).filter(ds -> !ds.isDeleted()) + .toList(); + if (!lockedDS.isEmpty()) { + final StringBuilder sb = new StringBuilder("Part of "); + if (lockedDS.size() == 1) { + sb.append("a locked distribution set: "); + } else { + sb.append(lockedDS.size()).append(" locked distribution sets: "); } - final boolean isAssigned = !ObjectUtils.isEmpty(assignedTo); - // schedule delete binary data of artifacts for every soft or not soft deleted module - deleteGridFsArtifacts(swModule); - return isAssigned; - }) - .toList(); + for (final DistributionSet ds : lockedDS) { + sb.append(ds.getName()).append(":").append(ds.getVersion()).append(" (").append(ds.getId()).append("), "); + } + sb.delete(sb.length() - 2, sb.length()); + throw new LockedException(JpaSoftwareModule.class, swModule.getId(), "DELETE", sb.toString()); + } + } + final boolean isAssigned = !ObjectUtils.isEmpty(assignedTo); + // schedule delete binary data of artifacts for every soft or not soft deleted module + deleteGridFsArtifacts(swModule); + return isAssigned; + }).toList(); } // called only with 'system code' access, so no need to check access control @Override public Map> findMetaDataBySoftwareModuleIdsAndTargetVisible(final Collection ids) { - return jpaRepository.findVisibleMetadataByModuleIds(ids) - .stream() - .collect(Collectors.groupingBy( - entry -> (Long) entry[0], - Collectors.toMap( - entry -> (String) entry[1], - entry -> (String) entry[2], - (existing, replacement) -> existing, // in case of duplicates, keep the first one - HashMap::new))); + return jpaRepository.findVisibleMetadataByModuleIds(ids).stream().collect(Collectors.groupingBy(entry -> (Long) entry[0], + Collectors.toMap(entry -> (String) entry[1], entry -> (String) entry[2], (existing, replacement) -> existing, + // in case of duplicates, keep the first one + HashMap::new))); } @Override @@ -177,10 +164,8 @@ public class JpaSoftwareModuleManagement public Page findByAssignedTo(final long distributionSetId, final Pageable pageable) { assertDistributionSetExists(distributionSetId); - return JpaManagementHelper.findAllWithCountBySpec( - jpaRepository, - Collections.singletonList(SoftwareModuleSpecification.byAssignedToDs(distributionSetId)), - pageable); + return JpaManagementHelper.findAllWithCountBySpec(jpaRepository, + Collections.singletonList(SoftwareModuleSpecification.byAssignedToDs(distributionSetId)), pageable); } /** @@ -203,11 +188,11 @@ public class JpaSoftwareModuleManagement } private void deleteGridFsArtifacts(final JpaSoftwareModule swModule) { - jpaRepository.getAccessController().ifPresent(accessController -> - accessController.assertOperationAllowed(AccessController.Operation.DELETE, swModule)); + jpaRepository.getAccessController() + .ifPresent(accessController -> accessController.assertOperationAllowed(AccessController.Operation.DELETE, swModule)); final Set sha1Hashes = swModule.getArtifacts().stream().map(Artifact::getSha1Hash).collect(Collectors.toSet()); - AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(() -> - sha1Hashes.forEach(((JpaArtifactManagement) artifactManagement)::clearArtifactBinary)); + AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit() + .afterCommit(() -> sha1Hashes.forEach(((JpaArtifactManagement) artifactManagement)::clearArtifactBinary)); } private void assertDistributionSetExists(final long distributionSetId) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleTypeManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleTypeManagement.java index f2b83199e..b279bd44e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleTypeManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleTypeManagement.java @@ -47,11 +47,6 @@ public class JpaSoftwareModuleTypeManagement return jpaRepository.findByKey(key); } - @Override - public Optional findByName(final String name) { - return jpaRepository.findByName(name); - } - @Override protected Collection softDelete(final Collection toDelete) { return toDelete.stream().filter(smt -> diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSystemManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSystemManagement.java index 7c864bc71..3fb343840 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSystemManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSystemManagement.java @@ -15,12 +15,12 @@ import java.util.function.Consumer; import jakarta.persistence.EntityManager; import lombok.extern.slf4j.Slf4j; -import org.eclipse.hawkbit.cache.TenancyCacheManager; +import org.eclipse.hawkbit.artifact.ArtifactStorage; +import org.eclipse.hawkbit.tenancy.cache.TenantCacheManager; import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.RolloutStatusCache; import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.TenantStatsManagement; -import org.eclipse.hawkbit.repository.artifact.ArtifactRepository; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.jpa.CurrentTenantCacheKeyGenerator; import org.eclipse.hawkbit.repository.jpa.SystemManagementCacheKeyGenerator; @@ -44,8 +44,8 @@ import org.eclipse.hawkbit.repository.jpa.utils.DeploymentHelper; import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.model.TenantMetaData; -import org.eclipse.hawkbit.repository.report.model.SystemUsageReport; -import org.eclipse.hawkbit.repository.report.model.SystemUsageReportWithTenants; +import org.eclipse.hawkbit.repository.model.report.SystemUsageReport; +import org.eclipse.hawkbit.repository.model.report.SystemUsageReportWithTenants; import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.tenancy.TenantAware; import org.springframework.beans.factory.annotation.Autowired; @@ -98,13 +98,13 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst private final SystemSecurityContext systemSecurityContext; private final TenantAware tenantAware; private final PlatformTransactionManager txManager; - private final TenancyCacheManager cacheManager; + private final TenantCacheManager cacheManager; private final RolloutStatusCache rolloutStatusCache; private final EntityManager entityManager; private final RepositoryProperties repositoryProperties; @Nullable - private ArtifactRepository artifactRepository; + private ArtifactStorage artifactRepository; @SuppressWarnings("squid:S00107") protected JpaSystemManagement( @@ -116,7 +116,7 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst final TenantConfigurationRepository tenantConfigurationRepository, final TenantMetaDataRepository tenantMetaDataRepository, final TenantStatsManagement systemStatsManagement, final SystemManagementCacheKeyGenerator currentTenantCacheKeyGenerator, final SystemSecurityContext systemSecurityContext, final TenantAware tenantAware, final PlatformTransactionManager txManager, - final TenancyCacheManager cacheManager, final RolloutStatusCache rolloutStatusCache, + final TenantCacheManager cacheManager, final RolloutStatusCache rolloutStatusCache, final EntityManager entityManager, final RepositoryProperties repositoryProperties, final JpaProperties properties) { this.targetRepository = targetRepository; @@ -147,7 +147,7 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst } @Autowired(required = false) // it's not required on dmf/ddi only instances - public void setArtifactRepository(ArtifactRepository artifactRepository) { + public void setArtifactRepository(ArtifactStorage artifactRepository) { this.artifactRepository = artifactRepository; } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetManagement.java index 4b9e77fd3..81cd9ab96 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetManagement.java @@ -126,6 +126,27 @@ public class JpaTargetManagement return jpaRepository.exists(AccessController.Operation.UPDATE, combinedSpecification); } + @Override + public Target getByControllerId(final String controllerId) { + return jpaRepository.findByControllerId(controllerId).map(Target.class::cast) + .orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId)); + } + + @Override + public Optional findByControllerId(final String controllerId) { + return jpaRepository.findByControllerId(controllerId).map(Target.class::cast); + } + + @Override + public List findByControllerId(final Collection controllerIDs) { + return Collections.unmodifiableList(jpaRepository.findAll(TargetSpecifications.byControllerIdWithAssignedDsInJoin(controllerIDs))); + } + + @Override + public Target getWithDetails(final String controllerId, final String detailsKey) { + return jpaRepository.getWithDetailsByControllerId(controllerId, "Target." + detailsKey); + } + @Override public Slice findByTargetFilterQueryAndNonDSAndCompatibleAndUpdatable( final long distributionSetId, final String rsql, final Pageable pageable) { @@ -143,21 +164,6 @@ public class JpaTargetManagement .map(Target.class::cast); } - @Override - public List getByControllerId(final Collection controllerIDs) { - return Collections.unmodifiableList(jpaRepository.findAll(TargetSpecifications.byControllerIdWithAssignedDsInJoin(controllerIDs))); - } - - @Override - public Optional getByControllerId(final String controllerId) { - return jpaRepository.findByControllerId(controllerId).map(Target.class::cast); - } - - @Override - public Target getWithDetails(final String controllerId, final String detailsKey) { - return jpaRepository.getWithDetailsByControllerId(controllerId, "Target." + detailsKey); - } - @Override public Slice findByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable( final Collection groups, final String rsql, final DistributionSetType dsType, final Pageable pageable) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTypeManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTypeManagement.java index 79338ec11..78fb643d4 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTypeManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTypeManagement.java @@ -76,26 +76,21 @@ public class JpaTargetTypeManagement } @Override - public Optional getByKey(final String key) { + public Optional findByKey(final String key) { return jpaRepository.findOne(TargetTypeSpecification.hasKey(key)).map(TargetType.class::cast); } - @Override - public Optional getByName(final String name) { - return jpaRepository.findOne(TargetTypeSpecification.hasName(name)).map(TargetType.class::cast); - } - @Override @Transactional @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) public TargetType assignCompatibleDistributionSetTypes(final long id, final Collection distributionSetTypeIds) { - final Collection dsTypes = distributionSetTypeRepository - .findAllById(distributionSetTypeIds); + final Collection dsTypes = distributionSetTypeRepository.findAllById(distributionSetTypeIds); if (dsTypes.size() < distributionSetTypeIds.size()) { - throw new EntityNotFoundException(DistributionSetType.class, distributionSetTypeIds, + throw new EntityNotFoundException( + DistributionSetType.class, distributionSetTypeIds, dsTypes.stream().map(DistributionSetType::getId).toList()); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantStatsManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantStatsManagement.java index 00282d3e5..c6f3a52f0 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantStatsManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantStatsManagement.java @@ -13,7 +13,7 @@ import org.eclipse.hawkbit.repository.TenantStatsManagement; import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository; import org.eclipse.hawkbit.repository.jpa.repository.LocalArtifactRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository; -import org.eclipse.hawkbit.repository.report.model.TenantUsage; +import org.eclipse.hawkbit.repository.model.report.TenantUsage; import org.eclipse.hawkbit.tenancy.TenantAware; import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.stereotype.Service; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaArtifact.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaArtifact.java index 4fc3bbd36..d7d1deb01 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaArtifact.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaArtifact.java @@ -28,7 +28,6 @@ import jakarta.validation.constraints.Size; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import org.eclipse.hawkbit.repository.artifact.model.AbstractDbArtifact; import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.SoftwareModule; @@ -76,13 +75,6 @@ public class JpaArtifact extends AbstractJpaTenantAwareBaseEntity implements Art @Column(name = "file_size", updatable = false) private long fileSize; - /** - * Constructs artifact. - * - * @param sha1Hash that is the link to the {@link AbstractDbArtifact} entity. - * @param filename that is used by {@link AbstractDbArtifact} store. - * @param softwareModule of this artifact - */ public JpaArtifact(@NotEmpty final String sha1Hash, @NotNull final String filename, final SoftwareModule softwareModule) { this.sha1Hash = sha1Hash; this.filename = filename; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/condition/PauseRolloutGroupAction.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/condition/PauseRolloutGroupAction.java index cbd07c633..653f226cb 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/condition/PauseRolloutGroupAction.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rollout/condition/PauseRolloutGroupAction.java @@ -56,8 +56,7 @@ public class PauseRolloutGroupAction implements RolloutGroupActionEvaluator new EntityNotFoundException(Rollout.class, rollout.getId())); + final Rollout refreshedRollout = rolloutManagement.get(rollout.getId()); if (Rollout.RolloutStatus.PAUSED != refreshedRollout.getStatus()) { // if only the latest state is != paused then pause rolloutManagement.pauseRollout(rollout.getId()); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/DistributionSetTypeSpecification.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/DistributionSetTypeSpecification.java index 8e20c1e73..9ad134486 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/DistributionSetTypeSpecification.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/DistributionSetTypeSpecification.java @@ -25,18 +25,6 @@ import org.springframework.data.jpa.domain.Specification; @NoArgsConstructor(access = AccessLevel.PRIVATE) public final class DistributionSetTypeSpecification { - /** - * {@link Specification} for retrieving {@link DistributionSetType} with - * given {@link DistributionSetType#getName()} including fetching the - * elements list. - * - * @param name to search - * @return the {@link DistributionSet} {@link Specification} - */ - public static Specification byName(final String name) { - return (targetRoot, query, cb) -> cb.equal(targetRoot.get(AbstractJpaNamedEntity_.name), name); - } - /** * {@link Specification} for retrieving {@link DistributionSetType} with * given {@link DistributionSetType#getKey()} including fetching the diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetTypeSpecification.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetTypeSpecification.java index 9d45caf6d..1a830279e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetTypeSpecification.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetTypeSpecification.java @@ -9,8 +9,6 @@ */ package org.eclipse.hawkbit.repository.jpa.specifications; -import java.util.Collection; - import jakarta.persistence.criteria.SetJoin; import lombok.AccessLevel; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/FileSizeAndStorageQuotaCheckingInputStream.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/FileSizeAndStorageQuotaCheckingInputStream.java index f15f71206..c457af12b 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/FileSizeAndStorageQuotaCheckingInputStream.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/FileSizeAndStorageQuotaCheckingInputStream.java @@ -13,11 +13,11 @@ import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; -import org.eclipse.hawkbit.repository.exception.FileSizeQuotaExceededException; -import org.eclipse.hawkbit.repository.exception.StorageQuotaExceededException; +import org.eclipse.hawkbit.artifact.exception.FileSizeQuotaExceededException; +import org.eclipse.hawkbit.artifact.exception.StorageQuotaExceededException; /** - * A FilterInputStream that ensures file size and storage quotas are enforced. It check during read operations if the + * A FilterInputStream that ensures file size and storage quotas are enforced. It checks during read operations if the * quota will be exceeded and throws an QuotaExceededException if this happens. */ public class FileSizeAndStorageQuotaCheckingInputStream extends FilterInputStream { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java index 289072a96..9608a6703 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java @@ -12,7 +12,6 @@ package org.eclipse.hawkbit.repository.jpa; import static org.assertj.core.api.Assertions.assertThat; import java.lang.reflect.Array; -import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; @@ -43,7 +42,6 @@ import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetTagRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetTypeRepository; import org.eclipse.hawkbit.repository.jpa.repository.TenantMetaDataRepository; -import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetSpecification; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -61,15 +59,11 @@ import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties; import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Slice; import org.springframework.data.jpa.domain.Specification; import org.springframework.orm.jpa.vendor.Database; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.CollectionUtils; -import org.springframework.util.ObjectUtils; @Slf4j @ContextConfiguration(classes = { JpaRepositoryConfiguration.class, TestConfiguration.class }) diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/DistributionSetAccessControllerTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/DistributionSetAccessControllerTest.java index 01f09c5d9..b8011d8e7 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/DistributionSetAccessControllerTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/DistributionSetAccessControllerTest.java @@ -10,6 +10,7 @@ package org.eclipse.hawkbit.repository.jpa.acm; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.eclipse.hawkbit.im.authentication.SpPermission.READ_DISTRIBUTION_SET; import static org.eclipse.hawkbit.im.authentication.SpPermission.READ_REPOSITORY; @@ -79,8 +80,8 @@ class DistributionSetAccessControllerTest extends AbstractJpaIntegrationTest { assertThat(distributionSetManagement.find(hiddenId)).isEmpty(); // verify distributionSetManagement#getWithDetails - assertThat(distributionSetManagement.getWithDetails(permittedActionId)).isPresent(); - assertThat(distributionSetManagement.getWithDetails(hiddenId)).isEmpty(); + assertThat(distributionSetManagement.getWithDetails(permittedActionId)).isNotNull(); + assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(() -> distributionSetManagement.getWithDetails(hiddenId)); // verify distributionSetManagement#get final List allActionIds = Arrays.asList(permittedActionId, hiddenId); @@ -88,8 +89,11 @@ class DistributionSetAccessControllerTest extends AbstractJpaIntegrationTest { .as("Fail if request hidden.").isInstanceOf(EntityNotFoundException.class); // verify distributionSetManagement#getByNameAndVersion - assertThat(distributionSetManagement.findByNameAndVersion(permitted.getName(), permitted.getVersion())).isPresent(); - assertThat(distributionSetManagement.findByNameAndVersion(hidden.getName(), hidden.getVersion())).isEmpty(); + assertThat(distributionSetManagement.findByNameAndVersion(permitted.getName(), permitted.getVersion())).isNotNull(); + final String hiddenName = hidden.getName(); + final String hiddenVersion = hidden.getVersion(); + assertThatExceptionOfType(EntityNotFoundException.class) + .isThrownBy(() -> distributionSetManagement.findByNameAndVersion(hiddenName, hiddenVersion)); }); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/TargetAccessControllerTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/TargetAccessControllerTest.java index 06aa31964..29883f452 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/TargetAccessControllerTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/TargetAccessControllerTest.java @@ -76,15 +76,18 @@ class TargetAccessControllerTest extends AbstractJpaIntegrationTest { .containsOnly(permittedTarget.getId()); // verify targetManagement#getByControllerID - assertThat(targetManagement.getByControllerId(permittedTarget.getControllerId())).isPresent(); + assertThat(targetManagement.getByControllerId(permittedTarget.getControllerId())).isNotNull(); final String hiddenTargetControllerId = hiddenTarget.getControllerId(); assertThatThrownBy(() -> targetManagement.getByControllerId(hiddenTargetControllerId)) .as("Missing read permissions for hidden target.") .isInstanceOf(InsufficientPermissionException.class); + assertThatThrownBy(() -> targetManagement.findByControllerId(hiddenTargetControllerId)) + .as("Missing read permissions for hidden target.") + .isInstanceOf(InsufficientPermissionException.class); // verify targetManagement#getByControllerId assertThat(targetManagement - .getByControllerId(List.of(permittedTarget.getControllerId(), hiddenTargetControllerId)) + .findByControllerId(List.of(permittedTarget.getControllerId(), hiddenTargetControllerId)) .stream().map(Identifiable::getId).toList()).containsOnly(permittedTarget.getId()); // verify targetManagement#get diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/TargetTypeAccessControllerTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/TargetTypeAccessControllerTest.java index a9f849421..f5e3c2a91 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/TargetTypeAccessControllerTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/TargetTypeAccessControllerTest.java @@ -64,10 +64,6 @@ class TargetTypeAccessControllerTest extends AbstractJpaIntegrationTest { final Long hiddenTargetTypeId = hiddenTargetType.getId(); assertThat(targetTypeManagement.find(hiddenTargetTypeId)).isEmpty(); - // verify targetTypeManagement#getByName - assertThat(targetTypeManagement.getByName(permittedTargetType.getName())).isPresent(); - assertThat(targetTypeManagement.getByName(hiddenTargetType.getName())).isEmpty(); - // verify targetTypeManagement#get by ids final List allEntityIds = Arrays.asList(permittedTargetType.getId(), hiddenTargetTypeId); assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(() -> targetTypeManagement.get(allEntityIds)); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerIntTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerIntTest.java index 9ce9f5f80..4bb6bced9 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerIntTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerIntTest.java @@ -432,7 +432,7 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest { for (final Target target : targetsAll) { if (targetIds.contains(target.getId())) { - assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId())).as("assigned DS").contains(set); + assertThat(deploymentManagement.findAssignedDistributionSet(target.getControllerId())).as("assigned DS").contains(set); } } } @@ -456,7 +456,7 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest { for (final Target target : targetsAll) { if (targetIds.contains(target.getId())) { - assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId())).isEmpty(); + assertThat(deploymentManagement.findAssignedDistributionSet(target.getControllerId())).isEmpty(); } } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ArtifactManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ArtifactManagementTest.java index 78bce8d56..90defeb1c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ArtifactManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ArtifactManagementTest.java @@ -26,20 +26,20 @@ import java.util.concurrent.Callable; import jakarta.validation.ConstraintViolationException; import org.apache.commons.io.IOUtils; -import org.eclipse.hawkbit.im.authentication.SpRole; -import org.eclipse.hawkbit.repository.artifact.exception.ArtifactBinaryNotFoundException; -import org.eclipse.hawkbit.repository.artifact.model.DbArtifact; -import org.eclipse.hawkbit.repository.artifact.model.DbArtifactHash; +import org.eclipse.hawkbit.artifact.exception.ArtifactBinaryNotFoundException; +import org.eclipse.hawkbit.artifact.exception.FileSizeQuotaExceededException; +import org.eclipse.hawkbit.artifact.exception.StorageQuotaExceededException; +import org.eclipse.hawkbit.artifact.model.ArtifactHashes; +import org.eclipse.hawkbit.artifact.model.ArtifactStream; import org.eclipse.hawkbit.im.authentication.SpPermission; +import org.eclipse.hawkbit.im.authentication.SpRole; import org.eclipse.hawkbit.repository.ArtifactManagement; import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; -import org.eclipse.hawkbit.repository.exception.FileSizeQuotaExceededException; import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; -import org.eclipse.hawkbit.repository.exception.InvalidMD5HashException; -import org.eclipse.hawkbit.repository.exception.InvalidSHA1HashException; -import org.eclipse.hawkbit.repository.exception.InvalidSHA256HashException; -import org.eclipse.hawkbit.repository.exception.StorageQuotaExceededException; +import org.eclipse.hawkbit.repository.exception.InvalidMd5HashException; +import org.eclipse.hawkbit.repository.exception.InvalidSha1HashException; +import org.eclipse.hawkbit.repository.exception.InvalidSha256HashException; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.RandomGeneratedInputStream; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; @@ -48,7 +48,6 @@ import org.eclipse.hawkbit.repository.model.ArtifactUpload; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.test.matcher.Expect; import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents; -import org.eclipse.hawkbit.repository.test.util.HashGeneratorUtils; import org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch; import org.eclipse.hawkbit.repository.test.util.WithUser; import org.junit.jupiter.api.Test; @@ -72,13 +71,9 @@ class ArtifactManagementTest extends AbstractJpaIntegrationTest { final long moduleId = module.getId(); final boolean encrypted = module.isEncrypted(); assertThatExceptionOfType(ArtifactBinaryNotFoundException.class) - .isThrownBy(() -> artifactManagement.loadArtifactBinary(NOT_EXIST_ID, moduleId, encrypted)); + .isThrownBy(() -> artifactManagement.getArtifactStream(NOT_EXIST_ID, moduleId, encrypted)); } - /** - * Verifies that management queries react as specfied on calls for non existing entities by means of - * throwing EntityNotFoundException. - */ @Test @ExpectEvents() void entityQueriesReferringToNotExistingEntitiesThrowsException() { @@ -87,12 +82,12 @@ class ArtifactManagementTest extends AbstractJpaIntegrationTest { verifyThrownExceptionBy( () -> artifactManagement.create(new ArtifactUpload( IOUtils.toInputStream(artifactData, "UTF-8"), - NOT_EXIST_IDL, "xxx", null, null, null, false, null, artifactSize)), "SoftwareModule"); + null, artifactSize, null, NOT_EXIST_IDL, "xxx", false)), "SoftwareModule"); verifyThrownExceptionBy( () -> artifactManagement.create(new ArtifactUpload( IOUtils.toInputStream(artifactData, "UTF-8"), - NOT_EXIST_IDL, "xxx", null, null, null, false, null, artifactSize)), "SoftwareModule"); + null, artifactSize, null, NOT_EXIST_IDL, "xxx", false)), "SoftwareModule"); verifyThrownExceptionBy(() -> artifactManagement.delete(NOT_EXIST_IDL), "Artifact"); } @@ -130,16 +125,10 @@ class ArtifactManagementTest extends AbstractJpaIntegrationTest { assertThat(artifact1).isNotEqualTo(artifact2); assertThat(artifact1.getSha1Hash()).isEqualTo(artifact2.getSha1Hash()); - final DbArtifact dbArtifact = artifactManagement.loadArtifactBinary( - HashGeneratorUtils.generateSHA1(randomBytes), sm.getId(), sm.isEncrypted()); - final DbArtifactHash hash = dbArtifact.getHashes(); - // md5 and sha256 are kept in local artifact db and should not be provided by "load", test only sha1 - assertThat(hash.getSha1()).isEqualTo(HashGeneratorUtils.generateSHA1(randomBytes)); - assertThat(artifactRepository.findAll()).hasSize(4); assertThat(softwareModuleRepository.findAll()).hasSize(3); - assertThat(softwareModuleManagement.find(sm.getId()).get().getArtifacts()).hasSize(3); + assertThat(softwareModuleManagement.get(sm.getId()).getArtifacts()).hasSize(3); } } @@ -154,16 +143,16 @@ class ArtifactManagementTest extends AbstractJpaIntegrationTest { final long smID = softwareModuleRepository.save(new JpaSoftwareModule(osType, "smIllegalFilenameTest", "1.0")).getId(); final ArtifactUpload artifactUpload = new ArtifactUpload( - IOUtils.toInputStream(artifactData, "UTF-8"), smID, illegalFilename, false, artifactSize); + IOUtils.toInputStream(artifactData, "UTF-8"), null, artifactSize, null, smID, illegalFilename, false); assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(() -> artifactManagement.create(artifactUpload)); - assertThat(softwareModuleManagement.find(smID).get().getArtifacts()).isEmpty(); + assertThat(softwareModuleManagement.get(smID).getArtifacts()).isEmpty(); } /** * Verifies that the quota specifying the maximum number of artifacts per software module is enforced. */ @Test - void createArtifactsUntilQuotaIsExceeded() throws IOException { + void failIfMaxArtifactsPerSoftwareModuleQuotaIsExceeded() throws IOException { // create a software module final long smId = softwareModuleRepository.save(new JpaSoftwareModule(osType, "sm1", "1.0")).getId(); @@ -186,11 +175,8 @@ class ArtifactManagementTest extends AbstractJpaIntegrationTest { createArtifactForSoftwareModule("fileXYZ", smId, artifactSize); } - /** - * Verifies that the quota specifying the maximum artifact storage is enforced (across software modules). - */ @Test - void createArtifactsUntilStorageQuotaIsExceeded() throws IOException { + void failIfMaxArtifactStorageQuotaIsExceeded() throws IOException { // create as many small artifacts as possible w/o violating the storage quota final long maxBytes = quotaManagement.getMaxArtifactStorage(); final List artifactIds = new ArrayList<>(); @@ -290,7 +276,7 @@ class ArtifactManagementTest extends AbstractJpaIntegrationTest { } /** - * Test the deletion of an artifact metadata where the binary is still linked to another metadata element. + * Test the deletion of an artifact metadata where the binary is still linked to another metadata element. * The expected result is that the metadata is deleted but the binary kept. */ @Test @@ -343,7 +329,7 @@ class ArtifactManagementTest extends AbstractJpaIntegrationTest { final Artifact artifact2 = createArtifactForSoftwareModule("file2", sm2.getId(), artifactSize, inputStream2); assertEqualFileContents( - artifactManagement.loadArtifactBinary(artifact2.getSha1Hash(), sm2.getId(), sm2.isEncrypted()), randomBytes); + artifactManagement.getArtifactStream(artifact2.getSha1Hash(), sm2.getId(), sm2.isEncrypted()), randomBytes); assertThat(artifactRepository.findAll()).hasSize(2); @@ -405,7 +391,7 @@ class ArtifactManagementTest extends AbstractJpaIntegrationTest { final SoftwareModule smOs = testdataFactory.createSoftwareModuleOs(); final Artifact artifact = createArtifactForSoftwareModule("file1", smOs.getId(), artifactSize, input); assertEqualFileContents( - artifactManagement.loadArtifactBinary(artifact.getSha1Hash(), smOs.getId(), smOs.isEncrypted()), randomBytes); + artifactManagement.getArtifactStream(artifact.getSha1Hash(), smOs.getId(), smOs.isEncrypted()), randomBytes); } } @@ -415,10 +401,10 @@ class ArtifactManagementTest extends AbstractJpaIntegrationTest { @Test @WithUser(allSpPermissions = true, removeFromAllPermission = { SpPermission.DOWNLOAD_REPOSITORY_ARTIFACT, SpRole.CONTROLLER_ROLE, SpRole.CONTROLLER_ROLE_ANONYMOUS }) - void loadArtifactBinaryWithoutDownloadArtifactThrowsPermissionDenied() { + void getArtifactBinaryWithoutDownloadArtifactThrowsPermissionDenied() { assertThatExceptionOfType(InsufficientPermissionException.class) .as("Should not have worked with missing permission.") - .isThrownBy(() -> artifactManagement.loadArtifactBinary("123", 1, false)); + .isThrownBy(() -> artifactManagement.getArtifactStream("123", 1, false)); } /** @@ -429,29 +415,29 @@ class ArtifactManagementTest extends AbstractJpaIntegrationTest { final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); final byte[] testData = randomBytes(100); - final DbArtifactHash artifactHashes = calcHashes(testData); + final ArtifactHashes artifactHashes = calcHashes(testData); try (final InputStream inputStream = new ByteArrayInputStream(testData)) { final ArtifactUpload artifactUploadWithInvalidSha1 = new ArtifactUpload( - inputStream, sm.getId(), "test-file", - artifactHashes.getMd5(), "sha1", artifactHashes.getSha256(), false, null, testData.length); - assertThatExceptionOfType(InvalidSHA1HashException.class) + inputStream, null, testData.length, new ArtifactHashes("sha1", artifactHashes.md5(), artifactHashes.sha256()), + sm.getId(), "test-file", false); + assertThatExceptionOfType(InvalidSha1HashException.class) .isThrownBy(() -> artifactManagement.create(artifactUploadWithInvalidSha1)); } try (final InputStream inputStream = new ByteArrayInputStream(testData)) { final ArtifactUpload artifactUploadWithInvalidMd5 = new ArtifactUpload( - inputStream, sm.getId(), "test-file", - "md5", artifactHashes.getSha1(), artifactHashes.getSha256(), false, null, testData.length); - assertThatExceptionOfType(InvalidMD5HashException.class) + inputStream, null, testData.length, new ArtifactHashes(artifactHashes.sha1(), "md5", artifactHashes.sha256()), + sm.getId(), "test-file", false); + assertThatExceptionOfType(InvalidMd5HashException.class) .isThrownBy(() -> artifactManagement.create(artifactUploadWithInvalidMd5)); } try (final InputStream inputStream = new ByteArrayInputStream(testData)) { final ArtifactUpload artifactUploadWithInvalidSha256 = new ArtifactUpload( - inputStream, sm.getId(), "test-file", - artifactHashes.getMd5(), artifactHashes.getSha1(), "sha256", false, null, testData.length); - assertThatExceptionOfType(InvalidSHA256HashException.class) + inputStream, null, testData.length, new ArtifactHashes(artifactHashes.sha1(), artifactHashes.md5(), "sha256"), + sm.getId(), "test-file", false); + assertThatExceptionOfType(InvalidSha256HashException.class) .isThrownBy(() -> artifactManagement.create(artifactUploadWithInvalidSha256)); } } @@ -464,20 +450,20 @@ class ArtifactManagementTest extends AbstractJpaIntegrationTest { final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); final byte[] testData = randomBytes(100); - final DbArtifactHash artifactHashes = calcHashes(testData); + final ArtifactHashes artifactHashes = calcHashes(testData); try (final InputStream inputStream = new ByteArrayInputStream(testData)) { final ArtifactUpload artifactUpload = new ArtifactUpload( - inputStream, sm.getId(), "test-file", - artifactHashes.getMd5(), artifactHashes.getSha1(), artifactHashes.getSha256(), false, null, testData.length); + inputStream, null, testData.length, + new ArtifactHashes(artifactHashes.sha1(), artifactHashes.md5(), artifactHashes.sha256()), + sm.getId(), "test-file", false); final Artifact createdArtifact = artifactManagement.create(artifactUpload); - assertThat(createdArtifact.getSha1Hash()).isEqualTo(artifactHashes.getSha1()); - assertThat(createdArtifact.getMd5Hash()).isEqualTo(artifactHashes.getMd5()); - assertThat(createdArtifact.getSha256Hash()).isEqualTo(artifactHashes.getSha256()); + assertThat(createdArtifact.getSha1Hash()).isEqualTo(artifactHashes.sha1()); + assertThat(createdArtifact.getMd5Hash()).isEqualTo(artifactHashes.md5()); + assertThat(createdArtifact.getSha256Hash()).isEqualTo(artifactHashes.sha256()); } - final DbArtifact dbArtifact = artifactManagement.loadArtifactBinary(artifactHashes.getSha1(), sm.getId(), sm.isEncrypted()); - assertThat(dbArtifact).isNotNull(); + assertThat(artifactManagement.getArtifactStream(artifactHashes.sha1(), sm.getId(), sm.isEncrypted())).isNotNull(); } /** @@ -489,34 +475,35 @@ class ArtifactManagementTest extends AbstractJpaIntegrationTest { final SoftwareModule smApp = testdataFactory.createSoftwareModuleApp(); final byte[] testData = randomBytes(100); - final DbArtifactHash artifactHashes = calcHashes(testData); + final ArtifactHashes artifactHashes = calcHashes(testData); try (final InputStream inputStream = new ByteArrayInputStream(testData)) { final ArtifactUpload artifactUpload = new ArtifactUpload( - inputStream, smOs.getId(), "test-file", - artifactHashes.getMd5(), artifactHashes.getSha1(), artifactHashes.getSha256(), false, null, testData.length); + inputStream, null, testData.length, + new ArtifactHashes(artifactHashes.sha1(), artifactHashes.md5(), artifactHashes.sha256()), + smOs.getId(), "test-file", false); final Artifact artifact = artifactManagement.create(artifactUpload); assertThat(artifact).isNotNull(); } - final DbArtifact dbArtifact = artifactManagement.loadArtifactBinary(artifactHashes.getSha1(), smOs.getId(), smOs.isEncrypted()); - assertThat(dbArtifact).isNotNull(); + + assertThat(artifactManagement.getArtifactStream(artifactHashes.sha1(), smOs.getId(), smOs.isEncrypted())).isNotNull(); try (final InputStream inputStream = new ByteArrayInputStream(testData)) { final ArtifactUpload existingArtifactUpload = new ArtifactUpload( - inputStream, smApp.getId(), "test-file", false, testData.length); + inputStream, null, testData.length, null, smApp.getId(), "test-file", false); final Artifact createdArtifact = artifactManagement.create(existingArtifactUpload); - assertThat(createdArtifact.getSha1Hash()).isEqualTo(artifactHashes.getSha1()); - assertThat(createdArtifact.getMd5Hash()).isEqualTo(artifactHashes.getMd5()); - assertThat(createdArtifact.getSha256Hash()).isEqualTo(artifactHashes.getSha256()); + assertThat(createdArtifact.getSha1Hash()).isEqualTo(artifactHashes.sha1()); + assertThat(createdArtifact.getMd5Hash()).isEqualTo(artifactHashes.md5()); + assertThat(createdArtifact.getSha256Hash()).isEqualTo(artifactHashes.sha256()); } } - private DbArtifactHash calcHashes(final byte[] input) throws NoSuchAlgorithmException { + private ArtifactHashes calcHashes(final byte[] input) throws NoSuchAlgorithmException { final String sha1Hash = toBase16Hash("SHA1", input); final String md5Hash = toBase16Hash("MD5", input); final String sha256Hash = toBase16Hash("SHA-256", input); - return new DbArtifactHash(sha1Hash, md5Hash, sha256Hash); + return new ArtifactHashes(sha1Hash, md5Hash, sha256Hash); } private String toBase16Hash(final String algorithm, final byte[] input) throws NoSuchAlgorithmException { @@ -534,7 +521,7 @@ class ArtifactManagementTest extends AbstractJpaIntegrationTest { private Artifact createArtifactForSoftwareModule( final String filename, final long moduleId, final int artifactSize, final InputStream inputStream) { - return artifactManagement.create(new ArtifactUpload(inputStream, moduleId, filename, false, artifactSize)); + return artifactManagement.create(new ArtifactUpload(inputStream, null, artifactSize, null, moduleId, filename, false)); } private T runAsTenant(final String tenant, final Callable callable) throws Exception { @@ -554,8 +541,8 @@ class ArtifactManagementTest extends AbstractJpaIntegrationTest { assertThat(runAsTenant(tenant, () -> artifactRepository.findAll())).hasSize(count); } - private void assertEqualFileContents(final DbArtifact artifact, final byte[] randomBytes) throws IOException { - try (final InputStream inputStream = artifact.getFileInputStream()) { + private void assertEqualFileContents(final ArtifactStream artifact, final byte[] randomBytes) throws IOException { + try (final InputStream inputStream = artifact) { assertTrue( IOUtils.contentEquals(new ByteArrayInputStream(randomBytes), inputStream), "The stored binary matches the given binary"); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementTest.java index a7c0d386b..7c6b1d885 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementTest.java @@ -334,8 +334,8 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { assertThat(controllerManagement.findActionWithDetails(NOT_EXIST_IDL)).isNotPresent(); assertThat(controllerManagement.findByControllerId(NOT_EXIST_ID)).isNotPresent(); assertThat(controllerManagement.find(NOT_EXIST_IDL)).isNotPresent(); - assertThat(controllerManagement.getActionForDownloadByTargetAndSoftwareModule(target.getControllerId(), - module.getId())).isNotPresent(); + assertThatExceptionOfType(EntityNotFoundException.class) + .isThrownBy(() -> controllerManagement.getActionForDownloadByTargetAndSoftwareModule(target.getControllerId(), module.getId())); assertThat(controllerManagement.findActiveActionWithHighestWeight(NOT_EXIST_ID)).isNotPresent(); @@ -654,10 +654,12 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { Target savedTarget = testdataFactory.createTarget(); // create two artifacts with identical SHA1 hash - final Artifact artifact = artifactManagement.create(new ArtifactUpload(new ByteArrayInputStream(random), - findFirstModuleByType(ds, osType).orElseThrow().getId(), "file1", false, artifactSize)); - final Artifact artifact2 = artifactManagement.create(new ArtifactUpload(new ByteArrayInputStream(random), - findFirstModuleByType(ds2, osType).orElseThrow().getId(), "file1", false, artifactSize)); + final Artifact artifact = artifactManagement.create(new ArtifactUpload( + new ByteArrayInputStream(random), null, artifactSize, null, + findFirstModuleByType(ds, osType).orElseThrow().getId(), "file1", false)); + final Artifact artifact2 = artifactManagement.create(new ArtifactUpload( + new ByteArrayInputStream(random), null, artifactSize, null, + findFirstModuleByType(ds2, osType).orElseThrow().getId(), "file1", false)); assertThat(artifact.getSha1Hash()).isEqualTo(artifact2.getSha1Hash()); assertThat( @@ -1107,13 +1109,11 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { ActionStatusCreate.builder().actionId(action.getId()).status(Action.Status.RUNNING).build())); // nothing changed as "feedback after close" is disabled - assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getUpdateStatus()) - .isEqualTo(TargetUpdateStatus.IN_SYNC); + assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).getUpdateStatus()).isEqualTo(TargetUpdateStatus.IN_SYNC); assertThat(actionRepository.findById(action.getId())) .hasValueSatisfying(a -> assertThat(a.getStatus()).isEqualTo(Status.FINISHED)); assertThat(actionStatusRepository.count()).isEqualTo(3); - assertThat(controllerManagement.findActionStatusByAction(action.getId(), PAGE).getNumberOfElements()) - .isEqualTo(3); + assertThat(controllerManagement.findActionStatusByAction(action.getId(), PAGE).getNumberOfElements()).isEqualTo(3); } /** @@ -1139,7 +1139,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { ActionStatusCreate.builder().actionId(action.getId()).status(Action.Status.RUNNING).build())); // nothing changed as "feedback after close" is disabled - assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getUpdateStatus()).isEqualTo(TargetUpdateStatus.IN_SYNC); + assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).getUpdateStatus()).isEqualTo(TargetUpdateStatus.IN_SYNC); // however, additional action status has been stored assertThat(actionStatusRepository.findAll(PAGE).getNumberOfElements()).isEqualTo(4); assertThat(controllerManagement.findActionStatusByAction(action.getId(), PAGE).getNumberOfElements()).isEqualTo(4); @@ -1166,11 +1166,12 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { }); // verify that audit information has not changed - final Target targetVerify = targetManagement.getByControllerId(controllerId).get(); - assertThat(targetVerify.getCreatedBy()).isEqualTo(target.getCreatedBy()); - assertThat(targetVerify.getCreatedAt()).isEqualTo(target.getCreatedAt()); - assertThat(targetVerify.getLastModifiedBy()).isEqualTo(target.getLastModifiedBy()); - assertThat(targetVerify.getLastModifiedAt()).isEqualTo(target.getLastModifiedAt()); + assertThat(targetManagement.getByControllerId(controllerId)).satisfies(targetVerify -> { + assertThat(targetVerify.getCreatedBy()).isEqualTo(target.getCreatedBy()); + assertThat(targetVerify.getCreatedAt()).isEqualTo(target.getCreatedAt()); + assertThat(targetVerify.getLastModifiedBy()).isEqualTo(target.getLastModifiedBy()); + assertThat(targetVerify.getLastModifiedAt()).isEqualTo(target.getLastModifiedAt()); + }); } /** @@ -1442,31 +1443,6 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { } } - /** - * Verify that getting a single action using externalRef works - */ - @Test - void getActionUsingSingleExternalRef() { - - final String knownControllerId = "controllerId"; - final String knownExternalRef = "externalRefId"; - final DistributionSet knownDistributionSet = testdataFactory.createDistributionSet(); - - // GIVEN - testdataFactory.createTarget(knownControllerId); - final DistributionSetAssignmentResult assignmentResult = assignDistributionSet(knownDistributionSet.getId(), - knownControllerId); - final Long actionId = getFirstAssignedActionId(assignmentResult); - controllerManagement.updateActionExternalRef(actionId, knownExternalRef); - - // WHEN - final Optional foundAction = controllerManagement.getActionByExternalRef(knownExternalRef); - - // THEN - assertThat(foundAction).isPresent(); - assertThat(foundAction.get().getId()).isEqualTo(actionId); - } - /** * Verify that assigning version form target works */ @@ -1728,9 +1704,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { final Long dsId = testdataFactory.createDistributionSet().getId(); testdataFactory.createTarget(); assignDistributionSet(dsId, DEFAULT_CONTROLLER_ID); - assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getUpdateStatus()) - .isEqualTo(TargetUpdateStatus.PENDING); - + assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).getUpdateStatus()).isEqualTo(TargetUpdateStatus.PENDING); return deploymentManagement.findActiveActionsByTarget(DEFAULT_CONTROLLER_ID, PAGE).getContent().get(0).getId(); } @@ -1738,7 +1712,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { final DistributionSet ds = testdataFactory.createDistributionSet(dsName); final Long dsId = ds.getId(); assignDistributionSet(dsId, defaultControllerId, DOWNLOAD_ONLY); - assertThat(targetManagement.getByControllerId(defaultControllerId).get().getUpdateStatus()).isEqualTo(TargetUpdateStatus.PENDING); + assertThat(targetManagement.getByControllerId(defaultControllerId).getUpdateStatus()).isEqualTo(TargetUpdateStatus.PENDING); final Long id = deploymentManagement.findActiveActionsByTarget(defaultControllerId, PAGE).getContent().get(0).getId(); assertThat(id).isNotNull(); @@ -1747,11 +1721,9 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { private Long assignDs(final Long dsId, final String defaultControllerId, final Action.ActionType actionType) { assignDistributionSet(dsId, defaultControllerId, actionType); - assertThat(targetManagement.getByControllerId(defaultControllerId).get().getUpdateStatus()) - .isEqualTo(TargetUpdateStatus.PENDING); + assertThat(targetManagement.getByControllerId(defaultControllerId).getUpdateStatus()).isEqualTo(TargetUpdateStatus.PENDING); - final Long id = deploymentManagement.findActiveActionsByTarget(defaultControllerId, PAGE).getContent().get(0) - .getId(); + final Long id = deploymentManagement.findActiveActionsByTarget(defaultControllerId, PAGE).getContent().get(0).getId(); assertThat(id).isNotNull(); return id; } @@ -1809,7 +1781,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { final Long actionId, final String controllerId, final TargetUpdateStatus expectedTargetUpdateStatus, final Action.Status expectedActionActionStatus, final Action.Status expectedActionStatus, final boolean actionActive) { - final TargetUpdateStatus targetStatus = targetManagement.getByControllerId(controllerId).get().getUpdateStatus(); + final TargetUpdateStatus targetStatus = targetManagement.getByControllerId(controllerId).getUpdateStatus(); assertThat(targetStatus).isEqualTo(expectedTargetUpdateStatus); final Action action = deploymentManagement.findAction(actionId).get(); assertThat(action.getStatus()).isEqualTo(expectedActionActionStatus); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DeploymentManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DeploymentManagementTest.java index d02cb4c08..39e12b468 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DeploymentManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DeploymentManagementTest.java @@ -180,7 +180,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { assertThat(action.getDistributionSet()).as("DistributionSet in action").isNotNull(); assertThat(action.getTarget()).as("Target in action").isNotNull(); - assertThat(deploymentManagement.getAssignedDistributionSet(action.getTarget().getControllerId()).get()) + assertThat(deploymentManagement.findAssignedDistributionSet(action.getTarget().getControllerId()).get()) .as("AssignedDistributionSet of target in action") .isNotNull(); } @@ -348,7 +348,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { final DistributionSet dsInstalled = action.getDistributionSet(); // check initial status - assertThat(targetManagement.getByControllerId("4712").get().getUpdateStatus()) + assertThat(targetManagement.getByControllerId("4712").getUpdateStatus()) .as("target has update status") .isEqualTo(TargetUpdateStatus.IN_SYNC); @@ -366,8 +366,8 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { controllerManagement.addCancelActionStatus(ActionStatusCreate.builder() .actionId(secondAction.getId()).status(Status.CANCELED).build()); assertThat(actionStatusRepository.findAll()).as("wrong size of actions status").hasSize(7); - assertThat(deploymentManagement.getAssignedDistributionSet("4712")).as("wrong ds").contains(dsFirst); - assertThat(targetManagement.getByControllerId("4712").get().getUpdateStatus()) + assertThat(deploymentManagement.findAssignedDistributionSet("4712")).as("wrong ds").contains(dsFirst); + assertThat(targetManagement.getByControllerId("4712").getUpdateStatus()) .as("wrong update status") .isEqualTo(TargetUpdateStatus.PENDING); @@ -378,9 +378,9 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { controllerManagement.addCancelActionStatus( ActionStatusCreate.builder().actionId(firstAction.getId()).status(Status.CANCELED).build()); assertThat(actionStatusRepository.findAll()).as("wrong size of action status").hasSize(9); - assertThat(deploymentManagement.getAssignedDistributionSet("4712")).as("wrong assigned ds") + assertThat(deploymentManagement.findAssignedDistributionSet("4712")).as("wrong assigned ds") .contains(dsInstalled); - assertThat(targetManagement.getByControllerId("4712").get().getUpdateStatus()).as("wrong update status") + assertThat(targetManagement.getByControllerId("4712").getUpdateStatus()).as("wrong update status") .isEqualTo(TargetUpdateStatus.IN_SYNC); } @@ -397,7 +397,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { final DistributionSet dsInstalled = action.getDistributionSet(); // check initial status - assertThat(targetManagement.getByControllerId("4712").get().getUpdateStatus()) + assertThat(targetManagement.getByControllerId("4712").getUpdateStatus()) .as("wrong update status") .isEqualTo(TargetUpdateStatus.IN_SYNC); @@ -415,23 +415,23 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { controllerManagement.addCancelActionStatus( ActionStatusCreate.builder().actionId(firstAction.getId()).status(Status.CANCELED).build()); assertThat(actionStatusRepository.findAll()).as("wrong size of action status").hasSize(7); - assertThat(deploymentManagement.getAssignedDistributionSet("4712")).as("wrong assigned ds").contains(dsSecond); - assertThat(targetManagement.getByControllerId("4712").get().getUpdateStatus()).as("wrong target update status") + assertThat(deploymentManagement.findAssignedDistributionSet("4712")).as("wrong assigned ds").contains(dsSecond); + assertThat(targetManagement.getByControllerId("4712").getUpdateStatus()).as("wrong target update status") .isEqualTo(TargetUpdateStatus.PENDING); // we cancel second -> remain assigned until finished cancellation deploymentManagement.cancelAction(secondAction.getId()); secondAction = (JpaAction) deploymentManagement.findActionWithDetails(secondAction.getId()).get(); assertThat(actionStatusRepository.findAll()).as("wrong size of action status").hasSize(8); - assertThat(deploymentManagement.getAssignedDistributionSet("4712")).as("wrong assigned ds").contains(dsSecond); + assertThat(deploymentManagement.findAssignedDistributionSet("4712")).as("wrong assigned ds").contains(dsSecond); // confirm cancellation controllerManagement.addCancelActionStatus( ActionStatusCreate.builder().actionId(secondAction.getId()).status(Status.CANCELED).build()); // cancelled success -> back to dsInstalled - assertThat(deploymentManagement.getAssignedDistributionSet("4712")) + assertThat(deploymentManagement.findAssignedDistributionSet("4712")) .as("wrong installed ds") .contains(dsInstalled); - assertThat(targetManagement.getByControllerId("4712").get().getUpdateStatus()) + assertThat(targetManagement.getByControllerId("4712").getUpdateStatus()) .as("wrong target info update status") .isEqualTo(TargetUpdateStatus.IN_SYNC); } @@ -448,7 +448,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { final DistributionSet ds = testdataFactory.createDistributionSet("newDS", true); // verify initial status - assertThat(targetManagement.getByControllerId("4712").get().getUpdateStatus()) + assertThat(targetManagement.getByControllerId("4712").getUpdateStatus()) .as("wrong target info update status").isEqualTo(TargetUpdateStatus.IN_SYNC); Action assigningAction = assignSet(target, ds); @@ -467,9 +467,9 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { // verify assertThat(assigningAction.getStatus()).as("wrong size of status").isEqualTo(Status.CANCELED); - assertThat(deploymentManagement.getAssignedDistributionSet("4712")).as("wrong assigned ds") + assertThat(deploymentManagement.findAssignedDistributionSet("4712")).as("wrong assigned ds") .contains(dsInstalled); - assertThat(targetManagement.getByControllerId("4712").get().getUpdateStatus()).as("wrong target update status") + assertThat(targetManagement.getByControllerId("4712").getUpdateStatus()).as("wrong target update status") .isEqualTo(TargetUpdateStatus.IN_SYNC); } @@ -480,7 +480,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { void forceQuitNotAllowedThrowsException() { final Action action = prepareFinishedUpdate("4712", "installed", true); // verify initial status - assertThat(targetManagement.getByControllerId("4712").get().getUpdateStatus()).as("wrong update status") + assertThat(targetManagement.getByControllerId("4712").getUpdateStatus()).as("wrong update status") .isEqualTo(TargetUpdateStatus.IN_SYNC); final Target target = action.getTarget(); @@ -1096,21 +1096,21 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { final Iterable allFoundTargets = targetManagement.findAll(PAGE).getContent(); // get final updated version of targets - savedDeployedTargets = targetManagement.getByControllerId(savedDeployedTargets.stream().map(Target::getControllerId).toList()); + savedDeployedTargets = targetManagement.findByControllerId(savedDeployedTargets.stream().map(Target::getControllerId).toList()); - Assertions.assertThat(allFoundTargets).as("founded targets are wrong") + Assertions. assertThat(allFoundTargets).as("founded targets are wrong") .containsAll(savedDeployedTargets) .containsAll(savedNakedTargets); assertThat(savedDeployedTargets).as("saved target are wrong").doesNotContain(toArray(savedNakedTargets, Target.class)); assertThat(savedNakedTargets).as("saved target are wrong").doesNotContain(toArray(savedDeployedTargets, Target.class)); for (final Target myt : savedNakedTargets) { - final Target t = targetManagement.getByControllerId(myt.getControllerId()).get(); + final Target t = targetManagement.getByControllerId(myt.getControllerId()); assertThat(deploymentManagement.countActionsByTarget(t.getControllerId())).as("action should be empty").isZero(); } for (final Target myt : savedDeployedTargets) { - final Target t = targetManagement.getByControllerId(myt.getControllerId()).get(); + final Target t = targetManagement.getByControllerId(myt.getControllerId()); final List activeActionsByTarget = deploymentManagement.findActiveActionsByTarget(t.getControllerId(), PAGE).getContent(); assertThat(activeActionsByTarget).as("action should not be empty").isNotEmpty(); assertThat(t.getUpdateStatus()).as("wrong target update status").isEqualTo(TargetUpdateStatus.PENDING); @@ -1247,23 +1247,23 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { // verifying the correctness of the assignments for (final Target t : deployResWithDsA.getDeployedTargets()) { - assertThat(deploymentManagement.getAssignedDistributionSet(t.getControllerId()).get().getId()) + assertThat(deploymentManagement.findAssignedDistributionSet(t.getControllerId()).get().getId()) .as("assignment is not correct").isEqualTo(dsA.getId()); - assertThat(deploymentManagement.getInstalledDistributionSet(t.getControllerId())) + assertThat(deploymentManagement.findInstalledDistributionSet(t.getControllerId())) .as("installed ds should be null").isNotPresent(); } for (final Target t : deployResWithDsB.getDeployedTargets()) { - assertThat(deploymentManagement.getAssignedDistributionSet(t.getControllerId()).get().getId()) + assertThat(deploymentManagement.findAssignedDistributionSet(t.getControllerId()).get().getId()) .as("assigned ds is wrong").isEqualTo(dsB.getId()); - assertThat(deploymentManagement.getInstalledDistributionSet(t.getControllerId())) + assertThat(deploymentManagement.findInstalledDistributionSet(t.getControllerId())) .as("installed ds should be null").isNotPresent(); } for (final Target t : deployResWithDsC.getDeployedTargets()) { - assertThat(deploymentManagement.getAssignedDistributionSet(t.getControllerId()).get().getId()) + assertThat(deploymentManagement.findAssignedDistributionSet(t.getControllerId()).get().getId()) .isEqualTo(dsC.getId()); - assertThat(deploymentManagement.getInstalledDistributionSet(t.getControllerId())) + assertThat(deploymentManagement.findInstalledDistributionSet(t.getControllerId())) .as("installed ds should not be null").isNotPresent(); - assertThat(targetManagement.getByControllerId(t.getControllerId()).get().getUpdateStatus()) + assertThat(targetManagement.getByControllerId(t.getControllerId()).getUpdateStatus()) .as("wrong target info update status").isEqualTo(TargetUpdateStatus.PENDING); } @@ -1274,12 +1274,12 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { // verify, that dsA is deployed correctly for (final Target t_ : updatedTsDsA) { - final Target t = targetManagement.getByControllerId(t_.getControllerId()).get(); - assertThat(deploymentManagement.getAssignedDistributionSet(t.getControllerId())) + final Target t = targetManagement.getByControllerId(t_.getControllerId()); + assertThat(deploymentManagement.findAssignedDistributionSet(t.getControllerId())) .as("assigned ds is wrong").contains(dsA); - assertThat(deploymentManagement.getInstalledDistributionSet(t.getControllerId())) + assertThat(deploymentManagement.findInstalledDistributionSet(t.getControllerId())) .as("installed ds is wrong").contains(dsA); - assertThat(targetManagement.getByControllerId(t.getControllerId()).get().getUpdateStatus()) + assertThat(targetManagement.getByControllerId(t.getControllerId()).getUpdateStatus()) .as("wrong target info update status").isEqualTo(TargetUpdateStatus.IN_SYNC); assertThat(deploymentManagement.findActiveActionsByTarget(t.getControllerId(), PAGE)) .as("no actions should be active").isEmpty(); @@ -1294,20 +1294,20 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { findActionsByDistributionSet(pageRequest, dsA.getId()).getContent().get(1); // get final updated version of targets - final List deployResWithDsBTargets = targetManagement.getByControllerId(deployResWithDsB - .getDeployedTargets().stream().map(Target::getControllerId).toList()); + final List deployResWithDsBTargets = targetManagement.findByControllerId( + deployResWithDsB.getDeployedTargets().stream().map(Target::getControllerId).toList()); assertThat(deployed2DS).as("deployed ds is wrong").usingElementComparator(controllerIdComparator()) .containsAll(deployResWithDsBTargets); assertThat(deployed2DS).as("deployed ds is wrong").hasSameSizeAs(deployResWithDsBTargets); for (final Target t_ : deployed2DS) { - final Target t = targetManagement.getByControllerId(t_.getControllerId()).get(); - assertThat(deploymentManagement.getAssignedDistributionSet(t.getControllerId())).as("assigned ds is wrong") + final Target t = targetManagement.getByControllerId(t_.getControllerId()); + assertThat(deploymentManagement.findAssignedDistributionSet(t.getControllerId())).as("assigned ds is wrong") .contains(dsA); - assertThat(deploymentManagement.getInstalledDistributionSet(t.getControllerId())) + assertThat(deploymentManagement.findInstalledDistributionSet(t.getControllerId())) .as("installed ds should be null").isNotPresent(); - assertThat(targetManagement.getByControllerId(t.getControllerId()).get().getUpdateStatus()) + assertThat(targetManagement.getByControllerId(t.getControllerId()).getUpdateStatus()) .as("wrong target info update status").isEqualTo(TargetUpdateStatus.PENDING); } @@ -1412,17 +1412,16 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { List targs = Collections.singletonList(testdataFactory.createTarget("target-id-A")); // doing the assignment - targs = assignDistributionSet(dsA, targs).getAssignedEntity().stream().map(Action::getTarget) - .toList(); + targs = assignDistributionSet(dsA, targs).getAssignedEntity().stream().map(Action::getTarget).toList(); implicitLock(dsA); - Target targ = targetManagement.getByControllerId(targs.iterator().next().getControllerId()).get(); + Target targ = targetManagement.getByControllerId(targs.iterator().next().getControllerId()); // checking the revisions of the created entities // verifying that the revision of the object and the revision within the // DB has incremented by implicit lock assertThat(dsA.getOptLockRevision()) .as("lock revision is wrong") - .isEqualTo(distributionSetManagement.getWithDetails(dsA.getId()).get().getOptLockRevision()); + .isEqualTo(distributionSetManagement.getWithDetails(dsA.getId()).getOptLockRevision()); // verifying that the assignment is correct assertThat(deploymentManagement.findActiveActionsByTarget(targ.getControllerId(), PAGE).getTotalElements()) @@ -1430,7 +1429,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { assertThat(deploymentManagement.countActionsByTarget(targ.getControllerId())).as("Target actions are wrong") .isEqualTo(1); assertThat(targ.getUpdateStatus()).as("UpdateStatus of target is wrong").isEqualTo(TargetUpdateStatus.PENDING); - assertThat(deploymentManagement.getAssignedDistributionSet(targ.getControllerId())) + assertThat(deploymentManagement.findAssignedDistributionSet(targ.getControllerId())) .as("Assigned distribution set of target is wrong").contains(dsA); assertThat(deploymentManagement.findActiveActionsByTarget(targ.getControllerId(), PAGE).getContent().get(0) .getDistributionSet()).as("Distribution set of action is wrong").isEqualTo(dsA); @@ -1441,8 +1440,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { controllerManagement.addUpdateActionStatus( ActionStatusCreate.builder().actionId(updAct.getContent().get(0).getId()).status(Status.FINISHED).build()); - targ = targetManagement.getByControllerId(targ.getControllerId()).get(); - + targ = targetManagement.getByControllerId(targ.getControllerId()); assertEquals(0, deploymentManagement.findActiveActionsByTarget(targ.getControllerId(), PAGE).getTotalElements(), "active target actions are wrong"); assertEquals(1, @@ -1450,9 +1448,9 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { "active actions are wrong"); assertEquals(TargetUpdateStatus.IN_SYNC, targ.getUpdateStatus(), "tagret update status is not correct"); - assertEquals(dsA, deploymentManagement.getAssignedDistributionSet(targ.getControllerId()).get(), + assertEquals(dsA, deploymentManagement.findAssignedDistributionSet(targ.getControllerId()).get(), "wrong assigned ds"); - assertEquals(dsA, deploymentManagement.getInstalledDistributionSet(targ.getControllerId()).get(), + assertEquals(dsA, deploymentManagement.findInstalledDistributionSet(targ.getControllerId()).get(), "wrong installed ds"); targs = assignDistributionSet(dsB.getId(), "target-id-A").getAssignedEntity().stream().map(Action::getTarget) @@ -1464,12 +1462,12 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { assertEquals(1, deploymentManagement.findActiveActionsByTarget(targ.getControllerId(), PAGE).getTotalElements(), "active actions are wrong"); assertEquals(TargetUpdateStatus.PENDING, - targetManagement.getByControllerId(targ.getControllerId()).get().getUpdateStatus(), + targetManagement.getByControllerId(targ.getControllerId()).getUpdateStatus(), "target status is wrong"); - assertEquals(dsB, deploymentManagement.getAssignedDistributionSet(targ.getControllerId()).get(), + assertEquals(dsB, deploymentManagement.findAssignedDistributionSet(targ.getControllerId()).get(), "wrong assigned ds"); assertEquals(dsA.getId(), - deploymentManagement.getInstalledDistributionSet(targ.getControllerId()).get().getId(), + deploymentManagement.findInstalledDistributionSet(targ.getControllerId()).get().getId(), "Installed ds is wrong"); assertEquals(dsB, deploymentManagement.findActiveActionsByTarget(targ.getControllerId(), PAGE).getContent() .get(0).getDistributionSet(), "Active ds is wrong"); @@ -1487,13 +1485,13 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { assertThat(dsA.getOptLockRevision()) .as("lock revision is wrong") - .isEqualTo(distributionSetManagement.getWithDetails(dsA.getId()).get().getOptLockRevision()); + .isEqualTo(distributionSetManagement.getWithDetails(dsA.getId()).getOptLockRevision()); assignDistributionSet(dsA, Collections.singletonList(targ)); // implicit lock - incremented the version assertThat(dsA.getOptLockRevision() + 1).as("lock revision is wrong") - .isEqualTo(distributionSetManagement.getWithDetails(dsA.getId()).get().getOptLockRevision()); + .isEqualTo(distributionSetManagement.getWithDetails(dsA.getId()).getOptLockRevision()); } /** @@ -1696,10 +1694,10 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { private JpaAction assignSet(final Target target, final DistributionSet ds) { assignDistributionSet(ds.getId(), target.getControllerId()); implicitLock(ds); - assertThat(targetManagement.getByControllerId(target.getControllerId()).get().getUpdateStatus()) + assertThat(targetManagement.getByControllerId(target.getControllerId()).getUpdateStatus()) .as("wrong update status").isEqualTo(TargetUpdateStatus.PENDING); - assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId())).as("wrong assigned ds") - .contains(ds); + assertThat(deploymentManagement.findAssignedDistributionSet(target.getControllerId())) + .as("wrong assigned ds").contains(ds); final JpaAction action = actionRepository .findAll( (root, query, cb) -> diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetInvalidationManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetInvalidationManagementTest.java index 348eb69f2..365c06fd9 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetInvalidationManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetInvalidationManagementTest.java @@ -267,9 +267,9 @@ class DistributionSetInvalidationManagementTest extends AbstractJpaIntegrationTe private void assertDistributionSetInvalidationCount( final DistributionSetInvalidationCount distributionSetInvalidationCount, final long expectedAutoAssignmentCount, final long expectedActionCount, final long expectedRolloutCount) { - assertThat(distributionSetInvalidationCount.getAutoAssignmentCount()).isEqualTo(expectedAutoAssignmentCount); - assertThat(distributionSetInvalidationCount.getActionCount()).isEqualTo(expectedActionCount); - assertThat(distributionSetInvalidationCount.getRolloutsCount()).isEqualTo(expectedRolloutCount); + assertThat(distributionSetInvalidationCount.autoAssignmentCount()).isEqualTo(expectedAutoAssignmentCount); + assertThat(distributionSetInvalidationCount.actionCount()).isEqualTo(expectedActionCount); + assertThat(distributionSetInvalidationCount.rolloutsCount()).isEqualTo(expectedRolloutCount); } private List findActionsByTarget(@Param("target") Target target) { // order by id ? diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetManagementTest.java index 9aa2663a0..f102e8517 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetManagementTest.java @@ -40,6 +40,7 @@ import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetUpdated import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; +import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException; import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException; import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException; @@ -85,8 +86,9 @@ class DistributionSetManagementTest extends AbstractRepositoryManagementWithMeta void nonExistingEntityAccessReturnsNotPresent() { final DistributionSet set = testdataFactory.createDistributionSet(); assertThat(distributionSetManagement.find(NOT_EXIST_IDL)).isNotPresent(); - assertThat(distributionSetManagement.getWithDetails(NOT_EXIST_IDL)).isNotPresent(); - assertThat(distributionSetManagement.findByNameAndVersion(NOT_EXIST_ID, NOT_EXIST_ID)).isNotPresent(); + assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(() -> distributionSetManagement.getWithDetails(NOT_EXIST_IDL)); + assertThatExceptionOfType(EntityNotFoundException.class) + .isThrownBy(() -> distributionSetManagement.findByNameAndVersion(NOT_EXIST_ID, NOT_EXIST_ID)); assertThat(distributionSetManagement.getMetadata(set.getId()).get(NOT_EXIST_ID)).isNull(); } @@ -277,7 +279,7 @@ class DistributionSetManagementTest extends AbstractRepositoryManagementWithMeta // assign target assignDistributionSet(ds.getId(), target.getControllerId()); - ds = distributionSetManagement.getWithDetails(ds.getId()).orElseThrow(); + ds = distributionSetManagement.getWithDetails(ds.getId()); final Long dsId = ds.getId(); // not allowed as it is assigned now @@ -348,6 +350,7 @@ class DistributionSetManagementTest extends AbstractRepositoryManagementWithMeta assertThatExceptionOfType(InvalidDistributionSetException.class) .as("Invalid distributionSet should throw an exception").isThrownBy(() -> distributionSetManagement.update(update)); } + @Test void failToModifyMetadataForInvalidDistributionSet() { final String key = forType(String.class); @@ -464,7 +467,7 @@ class DistributionSetManagementTest extends AbstractRepositoryManagementWithMeta assertThat(distributionSetManagement.find(distributionSet.getId()).map(DistributionSet::isLocked).orElse(false)).isTrue(); // assert software modules are locked assertThat(distributionSet.getModules().size()).isNotZero(); - distributionSetManagement.getWithDetails(distributionSet.getId()).map(DistributionSet::getModules).orElseThrow() + distributionSetManagement.getWithDetails(distributionSet.getId()).getModules() .forEach(module -> assertThat(module.isLocked()).isTrue()); } @@ -509,7 +512,7 @@ class DistributionSetManagementTest extends AbstractRepositoryManagementWithMeta assertThat(distributionSetManagement.find(distributionSet.getId()).map(DistributionSet::isLocked).orElse(true)).isFalse(); // assert software modules are not unlocked assertThat(distributionSet.getModules().size()).isNotZero(); - distributionSetManagement.getWithDetails(distributionSet.getId()).map(DistributionSet::getModules).orElseThrow() + distributionSetManagement.getWithDetails(distributionSet.getId()).getModules() .forEach(module -> assertThat(module.isLocked()).isTrue()); } @@ -530,7 +533,7 @@ class DistributionSetManagementTest extends AbstractRepositoryManagementWithMeta assertThatExceptionOfType(LockedException.class) .as("Attempt to modify a locked DS software modules should throw an exception") .isThrownBy(() -> distributionSetManagement.assignSoftwareModules(distributionSetId, moduleIds)); - assertThat(distributionSetManagement.getWithDetails(distributionSetId).orElseThrow().getModules()) + assertThat(distributionSetManagement.getWithDetails(distributionSetId).getModules()) .as("Software module shall not be added to a locked DS.") .hasSize(softwareModuleCount); @@ -539,7 +542,7 @@ class DistributionSetManagementTest extends AbstractRepositoryManagementWithMeta assertThatExceptionOfType(LockedException.class) .as("Attempt to modify a locked DS software modules should throw an exception") .isThrownBy(() -> distributionSetManagement.unassignSoftwareModule(distributionSetId, firstModuleId)); - assertThat(distributionSetManagement.getWithDetails(distributionSetId).orElseThrow().getModules()) + assertThat(distributionSetManagement.getWithDetails(distributionSetId).getModules()) .as("Software module shall not be removed from a locked DS.") .hasSize(softwareModuleCount); } @@ -705,15 +708,15 @@ class DistributionSetManagementTest extends AbstractRepositoryManagementWithMeta assertThat(distributionSetManagement.countRolloutsByStatusForDistributionSet(ds2.getId())).hasSize(1); assertThat(distributionSetManagement.countRolloutsByStatusForDistributionSet(ds3.getId())).isEmpty(); - Optional rollout = rolloutManagement.find(rollout1.getId()); - rollout.ifPresent(value -> assertThat(Rollout.RolloutStatus.valueOf( + Rollout rollout = rolloutManagement.get(rollout1.getId()); + assertThat(Rollout.RolloutStatus.valueOf( String.valueOf(distributionSetManagement.countRolloutsByStatusForDistributionSet(ds1.getId()).get(0).getName()))).isEqualTo( - value.getStatus())); + rollout.getStatus()); - rollout = rolloutManagement.find(rollout2.getId()); - rollout.ifPresent(value -> assertThat(Rollout.RolloutStatus.valueOf( + rollout = rolloutManagement.get(rollout2.getId()); + assertThat(Rollout.RolloutStatus.valueOf( String.valueOf(distributionSetManagement.countRolloutsByStatusForDistributionSet(ds2.getId()).get(0).getName()))).isEqualTo( - value.getStatus())); + rollout.getStatus()); } /** diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutGroupManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutGroupManagementTest.java index 16859685a..6e8ec3714 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutGroupManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutGroupManagementTest.java @@ -10,6 +10,7 @@ package org.eclipse.hawkbit.repository.jpa.management; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import org.eclipse.hawkbit.repository.event.remote.RolloutDeletedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent; @@ -21,6 +22,7 @@ import org.eclipse.hawkbit.repository.event.remote.entity.RolloutUpdatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleUpdatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent; +import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup; import org.eclipse.hawkbit.repository.model.RolloutGroup; @@ -41,8 +43,8 @@ class RolloutGroupManagementTest extends AbstractJpaIntegrationTest { @Test @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) }) void nonExistingEntityAccessReturnsNotPresent() { - assertThat(rolloutGroupManagement.get(NOT_EXIST_IDL)).isNotPresent(); - assertThat(rolloutGroupManagement.getWithDetailedStatus(NOT_EXIST_IDL)).isNotPresent(); + assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(() -> rolloutGroupManagement.get(NOT_EXIST_IDL)); + assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(() -> rolloutGroupManagement.getWithDetailedStatus(NOT_EXIST_IDL)); } /** @@ -81,10 +83,10 @@ class RolloutGroupManagementTest extends AbstractJpaIntegrationTest { testdataFactory.createAndStartRollout(1, 0, 1, "100", "80").getId(), PAGE).getContent() .get(0).getId(); for (final RolloutGroup.RolloutGroupStatus status : RolloutGroup.RolloutGroupStatus.values()) { - final JpaRolloutGroup rolloutGroup = ((JpaRolloutGroup) rolloutGroupManagement.get(id).orElseThrow()); + final JpaRolloutGroup rolloutGroup = (JpaRolloutGroup) rolloutGroupManagement.get(id); rolloutGroup.setStatus(status); rolloutGroupRepository.save(rolloutGroup); - assertThat(rolloutGroupManagement.get(id).orElseThrow().getStatus()).isEqualTo(status); + assertThat(rolloutGroupManagement.get(id).getStatus()).isEqualTo(status); } } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementTest.java index ab9f6d218..275f96ac4 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementTest.java @@ -17,7 +17,6 @@ import java.util.Arrays; import java.util.EnumMap; import java.util.List; import java.util.Map; -import java.util.NoSuchElementException; import java.util.Optional; import java.util.Set; import java.util.UUID; @@ -52,6 +51,7 @@ import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; +import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException; import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException; import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; @@ -289,9 +289,8 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { @Test @ExpectEvents({ @Expect(type = TargetCreatedEvent.class) }) void nonExistingEntityAccessReturnsNotPresent() { - assertThat(rolloutManagement.find(NOT_EXIST_IDL)).isNotPresent(); - assertThat(rolloutManagement.getByName(NOT_EXIST_ID)).isNotPresent(); - assertThat(rolloutManagement.getWithDetailedStatus(NOT_EXIST_IDL)).isNotPresent(); + assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(() -> rolloutManagement.get(NOT_EXIST_IDL)); + assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(() -> rolloutManagement.getWithDetailedStatus(NOT_EXIST_IDL)); } /** @@ -570,7 +569,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { rolloutHandler.handleAll(); // finish running actions, 2 actions should be finished assertThat(changeStatusForAllRunningActions(createdRollout, Status.FINISHED)).isEqualTo(2); - assertThat(findRollout(createdRollout.getId()).getStatus()).isEqualTo(RolloutStatus.RUNNING); + assertThat(rolloutManagement.get(createdRollout.getId()).getStatus()).isEqualTo(RolloutStatus.RUNNING); } // check rollout to see that all actions and all groups are finished and @@ -836,7 +835,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { final List targetList = targets.getContent(); assertThat(targetList).hasSize(5); - targets.getContent().stream().map(Target::getControllerId).map(deploymentManagement::getAssignedDistributionSet) + targets.getContent().stream().map(Target::getControllerId).map(deploymentManagement::findAssignedDistributionSet) .forEach(d -> assertThat(d.get().getId()).isEqualTo(ds.getId())); final List targetToCancel = new ArrayList<>(); @@ -955,7 +954,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { assertThat(targetList).hasSize(amountTargetsForRollout); targetList.stream() .map(Target::getControllerId) - .map(deploymentManagement::getAssignedDistributionSet) + .map(deploymentManagement::findAssignedDistributionSet) .forEach(d -> assertThat(d).contains(distributionSet)); } @@ -1164,25 +1163,6 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { } } - /** - * Verify that the expected rollout is found by name. - */ - @Test - void findRolloutByName() { - - final int amountTargetsForRollout = 12; - final int amountGroups = 2; - final String successCondition = "50"; - final String errorCondition = "80"; - final String rolloutName = "Rollout137"; - final Rollout rolloutCreated = createTestRolloutWithTargetsAndDistributionSet(amountTargetsForRollout, - amountGroups, successCondition, errorCondition, rolloutName, "RolloutA"); - - final Rollout rolloutFound = rolloutManagement.getByName(rolloutName).get(); - assertThat(rolloutCreated).isEqualTo(rolloutFound); - - } - /** * Verify that the percent count is acting like aspected when targets move to the status finished or error. */ @@ -1194,8 +1174,8 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { final String successCondition = "50"; final String errorCondition = "80"; final String rolloutName = "MyRollout"; - Rollout myRollout = createTestRolloutWithTargetsAndDistributionSet(amountTargetsForRollout, amountGroups, - successCondition, errorCondition, rolloutName, rolloutName); + Rollout myRollout = createTestRolloutWithTargetsAndDistributionSet( + amountTargetsForRollout, amountGroups, successCondition, errorCondition, rolloutName, rolloutName); rolloutManagement.start(myRollout.getId()); // Run here, because scheduler is disabled during tests @@ -1206,18 +1186,16 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { myRollout = reloadRollout(myRollout); float percent = rolloutGroupManagement - .getWithDetailedStatus( - rolloutGroupManagement.findByRollout(myRollout.getId(), PAGE).getContent().get(0).getId()) - .get().getTotalTargetCountStatus().getFinishedPercent(); + .getWithDetailedStatus(rolloutGroupManagement.findByRollout(myRollout.getId(), PAGE).getContent().get(0).getId()) + .getTotalTargetCountStatus().getFinishedPercent(); assertThat(percent).isEqualTo(40); changeStatusForRunningActions(myRollout, Status.FINISHED, 3); rolloutHandler.handleAll(); percent = rolloutGroupManagement - .getWithDetailedStatus( - rolloutGroupManagement.findByRollout(myRollout.getId(), PAGE).getContent().get(0).getId()) - .get().getTotalTargetCountStatus().getFinishedPercent(); + .getWithDetailedStatus(rolloutGroupManagement.findByRollout(myRollout.getId(), PAGE).getContent().get(0).getId()) + .getTotalTargetCountStatus().getFinishedPercent(); assertThat(percent).isEqualTo(100); changeStatusForRunningActions(myRollout, Status.FINISHED, 4); @@ -1225,9 +1203,8 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { rolloutHandler.handleAll(); percent = rolloutGroupManagement - .getWithDetailedStatus( - rolloutGroupManagement.findByRollout(myRollout.getId(), PAGE).getContent().get(1).getId()) - .get().getTotalTargetCountStatus().getFinishedPercent(); + .getWithDetailedStatus(rolloutGroupManagement.findByRollout(myRollout.getId(), PAGE).getContent().get(1).getId()) + .getTotalTargetCountStatus().getFinishedPercent(); assertThat(percent).isEqualTo(80); } @@ -1363,7 +1340,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { // Run here, because scheduler is disabled during tests rolloutHandler.handleAll(); - myRollout = findRollout(myRolloutId); + myRollout = rolloutManagement.get(myRolloutId); assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.RUNNING); final Map expectedTargetCountStatus = createInitStatusMap(); expectedTargetCountStatus.put(TotalTargetCountStatus.Status.RUNNING, 1L); @@ -1389,7 +1366,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.READY); rolloutHandler.handleAll(); - myRollout = findRollout(myRollout.getId()); + myRollout = rolloutManagement.get(myRollout.getId()); assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.READY); rolloutManagement.start(myRollout.getId()); @@ -1568,7 +1545,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { rolloutHandler.handleAll(); // rollout should not have been started - myRollout = findRollout(myRolloutId); + myRollout = rolloutManagement.get(myRolloutId); assertThat(myRollout.getName()).isEqualTo("newName"); assertThat(myRollout.getDescription()).isEqualTo("newDesc"); } @@ -1604,7 +1581,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { rolloutGroups.add(generateRolloutGroup(2, percentTargetsInGroup3, null)); Rollout myRollout = rolloutManagement.create(rolloutcreate, rolloutGroups, conditions); - myRollout = findRollout(myRollout.getId()); + myRollout = rolloutManagement.get(myRollout.getId()); assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.CREATING); for (final RolloutGroup group : rolloutGroupManagement.findByRollout(myRollout.getId(), PAGE).getContent()) { @@ -1616,7 +1593,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { rolloutHandler.handleAll(); - myRollout = findRollout(myRollout.getId()); + myRollout = rolloutManagement.get(myRollout.getId()); assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.READY); assertThat(myRollout.getTotalTargets()).isEqualTo(amountTargetsInGroup2and3 + amountTargetsInGroup1); @@ -1658,7 +1635,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { final Long rolloutId = rolloutManagement.create(rolloutcreate, rolloutGroups, conditions).getId(); - assertThat(findRollout(rolloutId)).satisfies(rollout -> { + assertThat(rolloutManagement.get(rolloutId)).satisfies(rollout -> { assertThat(rollout.getStatus()).isEqualTo(RolloutStatus.CREATING); for (final RolloutGroup group : rolloutGroupManagement.findByRollout(rollout.getId(), PAGE).getContent()) { assertThat(group.getStatus()).isEqualTo(RolloutGroupStatus.CREATING); @@ -1668,7 +1645,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { // first handle iteration will put rollout in ready state rolloutHandler.handleAll(); - assertThat(findRollout(rolloutId)).satisfies(rollout -> { + assertThat(rolloutManagement.get(rolloutId)).satisfies(rollout -> { assertThat(rollout.getStatus()).isEqualTo(RolloutStatus.READY); assertThat(rollout.getTotalTargets()).isEqualTo(amountTargetsInGroup1 + amountTargetsInGroup2); }); @@ -1796,7 +1773,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { .build(); Rollout myRollout = rolloutManagement.create(rolloutToCreate, amountGroups, false, conditions); - myRollout = findRollout(myRollout.getId()); + myRollout = rolloutManagement.get(myRollout.getId()); assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.CREATING); @@ -2215,10 +2192,10 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { void testRolloutStatusConvert() { final long id = testdataFactory.createAndStartRollout(1, 0, 1, "100", "80").getId(); for (final RolloutStatus status : RolloutStatus.values()) { - final JpaRollout rollout = ((JpaRollout) rolloutManagement.find(id).orElseThrow()); + final JpaRollout rollout = (JpaRollout) rolloutManagement.get(id); rollout.setStatus(status); rolloutRepository.save(rollout); - assertThat(rolloutManagement.find(id).orElseThrow().getStatus()).isEqualTo(status); + assertThat(rolloutManagement.get(id).getStatus()).isEqualTo(status); } } @@ -2229,10 +2206,10 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { void testActionTypeConvert() { final long id = testdataFactory.createAndStartRollout(1, 0, 1, "100", "80").getId(); for (final ActionType actionType : ActionType.values()) { - final JpaRollout rollout = ((JpaRollout) rolloutManagement.find(id).orElseThrow()); + final JpaRollout rollout = ((JpaRollout) rolloutManagement.get(id)); rollout.setActionType(actionType); rolloutRepository.save(rollout); - assertThat(rolloutManagement.find(id).orElseThrow().getActionType()).isEqualTo(actionType); + assertThat(rolloutManagement.get(id).getActionType()).isEqualTo(actionType); } } @@ -2355,16 +2332,12 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { } private Rollout reloadRollout(final Rollout r) { - return findRollout(r.getId()); - } - - private Rollout findRollout(final Long myRolloutId) { - return rolloutManagement.find(myRolloutId).orElseThrow(NoSuchElementException::new); + return rolloutManagement.get(r.getId()); } private void assertRolloutGroup(final long rolloutGroupId, final RolloutGroupStatus status, final boolean isConfirmationRequired, final long totalTargets, final Status actionStatusToCheck) { - assertThat(rolloutGroupManagement.get(rolloutGroupId)).hasValueSatisfying(rolloutGroup -> { + assertThat(rolloutGroupManagement.get(rolloutGroupId)).satisfies(rolloutGroup -> { assertThat(rolloutGroup.getStatus()).isEqualTo(status); assertThat(rolloutGroup.isConfirmationRequired()).isEqualTo(isConfirmationRequired); assertThat(rolloutGroup.getTotalTargets()).isEqualTo(totalTargets); @@ -2419,17 +2392,14 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest { .build(); } - private void validateRolloutGroupActionStatus(final RolloutGroup rolloutGroup, - final Map expectedTargetCountStatus) { - final RolloutGroup rolloutGroupWithDetail = rolloutGroupManagement.getWithDetailedStatus(rolloutGroup.getId()) - .get(); - validateStatus(rolloutGroupWithDetail.getTotalTargetCountStatus(), expectedTargetCountStatus); + private void validateRolloutGroupActionStatus( + final RolloutGroup rolloutGroup, final Map expectedTargetCountStatus) { + validateStatus( + rolloutGroupManagement.getWithDetailedStatus(rolloutGroup.getId()).getTotalTargetCountStatus(), expectedTargetCountStatus); } - private void validateRolloutActionStatus(final Long rolloutId, - final Map expectedTargetCountStatus) { - final Rollout rolloutWithDetail = rolloutManagement.getWithDetailedStatus(rolloutId).get(); - validateStatus(rolloutWithDetail.getTotalTargetCountStatus(), expectedTargetCountStatus); + private void validateRolloutActionStatus(final Long rolloutId, final Map expectedTargetCountStatus) { + validateStatus(rolloutManagement.getWithDetailedStatus(rolloutId).getTotalTargetCountStatus(), expectedTargetCountStatus); } private void validateStatus(final TotalTargetCountStatus totalTargetCountStatus, diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleManagementTest.java index 57c6381a5..45625f76f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleManagementTest.java @@ -19,16 +19,14 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.Set; -import java.util.function.Supplier; import jakarta.validation.ConstraintViolationException; +import org.eclipse.hawkbit.artifact.exception.ArtifactBinaryNotFoundException; import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.SoftwareModuleManagement.Create; import org.eclipse.hawkbit.repository.SoftwareModuleManagement.Update; -import org.eclipse.hawkbit.repository.artifact.exception.ArtifactBinaryNotFoundException; import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent; import org.eclipse.hawkbit.repository.exception.LockedException; import org.eclipse.hawkbit.repository.jpa.RandomGeneratedInputStream; @@ -185,8 +183,9 @@ class SoftwareModuleManagementTest SoftwareModule moduleX = createSoftwareModuleWithArtifacts(osType, "modulex", "v1.0", 0); // [STEP2]: Create newArtifactX and add it to SoftwareModuleX - artifactManagement.create(new ArtifactUpload(new ByteArrayInputStream(source), moduleX.getId(), "artifactx", - false, artifactSize)); + artifactManagement.create(new ArtifactUpload( + new ByteArrayInputStream(source), null, artifactSize, null, + moduleX.getId(), "artifactx", false)); moduleX = softwareModuleManagement.find(moduleX.getId()).get(); final Artifact artifactX = moduleX.getArtifacts().iterator().next(); @@ -194,8 +193,9 @@ class SoftwareModuleManagementTest SoftwareModule moduleY = createSoftwareModuleWithArtifacts(osType, "moduley", "v1.0", 0); // [STEP4]: Assign the same ArtifactX to SoftwareModuleY - artifactManagement.create(new ArtifactUpload(new ByteArrayInputStream(source), moduleY.getId(), "artifactx", - false, artifactSize)); + artifactManagement.create(new ArtifactUpload( + new ByteArrayInputStream(source), null, artifactSize, null, + moduleY.getId(), "artifactx", false)); moduleY = softwareModuleManagement.find(moduleY.getId()).get(); final Artifact artifactY = moduleY.getArtifacts().iterator().next(); @@ -231,15 +231,18 @@ class SoftwareModuleManagementTest // [STEP1]: Create SoftwareModuleX and add a new ArtifactX SoftwareModule moduleX = createSoftwareModuleWithArtifacts(osType, "modulex", "v1.0", 0); - artifactManagement.create(new ArtifactUpload(new ByteArrayInputStream(source), moduleX.getId(), "artifactx", false, artifactSize)); + artifactManagement.create(new ArtifactUpload( + new ByteArrayInputStream(source), null, artifactSize, null, + moduleX.getId(), "artifactx", false)); moduleX = softwareModuleManagement.find(moduleX.getId()).get(); final Artifact artifactX = moduleX.getArtifacts().iterator().next(); // [STEP2]: Create SoftwareModuleY and add the same ArtifactX SoftwareModule moduleY = createSoftwareModuleWithArtifacts(osType, "moduley", "v1.0", 0); - artifactManagement.create(new ArtifactUpload(new ByteArrayInputStream(source), moduleY.getId(), "artifactx", - false, artifactSize)); + artifactManagement.create(new ArtifactUpload( + new ByteArrayInputStream(source), null, artifactSize, null, + moduleY.getId(), "artifactx", false)); moduleY = softwareModuleManagement.find(moduleY.getId()).get(); final Artifact artifactY = moduleY.getArtifacts().iterator().next(); @@ -338,7 +341,8 @@ class SoftwareModuleManagementTest void lockSoftwareModuleApplied() { SoftwareModule softwareModule = testdataFactory.createSoftwareModule("sm-1"); final Long softwareModuleId = softwareModule.getId(); - artifactManagement.create(new ArtifactUpload(new ByteArrayInputStream(new byte[] { 1 }), softwareModuleId, "artifact1", false, 1)); + artifactManagement.create(new ArtifactUpload( + new ByteArrayInputStream(new byte[] { 1 }), null, 1, null, softwareModuleId, "artifact1", false)); // update software module reference since it is modified, old reference is stale final int artifactCount = (softwareModule = softwareModuleManagement.find(softwareModuleId).orElseThrow()).getArtifacts().size(); assertThat(artifactCount).isNotZero(); @@ -346,8 +350,8 @@ class SoftwareModuleManagementTest assertThat(softwareModuleManagement.find(softwareModuleId).map(SoftwareModule::isLocked).orElse(false)).isTrue(); // try add - final ArtifactUpload artifactUpload = new ArtifactUpload(new ByteArrayInputStream(new byte[] { 2 }), softwareModuleId, "artifact2", - false, 1); + final ArtifactUpload artifactUpload = new ArtifactUpload( + new ByteArrayInputStream(new byte[] { 2 }), null, 1, null, softwareModuleId, "artifact2", false); assertThatExceptionOfType(LockedException.class) .as("Attempt to modify a locked SM artifacts should throw an exception") .isThrownBy(() -> artifactManagement.create(artifactUpload)); @@ -425,8 +429,9 @@ class SoftwareModuleManagementTest final int artifactSize = 5 * 1024; for (int i = 0; i < numberArtifacts; i++) { - artifactManagement.create(new ArtifactUpload(new RandomGeneratedInputStream(artifactSize), - softwareModule.getId(), "file" + (i + 1), false, artifactSize)); + artifactManagement.create(new ArtifactUpload( + new RandomGeneratedInputStream(artifactSize), null, artifactSize, null, + softwareModule.getId(), "file" + (i + 1), false)); } // Verify correct Creation of SoftwareModule and corresponding artifacts diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleTypeManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleTypeManagementTest.java index b9f956e32..b7bc693de 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleTypeManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleTypeManagementTest.java @@ -35,7 +35,6 @@ class SoftwareModuleTypeManagementTest extends AbstractRepositoryManagementTest< @Test void failIfReferNotExistingEntity() { assertThat(softwareModuleTypeManagement.findByKey(NOT_EXIST_ID)).isNotPresent(); - assertThat(softwareModuleTypeManagement.findByName(NOT_EXIST_ID)).isNotPresent(); verifyThrownExceptionBy(() -> softwareModuleTypeManagement.delete(NOT_EXIST_IDL), "SoftwareModuleType"); verifyThrownExceptionBy(() -> softwareModuleTypeManagement.update(Update.builder().id(NOT_EXIST_IDL).build()), "SoftwareModuleType"); } @@ -88,19 +87,6 @@ class SoftwareModuleTypeManagementTest extends AbstractRepositoryManagementTest< softwareModuleTypeRepository.findById(type.getId()).orElseThrow()); } - @SuppressWarnings("unchecked") - @Test - void findSoftwareModuleTypeByName() { - testdataFactory.createSoftwareModuleOs(); - final SoftwareModuleType found = softwareModuleTypeManagement - .create(Create.builder().key("thetype").name("thename").build()); - softwareModuleTypeManagement - .create(Create.builder().key("thetype2").name("anothername").build()); - - Assertions.assertThat(((SoftwareModuleTypeManagement) softwareModuleTypeManagement).findByName("thename")) - .as("Type with given name").contains(found); - } - /** * Verifies that the creation of a softwareModuleType is failing because of invalid max assignment */ diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SystemManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SystemManagementTest.java index eb5fcc7e1..787685331 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SystemManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SystemManagementTest.java @@ -21,7 +21,7 @@ import org.eclipse.hawkbit.repository.model.ArtifactUpload; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.Target; -import org.eclipse.hawkbit.repository.report.model.TenantUsage; +import org.eclipse.hawkbit.repository.model.report.TenantUsage; import org.eclipse.hawkbit.repository.test.util.DisposableSqlTestDatabaseExtension; import org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch; import org.junit.jupiter.api.Test; @@ -38,7 +38,7 @@ class SystemManagementTest extends AbstractJpaIntegrationTest { * Ensures that findTenants returns all tenants and not only restricted to the tenant which currently is logged in */ @Test - void findTenantsReturnsAllTenantsNotOnlyWhichLoggedIn() throws Exception { + void findTenantsReturnsAllTenantsNotOnlyWhichLoggedIn() { assertThat(systemManagement.findTenants(PAGE).getContent()).hasSize(1); createTestTenantsForSystemStatistics(2, 0, 0, 0); @@ -50,7 +50,7 @@ class SystemManagementTest extends AbstractJpaIntegrationTest { * Ensures that getSystemUsageStatisticsWithTenants returns the usage of all tenants and not only the first 1000 (max page size). */ @Test - void systemUsageReportCollectsStatisticsOfManyTenants() throws Exception { + void systemUsageReportCollectsStatisticsOfManyTenants() { // Prepare tenants createTestTenantsForSystemStatistics(1050, 0, 0, 0); @@ -62,7 +62,7 @@ class SystemManagementTest extends AbstractJpaIntegrationTest { * Checks that the system report calculates correctly the artifact size of all tenants in the system. It ignores deleted software modules with their artifacts. */ @Test - void systemUsageReportCollectsArtifactsOfAllTenants() throws Exception { + void systemUsageReportCollectsArtifactsOfAllTenants() { // Prepare tenants createTestTenantsForSystemStatistics(2, 1234, 0, 0); @@ -88,7 +88,7 @@ class SystemManagementTest extends AbstractJpaIntegrationTest { * Checks that the system report calculates correctly the targets size of all tenants in the system */ @Test - void systemUsageReportCollectsTargetsOfAllTenants() throws Exception { + void systemUsageReportCollectsTargetsOfAllTenants() { // Prepare tenants createTestTenantsForSystemStatistics(2, 0, 100, 0); @@ -110,7 +110,7 @@ class SystemManagementTest extends AbstractJpaIntegrationTest { * Checks that the system report calculates correctly the actions size of all tenants in the system */ @Test - void systemUsageReportCollectsActionsOfAllTenants() throws Exception { + void systemUsageReportCollectsActionsOfAllTenants() { // Prepare tenants createTestTenantsForSystemStatistics(2, 0, 20, 2); @@ -129,7 +129,7 @@ class SystemManagementTest extends AbstractJpaIntegrationTest { assertThat(tenants).containsOnly(new TenantUsage("DEFAULT"), tenantUsage0, tenantUsage1); } - private byte[] createTestTenantsForSystemStatistics(final int tenants, final int artifactSize, final int targets, final int updates) { + private void createTestTenantsForSystemStatistics(final int tenants, final int artifactSize, final int targets, final int updates) { final Random randomgen = new Random(); final byte[] random = new byte[artifactSize]; randomgen.nextBytes(random); @@ -158,8 +158,6 @@ class SystemManagementTest extends AbstractJpaIntegrationTest { return null; }); } - - return random; } private List createTestTargets(final int targets) { @@ -170,14 +168,14 @@ class SystemManagementTest extends AbstractJpaIntegrationTest { final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); artifactManagement.create( - new ArtifactUpload(new ByteArrayInputStream(random), sm.getId(), "file1", false, random.length)); + new ArtifactUpload(new ByteArrayInputStream(random), null, random.length, null, sm.getId(), "file1", false)); } private void createDeletedTestArtifact(final byte[] random) { final DistributionSet ds = testdataFactory.createDistributionSet("deleted garbage", true); ds.getModules().forEach(module -> { artifactManagement.create( - new ArtifactUpload(new ByteArrayInputStream(random), module.getId(), "file1", false, random.length)); + new ArtifactUpload(new ByteArrayInputStream(random), null, random.length, null, module.getId(), "file1", false)); softwareModuleManagement.delete(module.getId()); }); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementSearchTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementSearchTest.java index 96ec21dd9..7b289cfd1 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementSearchTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementSearchTest.java @@ -45,7 +45,7 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest { assignDistributionSet(assignedSet, assignedtargets); // get final updated version of targets - assignedtargets = targetManagement.getByControllerId(assignedtargets.stream().map(Target::getControllerId).toList()); + assignedtargets = targetManagement.findByControllerId(assignedtargets.stream().map(Target::getControllerId).toList()); assertThat(targetManagement.findByAssignedDistributionSet(assignedSet.getId(), PAGE)) .as("Contains the assigned targets").containsAll(assignedtargets) @@ -90,7 +90,7 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest { assignDistributionSet(assignedSet, installedtargets); // get final updated version of targets - installedtargets = targetManagement.getByControllerId(installedtargets.stream().map(Target::getControllerId).toList()); + installedtargets = targetManagement.findByControllerId(installedtargets.stream().map(Target::getControllerId).toList()); assertThat(targetManagement.findByInstalledDistributionSet(installedSet.getId(), PAGE)) .as("Contains the assigned targets").containsAll(installedtargets) diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java index a7433e39a..cf7ce60a6 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java @@ -233,15 +233,15 @@ class TargetManagementTest extends AbstractRepositoryManagementWithMetadataTest< assignDistributionSet(testDs2.getId(), "4711"); implicitLock(testDs2); - Target target = targetManagement.getByControllerId("4711").orElseThrow(IllegalStateException::new); + final Target target = targetManagement.getByControllerId("4711"); // read data assertThat(target.getLastTargetQuery()).as("Target query is not work").isGreaterThanOrEqualTo(current); - final DistributionSet assignedDs = deploymentManagement.getAssignedDistributionSet("4711") + final DistributionSet assignedDs = deploymentManagement.findAssignedDistributionSet("4711") .orElseThrow(NoSuchElementException::new); assertThat(assignedDs).as("Assigned ds size is wrong").isEqualTo(testDs2); - final DistributionSet installedDs = deploymentManagement.getInstalledDistributionSet("4711") + final DistributionSet installedDs = deploymentManagement.findInstalledDistributionSet("4711") .orElseThrow(NoSuchElementException::new); assertThat(installedDs).as("Installed ds is wrong").isEqualTo(testDs1); } @@ -266,17 +266,13 @@ class TargetManagementTest extends AbstractRepositoryManagementWithMetadataTest< final List t2Tags = testdataFactory.createTargetTags(noT2Tags, "tag2"); t2Tags.forEach(tag -> targetManagement.assignTag(Collections.singletonList(t2.getControllerId()), tag.getId())); - final Target t11 = targetManagement.getByControllerId(t1.getControllerId()) - .orElseThrow(IllegalStateException::new); - assertThat(getTargetTags(t11.getControllerId())).as("Tag size is wrong") - .hasSize(noT1Tags).containsAll(t1Tags); + final Target t11 = targetManagement.getByControllerId(t1.getControllerId()); + assertThat(getTargetTags(t11.getControllerId())).as("Tag size is wrong").hasSize(noT1Tags).containsAll(t1Tags); assertThat(getTargetTags(t11.getControllerId())).as("Tag size is wrong") .hasSize(noT1Tags).doesNotContain(toArray(t2Tags, TargetTag.class)); - final Target t21 = targetManagement.getByControllerId(t2.getControllerId()) - .orElseThrow(IllegalStateException::new); - assertThat(getTargetTags(t21.getControllerId())).as("Tag size is wrong") - .hasSize(noT2Tags).containsAll(t2Tags); + final Target t21 = targetManagement.getByControllerId(t2.getControllerId()); + assertThat(getTargetTags(t21.getControllerId())).as("Tag size is wrong").hasSize(noT2Tags).containsAll(t2Tags); assertThat(getTargetTags(t21.getControllerId())).as("Tag size is wrong") .hasSize(noT2Tags).doesNotContain(toArray(t1Tags, TargetTag.class)); } @@ -445,8 +441,7 @@ class TargetManagementTest extends AbstractRepositoryManagementWithMetadataTest< controllerManagement.findOrRegisterTargetIfItDoesNotExist(knownTargetControllerId, new URI("http://127.0.0.1")); SecurityContextSwitch.getAs(SecurityContextSwitch.withUser("bumlux", "READ_TARGET"), () -> { - final Target findTargetByControllerID = targetManagement.getByControllerId(knownTargetControllerId) - .orElseThrow(IllegalStateException::new); + final Target findTargetByControllerID = targetManagement.getByControllerId(knownTargetControllerId); assertThat(findTargetByControllerID).isNotNull(); assertThat(findTargetByControllerID.getPollStatus()).isNotNull(); return null; @@ -485,8 +480,7 @@ class TargetManagementTest extends AbstractRepositoryManagementWithMetadataTest< assertThat(target.isRequestControllerAttributes()).isFalse(); targetManagement.update(Update.builder().id(target.getId()).requestControllerAttributes(true).build()); - final Target updated = targetManagement.getByControllerId(knownControllerId).orElseThrow(); - assertThat(updated.isRequestControllerAttributes()).isTrue(); + assertThat(targetManagement.getByControllerId(knownControllerId).isRequestControllerAttributes()).isTrue(); } /** @@ -1093,7 +1087,7 @@ class TargetManagementTest extends AbstractRepositoryManagementWithMetadataTest< private void checkTargetHasNotTags(final Iterable targets, final TargetTag... tags) { for (final Target tl : targets) { - targetManagement.getByControllerId(tl.getControllerId()).orElseThrow(); + assertThat(targetManagement.getByControllerId(tl.getControllerId())).isNotNull(); for (final Tag tag : tags) { for (final Tag tt : getTargetTags(tl.getControllerId())) { if (tag.getName().equals(tt.getName())) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetTagManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetTagManagementTest.java index 7996d3833..51385c6c8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetTagManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetTagManagementTest.java @@ -54,7 +54,7 @@ class TargetTagManagementTest extends AbstractRepositoryManagementTest A is now assigned List result = assignTag(groupA, tag); assertThat(result) - .containsAll(targetManagement.getByControllerId(groupA.stream().map(Target::getControllerId).toList())) + .containsAll(targetManagement.findByControllerId(groupA.stream().map(Target::getControllerId).toList())) .size().isEqualTo(20); assertThat(targetManagement.findByTag(tag.getId(), Pageable.unpaged()).getContent().stream().map(Target::getControllerId).sorted() .toList()) @@ -64,7 +64,7 @@ class TargetTagManagementTest extends AbstractRepositoryManagementTest groupAB = concat(groupA, groupB); result = assignTag(groupAB, tag); assertThat(result) - .containsAll(targetManagement.getByControllerId(groupAB.stream().map(Target::getControllerId).toList())) + .containsAll(targetManagement.findByControllerId(groupAB.stream().map(Target::getControllerId).toList())) .size().isEqualTo(40); assertThat(targetManagement.findByTag(tag.getId(), Pageable.unpaged()).getContent().stream().map(Target::getControllerId).sorted() .toList()) @@ -73,7 +73,7 @@ class TargetTagManagementTest extends AbstractRepositoryManagementTest both unassigned result = unassignTag(groupAB, tag); assertThat(result) - .containsAll(targetManagement.getByControllerId(groupAB.stream().map(Target::getControllerId).toList())) + .containsAll(targetManagement.findByControllerId(groupAB.stream().map(Target::getControllerId).toList())) .size().isEqualTo(40); assertThat(targetManagement.findByTag(tag.getId(), Pageable.unpaged()).getContent()).isEmpty(); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/model/EntityInterceptorListenerTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/model/EntityInterceptorListenerTest.java index 5f617d8ff..a42f69f61 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/model/EntityInterceptorListenerTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/model/EntityInterceptorListenerTest.java @@ -60,7 +60,7 @@ class EntityInterceptorListenerTest extends AbstractJpaIntegrationTest { final Target targetToBeCreated = testdataFactory.createTarget("targetToBeCreated"); - final Target loadedTarget = targetManagement.getByControllerId(targetToBeCreated.getControllerId()).get(); + final Target loadedTarget = targetManagement.getByControllerId(targetToBeCreated.getControllerId()); assertThat(postLoadEntityListener.getEntity()).isNotNull(); assertThat(postLoadEntityListener.getEntity()).isEqualTo(loadedTarget); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlRolloutFieldTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlRolloutFieldTest.java index a749dda70..18adaf6e1 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlRolloutFieldTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlRolloutFieldTest.java @@ -36,7 +36,7 @@ class RsqlRolloutFieldTest extends AbstractJpaIntegrationTest { testdataFactory.createTargets(20, "rollout", "rollout"); final DistributionSet dsA = testdataFactory.createDistributionSet(""); rollout = createRollout("rollout1", 4, dsA.getId(), "controllerId==rollout*"); - rollout = rolloutManagement.find(rollout.getId()).get(); + rollout = rolloutManagement.get(rollout.getId()); } /** diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlRolloutGroupFieldTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlRolloutGroupFieldTest.java index ed80790de..837f031ba 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlRolloutGroupFieldTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlRolloutGroupFieldTest.java @@ -40,9 +40,9 @@ class RsqlRolloutGroupFieldTest extends AbstractJpaIntegrationTest { testdataFactory.createTargets(amountTargets, "rollout", "rollout"); final DistributionSet dsA = testdataFactory.createDistributionSet(""); rollout = createRollout("rollout1", 4, dsA.getId(), "controllerId==rollout*"); - rollout = rolloutManagement.find(rollout.getId()).get(); + rollout = rolloutManagement.get(rollout.getId()); - this.rolloutGroupId = rolloutGroupManagement.findByRollout(rollout.getId(), PAGE).getContent().get(0).getId(); + rolloutGroupId = rolloutGroupManagement.findByRollout(rollout.getId(), PAGE).getContent().get(0).getId(); } /** diff --git a/hawkbit-repository/hawkbit-repository-test/pom.xml b/hawkbit-repository/hawkbit-repository-test/pom.xml index 4ff8277ce..29ab2c112 100644 --- a/hawkbit-repository/hawkbit-repository-test/pom.xml +++ b/hawkbit-repository/hawkbit-repository-test/pom.xml @@ -48,7 +48,7 @@ org.eclipse.hawkbit - hawkbit-artifact-repository-filesystem + hawkbit-artifact-fs ${project.version} diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/TestConfiguration.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/TestConfiguration.java index 2910d301d..ff7806317 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/TestConfiguration.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/TestConfiguration.java @@ -17,13 +17,13 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.atomic.AtomicLong; import org.eclipse.hawkbit.ContextAware; +import org.eclipse.hawkbit.artifact.ArtifactStorage; +import org.eclipse.hawkbit.artifact.fs.FileArtifactProperties; +import org.eclipse.hawkbit.artifact.fs.FileArtifactStorage; +import org.eclipse.hawkbit.artifact.urlresolver.PropertyBasedArtifactUrlResolver; +import org.eclipse.hawkbit.artifact.urlresolver.PropertyBasedArtifactUrlResolverProperties; +import org.eclipse.hawkbit.tenancy.cache.TenantAwareCacheManager; import org.eclipse.hawkbit.im.authentication.Hierarchy; -import org.eclipse.hawkbit.repository.artifact.ArtifactFilesystemProperties; -import org.eclipse.hawkbit.repository.artifact.ArtifactFilesystemRepository; -import org.eclipse.hawkbit.repository.artifact.ArtifactRepository; -import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrlHandlerProperties; -import org.eclipse.hawkbit.repository.artifact.urlhandler.PropertyBasedArtifactUrlHandler; -import org.eclipse.hawkbit.cache.TenantAwareCacheManager; import org.eclipse.hawkbit.repository.RolloutApprovalStrategy; import org.eclipse.hawkbit.repository.RolloutStatusCache; import org.eclipse.hawkbit.repository.event.ApplicationEventFilter; @@ -71,7 +71,7 @@ import org.springframework.security.concurrent.DelegatingSecurityContextSchedule */ @Configuration @EnableConfigurationProperties({ - DdiSecurityProperties.class, ArtifactUrlHandlerProperties.class, ArtifactFilesystemProperties.class, + DdiSecurityProperties.class, PropertyBasedArtifactUrlResolverProperties.class, FileArtifactProperties.class, HawkbitSecurityProperties.class, ControllerPollProperties.class, TenantConfigurationProperties.class }) @Profile("test") @EnableAutoConfiguration @@ -123,8 +123,8 @@ public class TestConfiguration implements AsyncConfigurer { } @Bean - ArtifactRepository artifactRepository(final ArtifactFilesystemProperties artifactFilesystemProperties) { - return new ArtifactFilesystemRepository(artifactFilesystemProperties); + ArtifactStorage artifactRepository(final FileArtifactProperties artifactFilesystemProperties) { + return new FileArtifactStorage(artifactFilesystemProperties); } /** @return the {@link org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch} to be injected. */ @@ -134,8 +134,9 @@ public class TestConfiguration implements AsyncConfigurer { } @Bean - PropertyBasedArtifactUrlHandler testPropertyBasedArtifactUrlHandler(final ArtifactUrlHandlerProperties urlHandlerProperties) { - return new PropertyBasedArtifactUrlHandler(urlHandlerProperties, ""); + PropertyBasedArtifactUrlResolver testPropertyBasedArtifactUrlHandler( + final PropertyBasedArtifactUrlResolverProperties urlHandlerProperties) { + return new PropertyBasedArtifactUrlResolver(urlHandlerProperties, ""); } @Bean diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java index 8d3765a54..27674c1e4 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java @@ -11,8 +11,8 @@ package org.eclipse.hawkbit.repository.test.util; import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.hawkbit.im.authentication.SpPermission.READ_TENANT_CONFIGURATION; -import static org.eclipse.hawkbit.im.authentication.SpRole.SYSTEM_ROLE; import static org.eclipse.hawkbit.im.authentication.SpRole.CONTROLLER_ROLE; +import static org.eclipse.hawkbit.im.authentication.SpRole.SYSTEM_ROLE; import java.io.File; import java.io.IOException; @@ -29,10 +29,14 @@ import java.util.NoSuchElementException; import java.util.Optional; import java.util.Random; +import jakarta.validation.constraints.NotEmpty; + import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; import org.awaitility.Awaitility; import org.awaitility.core.ConditionFactory; +import org.eclipse.hawkbit.artifact.ArtifactStorage; +import org.eclipse.hawkbit.artifact.exception.ArtifactStoreException; import org.eclipse.hawkbit.repository.ArtifactManagement; import org.eclipse.hawkbit.repository.ConfirmationManagement; import org.eclipse.hawkbit.repository.ControllerManagement; @@ -54,8 +58,6 @@ import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TargetTagManagement; import org.eclipse.hawkbit.repository.TargetTypeManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement; -import org.eclipse.hawkbit.repository.artifact.ArtifactRepository; -import org.eclipse.hawkbit.repository.artifact.exception.ArtifactStoreException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate; @@ -176,7 +178,7 @@ public abstract class AbstractIntegrationTest { @Autowired protected SystemSecurityContext systemSecurityContext; @Autowired - protected ArtifactRepository binaryArtifactRepository; + protected ArtifactStorage binaryArtifactRepository; @Autowired protected QuotaManagement quotaManagement; @@ -521,6 +523,11 @@ public abstract class AbstractIntegrationTest { return targetManagement.findAll(pageable).stream().filter(target -> status.equals(target.getUpdateStatus())).toList(); } + protected TargetType findTargetTypeByName(@NotEmpty String name) { + return targetTypeManagement.findByRsql("name==" + name, UNPAGED).stream().findAny() + .orElseThrow(() -> new EntityNotFoundException(TargetType.class, name)); + } + @SafeVarargs protected static Collection concat(final Collection... targets) { final List result = new ArrayList<>(); diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/CleanupTestExecutionListener.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/CleanupTestExecutionListener.java index 4643cc3ae..812669ef2 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/CleanupTestExecutionListener.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/CleanupTestExecutionListener.java @@ -14,7 +14,7 @@ import java.util.List; import jakarta.validation.constraints.NotNull; import lombok.extern.slf4j.Slf4j; -import org.eclipse.hawkbit.cache.TenantAwareCacheManager; +import org.eclipse.hawkbit.tenancy.cache.TenantAwareCacheManager; import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.security.SystemSecurityContext; import org.springframework.context.ApplicationContext; diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java index b7192693b..16ae74fd0 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java @@ -23,7 +23,6 @@ import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; -import java.util.NoSuchElementException; import java.util.Set; import java.util.UUID; import java.util.stream.IntStream; @@ -241,7 +240,6 @@ public class TestdataFactory { return createDistributionSet(UUID.randomUUID().toString(), DEFAULT_VERSION, false); } - public DistributionSet createDistributionSetLocked() { return distributionSetManagement.lock(createDistributionSet()); } @@ -488,7 +486,7 @@ public class TestdataFactory { */ public Artifact createArtifact(final String artifactData, final Long moduleId, final String filename) { final InputStream stubInputStream = IOUtils.toInputStream(artifactData, StandardCharsets.UTF_8); - return artifactManagement.create(new ArtifactUpload(stubInputStream, moduleId, filename, false, artifactData.length())); + return artifactManagement.create(new ArtifactUpload(stubInputStream, null, artifactData.length(), null, moduleId, filename, false)); } /** @@ -502,7 +500,7 @@ public class TestdataFactory { */ public Artifact createArtifact(final byte[] artifactData, final Long moduleId, final String filename, final int fileSize) { return artifactManagement.create( - new ArtifactUpload(new ByteArrayInputStream(artifactData), moduleId, filename, false, fileSize)); + new ArtifactUpload(new ByteArrayInputStream(artifactData), null, fileSize, null, moduleId, filename, false)); } /** @@ -637,7 +635,7 @@ public class TestdataFactory { SoftwareModuleManagement.Update.builder().id(module.getId()).description("Updated " + DEFAULT_DESCRIPTION).build())); // load also lazy stuff - return distributionSetManagement.getWithDetails(set.getId()).orElseThrow(); + return distributionSetManagement.getWithDetails(set.getId()); } /** @@ -1053,7 +1051,7 @@ public class TestdataFactory { // Run here, because Scheduler is disabled during tests rolloutHandleAll(); - return rolloutManagement.find(rollout.getId()).orElseThrow(); + return rolloutManagement.get(rollout.getId()); } /** @@ -1178,7 +1176,9 @@ public class TestdataFactory { * @return persisted {@link TargetType} */ public TargetType findOrCreateTargetType(final String targetTypeName) { - return targetTypeManagement.getByName(targetTypeName) + return targetTypeManagement.findByRsql("name==" + targetTypeName, Pageable.unpaged()) + .stream().findAny() + .map(TargetType.class::cast) .orElseGet(() -> targetTypeManagement.create(TargetTypeManagement.Create.builder() .name(targetTypeName).description(targetTypeName + SPACE_AND_DESCRIPTION) .key(targetTypeName + " key").colour(DEFAULT_COLOUR) @@ -1298,6 +1298,6 @@ public class TestdataFactory { } private Rollout reloadRollout(final Rollout rollout) { - return rolloutManagement.find(rollout.getId()).orElseThrow(NoSuchElementException::new); + return rolloutManagement.get(rollout.getId()); } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/resources/hawkbit-test-defaults.properties b/hawkbit-repository/hawkbit-repository-test/src/main/resources/hawkbit-test-defaults.properties index 10ddf3eea..151e1a4d3 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/resources/hawkbit-test-defaults.properties +++ b/hawkbit-repository/hawkbit-repository-test/src/main/resources/hawkbit-test-defaults.properties @@ -43,7 +43,7 @@ hawkbit.artifact.url.protocols.download-http.ip=127.0.0.1 hawkbit.artifact.url.protocols.download-http.protocol=http hawkbit.artifact.url.protocols.download-http.port=8080 hawkbit.artifact.url.protocols.download-http.supports=DMF,DDI -hawkbit.artifact.url.protocols.download-http.ref={protocol}://{hostnameRequest}:{portRequest}/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}/download +hawkbit.artifact.url.protocols.download-http.ref={protocolRequest}://{hostnameRequest}:{portRequest}/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName} hawkbit.artifact.url.protocols.md5sum-http.rel=md5sum-http hawkbit.artifact.url.protocols.md5sum-http.protocol=${hawkbit.artifact.url.protocols.download-http.protocol} hawkbit.artifact.url.protocols.md5sum-http.hostname=${hawkbit.artifact.url.protocols.download-http.hostname} @@ -59,6 +59,7 @@ hawkbit.artifact.url.protocols.download-cdn-http.port=8080 hawkbit.artifact.url.protocols.download-cdn-http.supports=MGMT hawkbit.artifact.url.protocols.download-cdn-http.ref={protocol}://download-cdn.com/artifacts/{artifactFileName}/download ## Download URL Generation - END +## Download URL Generation - END # Quota - START hawkbit.server.security.dos.maxStatusEntriesPerAction=10 diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/MultiPartFileUploadException.java b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/MultiPartFileUploadException.java index 395375d5a..e65b5e4bc 100644 --- a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/MultiPartFileUploadException.java +++ b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/MultiPartFileUploadException.java @@ -23,6 +23,6 @@ public final class MultiPartFileUploadException extends AbstractServerRtExceptio private static final long serialVersionUID = 1L; public MultiPartFileUploadException(final Throwable cause) { - super(cause.getMessage(), SpServerError.SP_ARTIFACT_UPLOAD_FAILED, cause); + super(SpServerError.SP_ARTIFACT_UPLOAD_FAILED, cause.getMessage(), cause); } } \ No newline at end of file diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FileStreamingFailedException.java b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FileStreamingFailedException.java index 2ac0ed861..dbaa5f879 100644 --- a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FileStreamingFailedException.java +++ b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FileStreamingFailedException.java @@ -28,7 +28,7 @@ public final class FileStreamingFailedException extends AbstractServerRtExceptio * @param message of the error */ public FileStreamingFailedException(final String message) { - super(message, SpServerError.SP_ARTIFACT_LOAD_FAILED); + super(SpServerError.SP_ARTIFACT_LOAD_FAILED, message); } /** @@ -38,6 +38,6 @@ public final class FileStreamingFailedException extends AbstractServerRtExceptio * @param cause for the exception */ public FileStreamingFailedException(final String message, final Throwable cause) { - super(message, SpServerError.SP_ARTIFACT_LOAD_FAILED, cause); + super(SpServerError.SP_ARTIFACT_LOAD_FAILED, message, cause); } } \ No newline at end of file diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FileStreamingUtil.java b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FileStreamingUtil.java index 7f0f796a7..5c09d5ef9 100644 --- a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FileStreamingUtil.java +++ b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FileStreamingUtil.java @@ -26,7 +26,7 @@ import lombok.AccessLevel; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.IOUtils; -import org.eclipse.hawkbit.repository.artifact.model.DbArtifact; +import org.eclipse.hawkbit.artifact.model.ArtifactStream; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -46,7 +46,6 @@ public final class FileStreamingUtil { * Write response with target relation and publishes events concerning the * download progress based on given update action status. *

    - * *

    * The request supports RFC7233 range requests. *

    @@ -59,16 +58,16 @@ public final class FileStreamingUtil { * @param progressListener to write progress updates to * @return http response * @throws FileStreamingFailedException if streaming fails - * @see https://tools.ietf.org - * /html/rfc7233 + * @see https://tools.ietf.org/html/rfc7233 */ - public static ResponseEntity writeFileResponse(final DbArtifact artifact, final String filename, + public static ResponseEntity writeFileResponse( + final ArtifactStream artifact, final String filename, final long lastModified, final HttpServletResponse response, final HttpServletRequest request, final FileStreamingProgressListener progressListener) { ResponseEntity result; - final String etag = artifact.getHashes().getSha1(); + final String etag = artifact.getSha1Hash(); final long length = artifact.getSize(); resetResponseExceptHeaders(response); @@ -114,20 +113,21 @@ public final class FileStreamingUtil { } } - // full request - no range - if (ranges.isEmpty() || ranges.get(0).equals(full)) { - log.debug("filename ({}) results into a full request: ", filename); - result = handleFullFileRequest(artifact, filename, response, progressListener, full); - } - // standard range request - else if (ranges.size() == 1) { - log.debug("filename ({}) results into a standard range request: ", filename); - result = handleStandardRangeRequest(artifact, filename, response, progressListener, ranges); - } - // multipart range request - else { - log.debug("filename ({}) results into a multipart range request: ", filename); - result = handleMultipartRangeRequest(artifact, filename, response, progressListener, ranges); + try (final InputStream inputStream = artifact) { + // full request - no range + if (ranges.isEmpty() || ranges.get(0).equals(full)) { + log.debug("filename ({}) results into a full request: ", filename); + result = handleFullFileRequest(inputStream, filename, response, progressListener, full); + } else if (ranges.size() == 1) { // standard range request + log.debug("filename ({}) results into a standard range request: ", filename); + result = handleStandardRangeRequest(inputStream, filename, response, progressListener, ranges.get(0)); + } else { // multipart range request + log.debug("filename ({}) results into a multipart range request: ", filename); + result = handleMultipartRangeRequest(inputStream, filename, response, progressListener, ranges); + } + } catch (final IOException e) { + log.error("streaming of file ({}) failed!", filename, e); + throw new FileStreamingFailedException(filename, e); } return result; @@ -146,16 +146,15 @@ public final class FileStreamingUtil { storedHeaders.forEach(response::addHeader); } - private static ResponseEntity handleFullFileRequest(final DbArtifact artifact, final String filename, - final HttpServletResponse response, final FileStreamingProgressListener progressListener, - final ByteRange full) { - final ByteRange r = full; - response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes " + r.getStart() + "-" + r.getEnd() + "/" + r.getTotal()); - response.setContentLengthLong(r.getLength()); + private static ResponseEntity handleFullFileRequest( + final InputStream inputStream, final String filename, final HttpServletResponse response, + final FileStreamingProgressListener progressListener, final ByteRange full) { + response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes " + full.getStart() + "-" + full.getEnd() + "/" + full.getTotal()); + response.setContentLengthLong(full.getLength()); - try (final InputStream from = artifact.getFileInputStream()) { + try { final ServletOutputStream to = response.getOutputStream(); - copyStreams(from, to, progressListener, r.getStart(), r.getLength(), filename); + copyStreams(inputStream, to, progressListener, full.getStart(), full.getLength(), filename); } catch (final IOException e) { throw new FileStreamingFailedException("fullfileRequest " + filename, e); } @@ -214,28 +213,30 @@ public final class FileStreamingUtil { } } - private static ResponseEntity handleMultipartRangeRequest(final DbArtifact artifact, - final String filename, final HttpServletResponse response, + private static ResponseEntity handleMultipartRangeRequest( + final InputStream inputStream, final String filename, final HttpServletResponse response, final FileStreamingProgressListener progressListener, final List ranges) { - + ranges.sort((r1, r2) -> Long.compare(r1.getStart(), r2.getStart())); response.setContentType("multipart/byteranges; boundary=" + ByteRange.MULTIPART_BOUNDARY); response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); try { final ServletOutputStream to = response.getOutputStream(); - for (final ByteRange r : ranges) { - try (final InputStream from = artifact.getFileInputStream()) { - - // Add multipart boundary and header fields for every range. - to.println(); - to.println("--" + ByteRange.MULTIPART_BOUNDARY); - to.println(HttpHeaders.CONTENT_RANGE + ": bytes " + r.getStart() + "-" + r.getEnd() + "/" - + r.getTotal()); - - // Copy single part range of multi part range. - copyStreams(from, to, progressListener, r.getStart(), r.getLength(), filename); + long streamPos = 0; + for (final ByteRange range : ranges) { + if (streamPos > range.getStart()) { + throw new FileStreamingFailedException("Ranges are overlapping or not in order"); } + + // Add multipart boundary and header fields for every range. + to.println(); + to.println("--" + ByteRange.MULTIPART_BOUNDARY); + to.println(HttpHeaders.CONTENT_RANGE + ": bytes " + range.getStart() + "-" + range.getEnd() + "/" + range.getTotal()); + + // Copy single part range of multipart range. + copyStreams(inputStream, to, progressListener, range.getStart() - streamPos, range.getLength(), filename); + streamPos = range.getStart() + range.getLength(); } // End with final multipart boundary. @@ -248,17 +249,16 @@ public final class FileStreamingUtil { return ResponseEntity.status(HttpStatus.PARTIAL_CONTENT).build(); } - private static ResponseEntity handleStandardRangeRequest(final DbArtifact artifact, - final String filename, final HttpServletResponse response, - final FileStreamingProgressListener progressListener, final List ranges) { - final ByteRange r = ranges.get(0); - response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes " + r.getStart() + "-" + r.getEnd() + "/" + r.getTotal()); - response.setContentLengthLong(r.getLength()); + private static ResponseEntity handleStandardRangeRequest( + final InputStream inputStream, final String filename, final HttpServletResponse response, + final FileStreamingProgressListener progressListener, final ByteRange range) { + response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes " + range.getStart() + "-" + range.getEnd() + "/" + range.getTotal()); + response.setContentLengthLong(range.getLength()); response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); - try (final InputStream from = artifact.getFileInputStream()) { + try { final ServletOutputStream to = response.getOutputStream(); - copyStreams(from, to, progressListener, r.getStart(), r.getLength(), filename); + copyStreams(inputStream, to, progressListener, range.getStart(), range.getLength(), filename); } catch (final IOException e) { log.error("standardRangeRequest of file ({}) failed!", filename, e); throw new FileStreamingFailedException(filename); @@ -267,10 +267,11 @@ public final class FileStreamingUtil { return ResponseEntity.status(HttpStatus.PARTIAL_CONTENT).build(); } - private static long copyStreams(final InputStream from, final OutputStream to, - final FileStreamingProgressListener progressListener, final long start, final long length, + private static long copyStreams( + final InputStream from, final OutputStream to, + final FileStreamingProgressListener progressListener, + final long start, final long length, final String filename) throws IOException { - final long startMillis = System.currentTimeMillis(); log.trace("Start of copy-streams of file {} from {} to {}", filename, start, length); @@ -287,7 +288,7 @@ public final class FileStreamingUtil { long shippedSinceLastEvent = 0; while (toContinue) { - final int r = from.read(buf); + final int r = from.read(buf, 0, Math.min(BUFFER_SIZE, toRead > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) toRead)); if (r == -1) { break; } @@ -319,8 +320,8 @@ public final class FileStreamingUtil { final long totalTime = System.currentTimeMillis() - startMillis; if (total < length) { - throw new FileStreamingFailedException(filename + ": " + (length - total) - + " bytes could not be written to client, total time on write: !" + totalTime + " ms"); + throw new FileStreamingFailedException( + filename + ": " + (length - total) + " bytes could not be written to client, total time on write: !" + totalTime + " ms"); } log.trace("Finished copy-stream of file {} with length {} in {} ms", filename, length, totalTime); @@ -417,6 +418,5 @@ public final class FileStreamingUtil { private long getTotal() { return total; } - } -} +} \ No newline at end of file diff --git a/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/FileStreamingUtilTest.java b/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/FileStreamingUtilTest.java index d862804ea..c0630efe3 100644 --- a/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/FileStreamingUtilTest.java +++ b/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/FileStreamingUtilTest.java @@ -20,13 +20,13 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; +import java.util.function.Supplier; import jakarta.servlet.ServletOutputStream; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import org.eclipse.hawkbit.repository.artifact.model.DbArtifact; -import org.eclipse.hawkbit.repository.artifact.model.DbArtifactHash; +import org.eclipse.hawkbit.artifact.model.ArtifactStream; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; @@ -43,33 +43,8 @@ class FileStreamingUtilTest { private static final String CONTENT = "This is some very long string which is intended to test"; private static final byte[] CONTENT_BYTES = CONTENT.getBytes(StandardCharsets.UTF_8); - private static final DbArtifact TEST_ARTIFACT = new DbArtifact() { - - @Override - public String getArtifactId() { - return "1"; - } - - @Override - public DbArtifactHash getHashes() { - return new DbArtifactHash("sha1-111", "md5-123", "sha256-123"); - } - - @Override - public long getSize() { - return CONTENT_BYTES.length; - } - - @Override - public String getContentType() { - return "text/plain"; - } - - @Override - public InputStream getFileInputStream() { - return new ByteArrayInputStream(CONTENT_BYTES); - } - }; + private static final Supplier TEST_ARTIFACT = + () -> new ArtifactStream(new ByteArrayInputStream(CONTENT_BYTES), CONTENT_BYTES.length, "sha1-111"); @Test void shouldProcessRangeHeaderForMultipartRequests() throws IOException { @@ -78,11 +53,11 @@ class FileStreamingUtilTest { Mockito.when(servletResponse.getOutputStream()).thenReturn(outputStream); final HttpServletRequest servletRequest = Mockito.mock(HttpServletRequest.class); - Mockito.when(servletRequest.getHeader("Range")).thenReturn("bytes=0-10,9-15,16-"); + Mockito.when(servletRequest.getHeader("Range")).thenReturn("bytes=0-10,11-15,16-"); long lastModified = System.currentTimeMillis(); - final ResponseEntity responseEntity = FileStreamingUtil.writeFileResponse(TEST_ARTIFACT, - "test.file", lastModified, servletResponse, servletRequest, null); + final ResponseEntity responseEntity = FileStreamingUtil.writeFileResponse( + TEST_ARTIFACT.get(), "test.file", lastModified, servletResponse, servletRequest, null); assertThat(responseEntity).isNotNull(); verify(servletResponse).setDateHeader(HttpHeaders.LAST_MODIFIED, lastModified); @@ -92,7 +67,7 @@ class FileStreamingUtilTest { verify(outputStream).print(stringCaptor.capture()); assertThat(stringCaptor.getValue()).contains("--THIS_STRING_SEPARATES_MULTIPART--"); verify(outputStream, times(3)).write(any(), anyInt(), lenCaptor.capture()); - assertThat(lenCaptor.getAllValues()).containsExactly(11, 7, 39); // Range lengths + assertThat(lenCaptor.getAllValues()).containsExactly(11, 5, 39); // Range lengths } @Test @@ -105,8 +80,8 @@ class FileStreamingUtilTest { final HttpServletRequest servletRequest = Mockito.mock(HttpServletRequest.class); Mockito.when(servletRequest.getHeader("Range")).thenReturn("bytes=0-10***,9-15,16-"); - final ResponseEntity responseEntity = FileStreamingUtil.writeFileResponse(TEST_ARTIFACT, - "test.file", lastModified, servletResponse, servletRequest, null); + final ResponseEntity responseEntity = FileStreamingUtil.writeFileResponse( + TEST_ARTIFACT.get(), "test.file", lastModified, servletResponse, servletRequest, null); assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE); verify(outputStream, times(0)).print(anyString()); diff --git a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/InMemoryUserAuthoritiesResolver.java b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/InMemoryUserAuthoritiesResolver.java index 540cd897b..eb21431a4 100644 --- a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/InMemoryUserAuthoritiesResolver.java +++ b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/InMemoryUserAuthoritiesResolver.java @@ -17,8 +17,7 @@ import java.util.Map; import org.eclipse.hawkbit.tenancy.UserAuthoritiesResolver; /** - * An implementation of the {@link UserAuthoritiesResolver} that is based on - * in-memory user permissions. + * An implementation of the {@link UserAuthoritiesResolver} that is based on in-memory user permissions. */ public class InMemoryUserAuthoritiesResolver implements UserAuthoritiesResolver { diff --git a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/MdcHandler.java b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/MdcHandler.java index d0b2065f4..2daced2d9 100644 --- a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/MdcHandler.java +++ b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/MdcHandler.java @@ -77,7 +77,7 @@ public class MdcHandler { final String tenant; if (authentication.getDetails() instanceof TenantAwareAuthenticationDetails tenantAwareAuthenticationDetails) { - tenant = tenantAwareAuthenticationDetails.getTenant(); + tenant = tenantAwareAuthenticationDetails.tenant(); } else { tenant = null; } diff --git a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SpringSecurityAuditorAware.java b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SpringSecurityAuditorAware.java index 94d05a824..ce5a07d31 100644 --- a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SpringSecurityAuditorAware.java +++ b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SpringSecurityAuditorAware.java @@ -59,7 +59,7 @@ public class SpringSecurityAuditorAware implements AuditorAware { } protected String getCurrentAuditor(final Authentication authentication) { - if (authentication.getDetails() instanceof TenantAwareAuthenticationDetails tenantAwareDetails && tenantAwareDetails.isController()) { + if (authentication.getDetails() instanceof TenantAwareAuthenticationDetails tenantAwareDetails && tenantAwareDetails.controller()) { return "CONTROLLER_PLUG_AND_PLAY"; } if (authentication.getPrincipal() instanceof UserDetails userDetails) { diff --git a/hawkbit-test-report/pom.xml b/hawkbit-test-report/pom.xml index ad03c9956..59d908dfc 100644 --- a/hawkbit-test-report/pom.xml +++ b/hawkbit-test-report/pom.xml @@ -35,7 +35,7 @@ org.eclipse.hawkbit - hawkbit-artifact-repository-filesystem + hawkbit-artifact-fs ${project.version} diff --git a/site/content/apis/dmf_api.md b/site/content/apis/dmf_api.md index 17d0b8b79..27eb6221c 100644 --- a/site/content/apis/dmf_api.md +++ b/site/content/apis/dmf_api.md @@ -376,8 +376,8 @@ Example header and payload: "HTTPS":"https://download-from-url.com" }, "hashes":{ - "md5":"md5hash", - "sha1":"sha1hash" + "md5":"", + "sha1":"" }, "size":512 }], @@ -508,8 +508,8 @@ Example header and payload: "HTTPS":"https://download-from-url.com" }, "hashes":{ - "md5":"md5hash", - "sha1":"sha1hash" + "md5":"", + "sha1":"" }, "size":512 }], @@ -541,8 +541,8 @@ Example header and payload: "HTTPS":"https://download-from-url.com" }, "hashes":{ - "md5":"md5hash", - "sha1":"sha1hash" + "md5":"", + "sha1":"" }, "size":512 }], diff --git a/site/content/guides/clustering.md b/site/content/guides/clustering.md index 3d9c6f062..11c00446b 100644 --- a/site/content/guides/clustering.md +++ b/site/content/guides/clustering.md @@ -80,7 +80,7 @@ Add to your `pom.xml` : Every node is maintaining its own caches independent from other nodes. So there is no globally shared/synchronized cache instance within the cluster. In order to keep nodes in sync a TTL (time to live) can be set for all caches to ensure that after some time the cache is refreshed from the database. To enable the TTL just set the property " -hawkbit.cache.global.ttl" (value in milliseconds). Of course you can implement a shared cache, e.g. Redis. +hawkbit.cache.ttl" (value in milliseconds). Of course you can implement a shared cache, e.g. Redis. See [CacheAutoConfiguration](https://github.com/eclipse-hawkbit/hawkbit/blob/master/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/CacheAutoConfiguration.java) ## Schedulers