20250828 cleanup (#2639)

* Cleanup

* Refactor artifact management
This commit is contained in:
Avgustin Marinov
2025-09-02 16:08:14 +03:00
committed by GitHub
parent 4f0a8893c7
commit 2a636328a0
305 changed files with 2253 additions and 4566 deletions

View File

@@ -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<InputStream> decryptionFunction;
private final int encryptionOverhead;
public EncryptionAwareDbArtifact(final DbArtifact encryptedDbArtifact,
final UnaryOperator<InputStream> decryptionFunction) {
this.encryptedDbArtifact = encryptedDbArtifact;
this.decryptionFunction = decryptionFunction;
this.encryptionOverhead = 0;
}
public EncryptionAwareDbArtifact(final DbArtifact encryptedDbArtifact,
final UnaryOperator<InputStream> 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());
}
}

View File

@@ -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
*/

View File

@@ -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> artifactRepository,
final Optional<ArtifactStorage> 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);

View File

@@ -146,7 +146,7 @@ public class JpaConfirmationManagement extends JpaActionManagement implements Co
}
@Override
public Optional<AutoConfirmationStatus> getStatus(final String controllerId) {
public Optional<AutoConfirmationStatus> findStatus(final String controllerId) {
return Optional.of(targetRepository.getWithDetailsByControllerId(controllerId, JpaTarget_.GRAPH_TARGET_AUTO_CONFIRMATION_STATUS))
.map(JpaTarget::getAutoConfirmationStatus);
}

View File

@@ -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<? extends TargetType> 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<? extends TargetType> targetTypeManagement,
final TargetRepository targetRepository, final TargetTypeRepository targetTypeRepository,
final DeploymentManagement deploymentManagement, final ConfirmationManagement confirmationManagement,
final SoftwareModuleRepository softwareModuleRepository,
final SoftwareModuleManagement<? extends SoftwareModule> 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<SoftwareModule> 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<Action> 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<Action> 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<Action> getInstalledActionByTarget(final Target target) {
public Optional<Action> 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<DistributionSetAssignmentResult> 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<TargetType> getTargetType(String targetTypeName) {
return systemSecurityContext.runAsSystem(() -> targetTypeManagement.getByName(targetTypeName));
private Optional<TargetType> 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<TargetType> 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<TargetType> targetTypeOptional = getTargetType(type);
final Optional<TargetType> targetTypeOptional = findTargetType(type);
if (targetTypeOptional.isPresent()) {
log.debug("Updating target type for thing ID \"{}\" to \"{}\".", toUpdate.getControllerId(), type);
toUpdate.setTargetType(targetTypeOptional.get());

View File

@@ -464,13 +464,13 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
}
@Override
public Optional<DistributionSet> getAssignedDistributionSet(final String controllerId) {
public Optional<DistributionSet> findAssignedDistributionSet(final String controllerId) {
return targetRepository.findWithDetailsByControllerId(controllerId, JpaTarget_.GRAPH_TARGET_ASSIGNED_DISTRIBUTION_SET)
.map(JpaTarget::getAssignedDistributionSet);
}
@Override
public Optional<DistributionSet> getInstalledDistributionSet(final String controllerId) {
public Optional<DistributionSet> findInstalledDistributionSet(final String controllerId) {
return targetRepository.findWithDetailsByControllerId(controllerId, JpaTarget_.GRAPH_TARGET_INSTALLED_DISTRIBUTION_SET)
.map(JpaTarget::getInstalledDistributionSet);
}

View File

@@ -154,8 +154,9 @@ public class JpaDistributionSetManagement
}
@Override
public Optional<JpaDistributionSet> 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<JpaDistributionSet> 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

View File

@@ -94,11 +94,6 @@ public class JpaDistributionSetTypeManagement
return jpaRepository.findOne(DistributionSetTypeSpecification.byKey(key));
}
@Override
public Optional<JpaDistributionSetType> 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))

View File

@@ -109,8 +109,26 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
}
@Override
public Optional<RolloutGroup> 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<TotalTargetCountActionStatus> 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<RolloutGroup> getWithDetailedStatus(final long rolloutGroupId) {
final Optional<RolloutGroup> rolloutGroup = get(rolloutGroupId);
if (rolloutGroup.isEmpty()) {
return rolloutGroup;
}
final JpaRolloutGroup jpaRolloutGroup = (JpaRolloutGroup) rolloutGroup.get();
List<TotalTargetCountActionStatus> 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);

View File

@@ -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<Rollout> find(final long rolloutId) {
return rolloutRepository.findById(rolloutId).map(Rollout.class::cast);
}
@Override
public Optional<Rollout> getByName(final String rolloutName) {
return rolloutRepository.findByName(rolloutName);
}
@Override
public Optional<Rollout> getWithDetailedStatus(final long rolloutId) {
final Optional<Rollout> 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<TotalTargetCountActionStatus> 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)

View File

@@ -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<JpaSoftwareModule, SoftwareModuleManagement.Create, SoftwareModuleManagement.Update, SoftwareModuleRepository, SoftwareModuleFields, MetadataValue, JpaSoftwareModule.JpaMetadataValue>
public class JpaSoftwareModuleManagement extends
AbstractJpaRepositoryWithMetadataManagement<JpaSoftwareModule, SoftwareModuleManagement.Create, SoftwareModuleManagement.Update, SoftwareModuleRepository, SoftwareModuleFields, MetadataValue, JpaSoftwareModule.JpaMetadataValue>
implements SoftwareModuleManagement<JpaSoftwareModule> {
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<JpaSoftwareModule> softDelete(final Collection<JpaSoftwareModule> toDelete) {
return toDelete.stream()
.filter(swModule -> {
final List<DistributionSet> assignedTo = swModule.getAssignedTo();
if (assignedTo != null) {
final List<DistributionSet> 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<DistributionSet> assignedTo = swModule.getAssignedTo();
if (assignedTo != null) {
final List<DistributionSet> 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<Long, Map<String, String>> findMetaDataBySoftwareModuleIdsAndTargetVisible(final Collection<Long> 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<JpaSoftwareModule> 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<String> 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) {

View File

@@ -47,11 +47,6 @@ public class JpaSoftwareModuleTypeManagement
return jpaRepository.findByKey(key);
}
@Override
public Optional<JpaSoftwareModuleType> findByName(final String name) {
return jpaRepository.findByName(name);
}
@Override
protected Collection<JpaSoftwareModuleType> softDelete(final Collection<JpaSoftwareModuleType> toDelete) {
return toDelete.stream().filter(smt ->

View File

@@ -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;
}

View File

@@ -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<Target> findByControllerId(final String controllerId) {
return jpaRepository.findByControllerId(controllerId).map(Target.class::cast);
}
@Override
public List<Target> findByControllerId(final Collection<String> 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<Target> findByTargetFilterQueryAndNonDSAndCompatibleAndUpdatable(
final long distributionSetId, final String rsql, final Pageable pageable) {
@@ -143,21 +164,6 @@ public class JpaTargetManagement
.map(Target.class::cast);
}
@Override
public List<Target> getByControllerId(final Collection<String> controllerIDs) {
return Collections.unmodifiableList(jpaRepository.findAll(TargetSpecifications.byControllerIdWithAssignedDsInJoin(controllerIDs)));
}
@Override
public Optional<Target> 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<Target> findByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(
final Collection<Long> groups, final String rsql, final DistributionSetType dsType, final Pageable pageable) {

View File

@@ -76,26 +76,21 @@ public class JpaTargetTypeManagement
}
@Override
public Optional<TargetType> getByKey(final String key) {
public Optional<TargetType> findByKey(final String key) {
return jpaRepository.findOne(TargetTypeSpecification.hasKey(key)).map(TargetType.class::cast);
}
@Override
public Optional<TargetType> 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<Long> distributionSetTypeIds) {
final Collection<JpaDistributionSetType> dsTypes = distributionSetTypeRepository
.findAllById(distributionSetTypeIds);
final Collection<JpaDistributionSetType> 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());
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -56,8 +56,7 @@ public class PauseRolloutGroupAction implements RolloutGroupActionEvaluator<Roll
and this one tries to pause the rollout too but throws an exception
and rollbacks rollout processing transaction
*/
final Rollout refreshedRollout = rolloutManagement.find(rollout.getId())
.orElseThrow(() -> 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());

View File

@@ -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<JpaDistributionSetType> 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

View File

@@ -9,8 +9,6 @@
*/
package org.eclipse.hawkbit.repository.jpa.specifications;
import java.util.Collection;
import jakarta.persistence.criteria.SetJoin;
import lombok.AccessLevel;

View File

@@ -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 {