Refactor Management interfaces: find/get pattern (#2609)
Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -16,7 +16,6 @@ import java.util.concurrent.locks.Lock;
|
||||
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.hawkbit.ContextAware;
|
||||
import org.eclipse.hawkbit.repository.RolloutExecutor;
|
||||
import org.eclipse.hawkbit.repository.RolloutHandler;
|
||||
import org.eclipse.hawkbit.repository.RolloutManagement;
|
||||
@@ -108,7 +107,7 @@ public class JpaRolloutHandler implements RolloutHandler {
|
||||
final long startNano = System.nanoTime();
|
||||
|
||||
DeploymentHelper.runInNewTransaction(txManager, handlerId + "-" + rolloutId, status -> {
|
||||
rolloutManagement.get(rolloutId).ifPresentOrElse(
|
||||
rolloutManagement.find(rolloutId).ifPresentOrElse(
|
||||
rolloutExecutor::execute,
|
||||
() -> log.error("Could not retrieve rollout with id {}. Will not continue with execution.", rolloutId));
|
||||
return 0L;
|
||||
|
||||
@@ -15,12 +15,16 @@ import static org.eclipse.hawkbit.repository.jpa.configuration.Constants.TX_RT_M
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
@@ -31,11 +35,13 @@ import jakarta.persistence.criteria.CriteriaUpdate;
|
||||
import jakarta.persistence.criteria.Root;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||
import org.eclipse.hawkbit.repository.Identifiable;
|
||||
import org.eclipse.hawkbit.repository.RepositoryManagement;
|
||||
import org.eclipse.hawkbit.repository.RsqlQueryField;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.jpa.Jpa;
|
||||
import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper;
|
||||
import org.eclipse.hawkbit.repository.jpa.JpaRepositoryConfiguration;
|
||||
@@ -48,7 +54,6 @@ import org.eclipse.hawkbit.utils.ObjectCopyUtil;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
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.retry.annotation.Backoff;
|
||||
import org.springframework.retry.annotation.Retryable;
|
||||
@@ -73,6 +78,7 @@ import org.springframework.validation.annotation.Validated;
|
||||
@HandleAuthorizationDenied(handlerClass = JpaRepositoryConfiguration.ManagementExceptionThrowingMethodAuthorizationDeniedHandler.class)
|
||||
@Transactional(readOnly = true)
|
||||
@Validated
|
||||
@Slf4j
|
||||
abstract class AbstractJpaRepositoryManagement<T extends AbstractJpaBaseEntity, C, U extends Identifiable<Long>, R extends BaseEntityRepository<T>, A extends Enum<A> & RsqlQueryField>
|
||||
implements RepositoryManagement<T, C, U> {
|
||||
|
||||
@@ -81,6 +87,7 @@ abstract class AbstractJpaRepositoryManagement<T extends AbstractJpaBaseEntity,
|
||||
protected final R jpaRepository;
|
||||
protected final EntityManager entityManager;
|
||||
private final Supplier<T> jpaEntityCreator;
|
||||
private final Function<T, Boolean> isValid;
|
||||
|
||||
protected AbstractJpaRepositoryManagement(final R jpaRepository, final EntityManager entityManager) {
|
||||
this.jpaRepository = jpaRepository;
|
||||
@@ -100,6 +107,25 @@ abstract class AbstractJpaRepositoryManagement<T extends AbstractJpaBaseEntity,
|
||||
throw new IllegalStateException("Must NEVER happen!", e);
|
||||
}
|
||||
};
|
||||
Method isValidMethod = null;
|
||||
try {
|
||||
isValidMethod = jpaRepository.getDomainClass().getMethod("isValid");
|
||||
} catch (final NoSuchMethodException e) {
|
||||
// if there is no isValid method, then it is always valid
|
||||
}
|
||||
final Method isValidMethodF = isValidMethod;
|
||||
isValid = jpaEntity -> {
|
||||
if (isValidMethodF == null) {
|
||||
return true; // if there is no isValid method, then it is always valid
|
||||
} else {
|
||||
try {
|
||||
return (Boolean) isValidMethodF.invoke(jpaEntity);
|
||||
} catch (final IllegalAccessException | InvocationTargetException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return false; // if it fails, then it is not valid
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -117,13 +143,23 @@ abstract class AbstractJpaRepositoryManagement<T extends AbstractJpaBaseEntity,
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<T> get(final long id) {
|
||||
public T get(final long id) {
|
||||
return jpaRepository.getById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<T> find(final long id) {
|
||||
return jpaRepository.findById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<T> get(final Collection<Long> ids) {
|
||||
return findAllById(ids);
|
||||
return findAllById(ids, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<T> find(final Collection<Long> ids) {
|
||||
return findAllById(ids, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -157,13 +193,8 @@ abstract class AbstractJpaRepositoryManagement<T extends AbstractJpaBaseEntity,
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY))
|
||||
@SuppressWarnings("java:S1066") // javaS1066 - better readable that way
|
||||
public T update(final U update) {
|
||||
final T entity = jpaRepository
|
||||
.findById(update.getId())
|
||||
.orElseThrow(() -> new EntityNotFoundException(managementClass(), update.getId()));
|
||||
return update(update, entity);
|
||||
}
|
||||
|
||||
protected T update(final Identifiable<Long> update, final T entity) {
|
||||
final T entity = getValid(update.getId());
|
||||
checkUpdate(update, entity);
|
||||
// update getId has no setter in target JPA entity but shall have getter and the value shall be the same
|
||||
// otherwise the Utils will throw an exception that there is no counterpart setter for getId
|
||||
if (ObjectCopyUtil.copy(update, entity, false, this::attach)) {
|
||||
@@ -173,6 +204,43 @@ abstract class AbstractJpaRepositoryManagement<T extends AbstractJpaBaseEntity,
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY))
|
||||
@SuppressWarnings("java:S1066") // javaS1066 - better readable that way
|
||||
public Map<Long, T> update(final Collection<U> update) {
|
||||
final Map<Long, T> toUpdate = findAllById(update.stream().map(Identifiable::getId).toList(), true)
|
||||
.stream()
|
||||
.filter(entity -> {
|
||||
if (Boolean.FALSE.equals(isValid.apply(entity))) {
|
||||
throw new InvalidDistributionSetException(
|
||||
jpaRepository.getManagementClass().getSimpleName() + " " + entity.getId() + " is invalid");
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.collect(Collectors.toMap(Identifiable::getId, Function.identity()));
|
||||
final List<T> toSave = new ArrayList<>(toUpdate.values());
|
||||
for (final U u : update) {
|
||||
final T entity = toUpdate.get(u.getId());
|
||||
checkUpdate(u, entity);
|
||||
// update getId has no setter in target JPA entity but shall have getter and the value shall be the same
|
||||
// otherwise the Utils will throw an exception that there is no counterpart setter for getId
|
||||
if (ObjectCopyUtil.copy(u, entity, false, this::attach)) {
|
||||
toSave.add(entity);
|
||||
}
|
||||
}
|
||||
if (toSave.isEmpty()) {
|
||||
return toUpdate;
|
||||
} else {
|
||||
final List<T> savedEntities = jpaRepository.saveAll(toSave);
|
||||
final Map<Long, T> result = new HashMap<>(toUpdate);
|
||||
for (final T savedEntity : savedEntities) {
|
||||
result.put(savedEntity.getId(), savedEntity);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY))
|
||||
@@ -194,18 +262,28 @@ abstract class AbstractJpaRepositoryManagement<T extends AbstractJpaBaseEntity,
|
||||
.orElseGet(() -> List.of(RsqlUtility.getInstance().buildRsqlSpecification(rsql, fieldsClass())));
|
||||
}
|
||||
|
||||
protected void checkUpdate(final U update, final T distributionSet) {}
|
||||
|
||||
// return which are for soft deletion
|
||||
@SuppressWarnings("java:S1172") // java:S1172 - it is intended to be used by subclasses
|
||||
protected Collection<T> softDelete(final Collection<T> toDelete) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
protected T getValid(final Long id) {
|
||||
final T jpaEntity = jpaRepository.getById(id);
|
||||
if (Boolean.FALSE.equals(isValid.apply(jpaEntity))) {
|
||||
throw new InvalidDistributionSetException(jpaRepository.getManagementClass().getSimpleName() + " " + id + " is invalid");
|
||||
}
|
||||
return jpaEntity;
|
||||
}
|
||||
|
||||
protected void delete0(final Collection<Long> ids) {
|
||||
if (ObjectUtils.isEmpty(ids)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final List<T> toDelete = findAllById(ids); // throws EntityNotFoundException if any of these does not exist
|
||||
final List<T> toDelete = findAllById(ids, true); // throws EntityNotFoundException if any of these does not exist
|
||||
jpaRepository.getAccessController().ifPresent(ac -> {
|
||||
for (final T entity : toDelete) {
|
||||
ac.assertOperationAllowed(AccessController.Operation.DELETE, entity);
|
||||
@@ -240,9 +318,9 @@ abstract class AbstractJpaRepositoryManagement<T extends AbstractJpaBaseEntity,
|
||||
}
|
||||
}
|
||||
|
||||
private List<T> findAllById(final Collection<Long> ids) {
|
||||
private List<T> findAllById(final Collection<Long> ids, final boolean throwIfNotFound) {
|
||||
final List<T> foundDs = jpaRepository.findAllById(ids);
|
||||
if (foundDs.size() != ids.size()) {
|
||||
if (throwIfNotFound && foundDs.size() != ids.size()) {
|
||||
throw new EntityNotFoundException(managementClass(), ids, foundDs.stream().map(T::getId).toList());
|
||||
}
|
||||
return foundDs;
|
||||
|
||||
@@ -121,14 +121,8 @@ abstract class AbstractJpaRepositoryWithMetadataManagement<T extends AbstractJpa
|
||||
|
||||
@Override
|
||||
public Map<String, MV> getMetadata(final Long id) {
|
||||
return jpaRepository
|
||||
.findById(id)
|
||||
.map(T::getMetadata)
|
||||
.map(metadata -> metadata.entrySet().stream()
|
||||
.collect(Collectors.toMap(
|
||||
Map.Entry::getKey,
|
||||
e -> (MV) e.getValue())))
|
||||
.orElseThrow(() -> new EntityNotFoundException(jpaRepository.getManagementClass(), id));
|
||||
final T entity = jpaRepository.getById(id);
|
||||
return entity.getMetadata().entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -146,16 +140,6 @@ abstract class AbstractJpaRepositoryWithMetadataManagement<T extends AbstractJpa
|
||||
|
||||
protected abstract void assertMetadataQuota(final long requested);
|
||||
|
||||
private T getValid(final Long id) {
|
||||
final T jpaEntity = jpaRepository
|
||||
.findById(id)
|
||||
.orElseThrow(() -> new EntityNotFoundException(jpaRepository.getManagementClass(), id));
|
||||
if (!jpaEntity.isValid()) {
|
||||
throw new InvalidDistributionSetException(jpaRepository.getManagementClass().getSimpleName() + " " + id + " is invalid");
|
||||
}
|
||||
return jpaEntity;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private boolean setMetadataValue(final String key, final MV newValue, final MVI existingValue, final Map<String, MVI> metadataValueMap) {
|
||||
if (useCopy) {
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.util.stream.Stream;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.hawkbit.repository.QuotaManagement;
|
||||
import org.eclipse.hawkbit.repository.RepositoryProperties;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus;
|
||||
@@ -80,7 +79,7 @@ public class JpaActionManagement {
|
||||
|
||||
protected Action addActionStatus(final ActionStatusCreate create) {
|
||||
final Long actionId = create.getActionId();
|
||||
final JpaAction action = getActionAndThrowExceptionIfNotFound(actionId);
|
||||
final JpaAction action = actionRepository.getById(actionId);
|
||||
|
||||
if (isUpdatingActionStatusAllowed(action, create)) {
|
||||
return handleAddUpdateActionStatus(create, action);
|
||||
@@ -92,10 +91,6 @@ public class JpaActionManagement {
|
||||
return action;
|
||||
}
|
||||
|
||||
protected JpaAction getActionAndThrowExceptionIfNotFound(final Long actionId) {
|
||||
return actionRepository.findById(actionId).orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
|
||||
}
|
||||
|
||||
protected void onActionStatusUpdate(final JpaActionStatus newActionStatus, final JpaAction action) {
|
||||
// can be overwritten to intercept the persistence of the action status
|
||||
}
|
||||
|
||||
@@ -13,24 +13,22 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Optional;
|
||||
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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.artifact.encryption.ArtifactEncryptionService;
|
||||
import org.eclipse.hawkbit.repository.ArtifactManagement;
|
||||
import org.eclipse.hawkbit.repository.QuotaManagement;
|
||||
import org.eclipse.hawkbit.repository.exception.ArtifactDeleteFailedException;
|
||||
import org.eclipse.hawkbit.repository.exception.ArtifactUploadFailedException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
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;
|
||||
@@ -53,8 +51,6 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.retry.annotation.Backoff;
|
||||
import org.springframework.retry.annotation.Retryable;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -72,49 +68,49 @@ import org.springframework.validation.annotation.Validated;
|
||||
@ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "artifact-management" }, matchIfMissing = true)
|
||||
public class JpaArtifactManagement implements ArtifactManagement {
|
||||
|
||||
private final LocalArtifactRepository localArtifactRepository;
|
||||
private final ArtifactRepository artifactRepository;
|
||||
private final SoftwareModuleRepository softwareModuleRepository;
|
||||
private final EntityManager entityManager;
|
||||
private final PlatformTransactionManager txManager;
|
||||
private final LocalArtifactRepository localArtifactRepository;
|
||||
private final SoftwareModuleRepository softwareModuleRepository;
|
||||
@Nullable
|
||||
private final ArtifactRepository artifactRepository;
|
||||
private final TenantAware tenantAware;
|
||||
private final QuotaManagement quotaManagement;
|
||||
|
||||
protected JpaArtifactManagement(
|
||||
final LocalArtifactRepository localArtifactRepository,
|
||||
final Optional<ArtifactRepository> artifactRepository,
|
||||
final SoftwareModuleRepository softwareModuleRepository,
|
||||
final EntityManager entityManager,
|
||||
final PlatformTransactionManager txManager,
|
||||
final LocalArtifactRepository localArtifactRepository,
|
||||
final SoftwareModuleRepository softwareModuleRepository, @Nullable final ArtifactRepository artifactRepository,
|
||||
final QuotaManagement quotaManagement,
|
||||
final TenantAware tenantAware) {
|
||||
this.localArtifactRepository = localArtifactRepository;
|
||||
this.artifactRepository = artifactRepository.orElse(null);
|
||||
this.softwareModuleRepository = softwareModuleRepository;
|
||||
this.entityManager = entityManager;
|
||||
this.txManager = txManager;
|
||||
this.localArtifactRepository = localArtifactRepository;
|
||||
this.softwareModuleRepository = softwareModuleRepository;
|
||||
this.artifactRepository = artifactRepository;
|
||||
this.quotaManagement = quotaManagement;
|
||||
this.tenantAware = tenantAware;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count() {
|
||||
return localArtifactRepository.count();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public Artifact create(final ArtifactUpload artifactUpload) {
|
||||
assertArtifactRepositoryAvailable();
|
||||
if (artifactRepository == null) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
final long moduleId = artifactUpload.getModuleId();
|
||||
assertArtifactQuota(moduleId, 1);
|
||||
final JpaSoftwareModule softwareModule =
|
||||
softwareModuleRepository
|
||||
.findById(moduleId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, moduleId));
|
||||
QuotaHelper.assertAssignmentQuota(
|
||||
moduleId, 1, quotaManagement.getMaxArtifactsPerSoftwareModule(),
|
||||
Artifact.class, SoftwareModule.class,
|
||||
// get all artifacts without user context
|
||||
softwareModuleId -> localArtifactRepository
|
||||
.count(null, ArtifactSpecifications.bySoftwareModuleId(softwareModuleId)));
|
||||
|
||||
final JpaSoftwareModule softwareModule = softwareModuleRepository.getById(moduleId);
|
||||
|
||||
final String filename = artifactUpload.getFilename();
|
||||
final Artifact existing = softwareModule.getArtifactByFilename(filename).orElse(null);
|
||||
@@ -139,12 +135,34 @@ public class JpaArtifactManagement implements ArtifactManagement {
|
||||
}
|
||||
}
|
||||
|
||||
@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) {
|
||||
if (artifactRepository == null) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
final String tenant = tenantAware.getCurrentTenant();
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
throw new ArtifactBinaryNotFoundException(sha1Hash);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public void delete(final long id) {
|
||||
final JpaArtifact toDelete = (JpaArtifact) get(id).orElseThrow(() -> new EntityNotFoundException(Artifact.class, id));
|
||||
if (artifactRepository == null) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
final JpaArtifact toDelete = localArtifactRepository.getById(id);
|
||||
|
||||
final JpaSoftwareModule softwareModule = toDelete.getSoftwareModule();
|
||||
// clearArtifactBinary checks (unconditionally) software module UPDATE access
|
||||
@@ -159,66 +177,6 @@ public class JpaArtifactManagement implements ArtifactManagement {
|
||||
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(() -> clearArtifactBinary(sha1Hash));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Artifact> get(final long id) {
|
||||
return localArtifactRepository.findById(id).map(Artifact.class::cast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Artifact> getByFilenameAndSoftwareModule(final String filename, final long softwareModuleId) {
|
||||
assertSoftwareModuleExists(softwareModuleId);
|
||||
|
||||
return localArtifactRepository.findFirstByFilenameAndSoftwareModuleId(filename, softwareModuleId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Artifact> findFirstBySHA1(final String sha1Hash) {
|
||||
return localArtifactRepository.findFirstBySha1Hash(sha1Hash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Artifact> getByFilename(final String filename) {
|
||||
return localArtifactRepository.findFirstByFilename(filename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Artifact> findBySoftwareModule(final long softwareModuleId, final Pageable pageable) {
|
||||
assertSoftwareModuleExists(softwareModuleId);
|
||||
|
||||
return localArtifactRepository
|
||||
.findAll(ArtifactSpecifications.bySoftwareModuleId(softwareModuleId), pageable)
|
||||
.map(Artifact.class::cast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countBySoftwareModule(final long softwareModuleId) {
|
||||
assertSoftwareModuleExists(softwareModuleId);
|
||||
|
||||
return localArtifactRepository.count(ArtifactSpecifications.bySoftwareModuleId(softwareModuleId));
|
||||
}
|
||||
|
||||
@SuppressWarnings("java:S2201") // java:S2201 - the idea is to just check if the artifact exists
|
||||
@Override
|
||||
public Optional<DbArtifact> loadArtifactBinary(final String sha1Hash, final long softwareModuleId, final boolean isEncrypted) {
|
||||
assertArtifactRepositoryAvailable();
|
||||
|
||||
assertSoftwareModuleExists(softwareModuleId);
|
||||
|
||||
final String tenant = tenantAware.getCurrentTenant();
|
||||
if (artifactRepository.existsByTenantAndSha1(tenant, sha1Hash)) {
|
||||
// assert artifact exists and belongs to the software module
|
||||
findFirstBySHA1(sha1Hash)
|
||||
// if not found no assertOperationAllowed shall fail
|
||||
.orElseThrow(InsufficientPermissionException::new);
|
||||
|
||||
final DbArtifact dbArtifact = artifactRepository.getArtifactBySha1(tenant, sha1Hash);
|
||||
return Optional.ofNullable(
|
||||
isEncrypted ? wrapInEncryptionAwareDbArtifact(softwareModuleId, dbArtifact) : dbArtifact);
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Garbage collects artifact binaries if only referenced by given {@link SoftwareModule#getId()} or {@link SoftwareModule}'s that are
|
||||
* marked as deleted.
|
||||
@@ -231,11 +189,10 @@ public class JpaArtifactManagement implements ArtifactManagement {
|
||||
* @param sha1Hash no longer needed
|
||||
*/
|
||||
void clearArtifactBinary(final String sha1Hash) {
|
||||
assertArtifactRepositoryAvailable();
|
||||
|
||||
DeploymentHelper.runInNewTransaction(txManager, "clearArtifactBinary", status -> {
|
||||
// countBySha1HashAndTenantAndSoftwareModuleDeletedIsFalse will skip ACM checks and will return total count as it should be
|
||||
if (localArtifactRepository.countBySha1HashAndTenantAndSoftwareModuleDeletedIsFalse(sha1Hash, tenantAware.getCurrentTenant()) <= 0) { // 1 artifact is the one being deleted!
|
||||
if (localArtifactRepository.countBySha1HashAndTenantAndSoftwareModuleDeletedIsFalse(sha1Hash,
|
||||
tenantAware.getCurrentTenant()) <= 0) { // 1 artifact is the one being deleted!
|
||||
// removes the real artifact ONLY AFTER the delete of artifact or software module
|
||||
// in local history has passed successfully (caller has permission and no errors)
|
||||
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(() -> {
|
||||
@@ -252,19 +209,17 @@ public class JpaArtifactManagement implements ArtifactManagement {
|
||||
}
|
||||
|
||||
private AbstractDbArtifact storeArtifact(final ArtifactUpload artifactUpload, final boolean isSmEncrypted) {
|
||||
final String tenant = tenantAware.getCurrentTenant();
|
||||
final long smId = artifactUpload.getModuleId();
|
||||
final InputStream stream = artifactUpload.getInputStream();
|
||||
final String fileName = artifactUpload.getFilename();
|
||||
final String contentType = artifactUpload.getContentType();
|
||||
final String providedSha1 = artifactUpload.getProvidedSha1Sum();
|
||||
final String providedMd5 = artifactUpload.getProvidedMd5Sum();
|
||||
final String providedSha256 = artifactUpload.getProvidedSha256Sum();
|
||||
|
||||
try (final InputStream wrappedStream = wrapInQuotaStream(
|
||||
isSmEncrypted ? wrapInEncryptionStream(smId, stream) : stream)) {
|
||||
return artifactRepository.store(tenant, wrappedStream, fileName, contentType,
|
||||
new DbArtifactHash(providedSha1, providedMd5, providedSha256));
|
||||
isSmEncrypted
|
||||
? wrapInEncryptionStream(artifactUpload.getModuleId(), stream)
|
||||
: stream)) {
|
||||
return artifactRepository.store(
|
||||
tenantAware.getCurrentTenant(), wrappedStream, artifactUpload.getFilename(), artifactUpload.getContentType(),
|
||||
new DbArtifactHash(
|
||||
artifactUpload.getProvidedSha1Sum(),
|
||||
artifactUpload.getProvidedMd5Sum(),
|
||||
artifactUpload.getProvidedSha256Sum()));
|
||||
} catch (final ArtifactStoreException | IOException e) {
|
||||
throw new ArtifactUploadFailedException(e);
|
||||
} catch (final HashNotMatchException e) {
|
||||
@@ -282,15 +237,6 @@ public class JpaArtifactManagement implements ArtifactManagement {
|
||||
return ArtifactEncryptionService.getInstance().encryptArtifact(smId, stream);
|
||||
}
|
||||
|
||||
private void assertArtifactQuota(final long moduleId, final int requested) {
|
||||
QuotaHelper.assertAssignmentQuota(
|
||||
moduleId, requested, quotaManagement.getMaxArtifactsPerSoftwareModule(),
|
||||
Artifact.class, SoftwareModule.class,
|
||||
// get all artifacts without user context
|
||||
softwareModuleId -> localArtifactRepository
|
||||
.count(null, ArtifactSpecifications.bySoftwareModuleId(softwareModuleId)));
|
||||
}
|
||||
|
||||
private InputStream wrapInQuotaStream(final InputStream in) {
|
||||
final long maxArtifactSize = quotaManagement.getMaxArtifactSize();
|
||||
|
||||
@@ -311,8 +257,9 @@ public class JpaArtifactManagement implements ArtifactManagement {
|
||||
encryptionService.encryptionSizeOverhead());
|
||||
}
|
||||
|
||||
private Artifact storeArtifactMetadata(final SoftwareModule softwareModule, final String providedFilename,
|
||||
final AbstractDbArtifact result, final Artifact existing) {
|
||||
private Artifact storeArtifactMetadata(
|
||||
final SoftwareModule softwareModule, final String providedFilename, final AbstractDbArtifact result,
|
||||
final Artifact existing) {
|
||||
final JpaArtifact artifact;
|
||||
if (existing == null) {
|
||||
artifact = new JpaArtifact(result.getHashes().getSha1(), providedFilename, softwareModule);
|
||||
@@ -327,16 +274,4 @@ public class JpaArtifactManagement implements ArtifactManagement {
|
||||
log.debug("storing new artifact into repository {}", artifact);
|
||||
return localArtifactRepository.save(AccessController.Operation.CREATE, artifact);
|
||||
}
|
||||
|
||||
private void assertSoftwareModuleExists(final long softwareModuleId) {
|
||||
if (!softwareModuleRepository.existsById(softwareModuleId)) {
|
||||
throw new EntityNotFoundException(SoftwareModule.class, softwareModuleId);
|
||||
}
|
||||
}
|
||||
|
||||
private void assertArtifactRepositoryAvailable() {
|
||||
if (artifactRepository == null) {
|
||||
throw new UnsupportedOperationException("ArtifactRepository is unavailable");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,7 +108,7 @@ public class JpaConfirmationManagement extends JpaActionManagement implements Co
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public Action confirmAction(final long actionId, final Integer code, final Collection<String> deviceMessages) {
|
||||
log.trace("Action with id {} confirm request is triggered.", actionId);
|
||||
final Action action = getActionAndThrowExceptionIfNotFound(actionId);
|
||||
final Action action = actionRepository.getById(actionId);
|
||||
assertActionCanAcceptFeedback(action);
|
||||
final List<String> messages = new ArrayList<>();
|
||||
if (deviceMessages != null) {
|
||||
@@ -124,7 +124,7 @@ public class JpaConfirmationManagement extends JpaActionManagement implements Co
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public Action denyAction(final long actionId, final Integer code, final Collection<String> deviceMessages) {
|
||||
log.trace("Action with id {} deny request is triggered.", actionId);
|
||||
final Action action = getActionAndThrowExceptionIfNotFound(actionId);
|
||||
final Action action = actionRepository.getById(actionId);
|
||||
assertActionCanAcceptFeedback(action);
|
||||
final List<String> messages = new ArrayList<>();
|
||||
if (deviceMessages != null) {
|
||||
|
||||
@@ -223,7 +223,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont
|
||||
}
|
||||
case DOWNLOADED: {
|
||||
handleDownloadedActionStatus(action).ifPresent(controllerId ->
|
||||
requestControllerAttributes(getByControllerId(controllerId)
|
||||
requestControllerAttributes(findByControllerId(controllerId)
|
||||
.map(JpaTarget.class::cast)
|
||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId))));
|
||||
break;
|
||||
@@ -239,7 +239,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public Action addCancelActionStatus(final ActionStatusCreate create) {
|
||||
final JpaAction action = getActionAndThrowExceptionIfNotFound(create.getActionId());
|
||||
final JpaAction action = actionRepository.getById(create.getActionId());
|
||||
if (!action.isCancelingOrCanceled()) {
|
||||
throw new CancelActionNotAllowedException("The action is not in canceling state.");
|
||||
}
|
||||
@@ -284,7 +284,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public ActionStatus addInformationalActionStatus(final ActionStatusCreate create) {
|
||||
final JpaAction action = getActionAndThrowExceptionIfNotFound(create.getActionId());
|
||||
final JpaAction action = actionRepository.getById(create.getActionId());
|
||||
assertActionStatusQuota(create, action);
|
||||
|
||||
final JpaActionStatus actionStatus = buildJpaActionStatus(create);
|
||||
@@ -476,13 +476,13 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Target> getByControllerId(final String controllerId) {
|
||||
return targetRepository.findByControllerId(controllerId).map(Target.class::cast);
|
||||
public Optional<Target> find(final long targetId) {
|
||||
return targetRepository.findById(targetId).map(Target.class::cast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Target> get(final long targetId) {
|
||||
return targetRepository.findById(targetId).map(Target.class::cast);
|
||||
public Optional<Target> findByControllerId(final String controllerId) {
|
||||
return targetRepository.findByControllerId(controllerId).map(Target.class::cast);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -538,10 +538,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont
|
||||
targetRepository.getAccessController().ifPresent(
|
||||
accessController -> accessController.assertOperationAllowed(
|
||||
AccessController.Operation.UPDATE,
|
||||
actionRepository
|
||||
.findById(actionId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(Action.class, actionId))
|
||||
.getTarget()));
|
||||
actionRepository.getById(actionId).getTarget()));
|
||||
actionRepository.updateExternalRef(actionId, externalRef);
|
||||
}
|
||||
|
||||
@@ -579,13 +576,14 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont
|
||||
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()))))
|
||||
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))));
|
||||
|
||||
return distributionSetAssignmentResults.stream().findFirst()
|
||||
return distributionSetAssignmentResults.stream()
|
||||
.findFirst()
|
||||
.map(result -> result.getAlreadyAssigned() == 0)
|
||||
.orElseThrow();
|
||||
}
|
||||
@@ -901,7 +899,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont
|
||||
* {@link Status#RETRIEVED}
|
||||
*/
|
||||
private Action handleRegisterRetrieved(final Long actionId, final String message) {
|
||||
final JpaAction action = getActionAndThrowExceptionIfNotFound(actionId);
|
||||
final JpaAction action = actionRepository.getById(actionId);
|
||||
// do a manual query with CriteriaBuilder to avoid unnecessary field queries and an extra
|
||||
// count query made by spring-data when using pageable requests, we don't need an extra count
|
||||
// query, we just want to check if the last action status is a retrieved or not.
|
||||
|
||||
@@ -222,7 +222,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
private Action cancelAction0(final long actionId) {
|
||||
log.debug("cancelAction({})", actionId);
|
||||
|
||||
final JpaAction action = actionRepository.findById(actionId).orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
|
||||
final JpaAction action = actionRepository.getById(actionId);
|
||||
|
||||
if (action.isCancelingOrCanceled()) {
|
||||
throw new CancelActionNotAllowedException("Actions in canceling or canceled state cannot be canceled");
|
||||
@@ -378,7 +378,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
}
|
||||
|
||||
private Action forceQuitAction0(final long actionId) {
|
||||
final JpaAction action = actionRepository.findById(actionId).orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
|
||||
final JpaAction action = actionRepository.getById(actionId);
|
||||
|
||||
if (!action.isCancelingOrCanceled()) {
|
||||
throw new ForceQuitActionNotAllowedException(action.getId() + " is not canceled yet and cannot be force quit");
|
||||
@@ -406,7 +406,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
@Retryable(retryFor = {
|
||||
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public Action forceTargetAction(final long actionId) {
|
||||
final JpaAction action = actionRepository.findById(actionId).map(this::assertTargetUpdateAllowed)
|
||||
final JpaAction action = actionRepository.findById(actionId)
|
||||
.map(this::assertTargetUpdateAllowed)
|
||||
.orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
|
||||
|
||||
if (!action.isForcedOrTimeForced()) {
|
||||
@@ -997,9 +998,4 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
throw new EntityNotFoundException(Action.class, actionId);
|
||||
}
|
||||
}
|
||||
|
||||
private Page<JpaAction> findActiveActionsForRollout(long rolloutId, Pageable pageable) {
|
||||
return actionRepository
|
||||
.findAll(ActionSpecifications.byRolloutIdAndActive(rolloutId), pageable);
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.management;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
@@ -22,13 +21,10 @@ import org.eclipse.hawkbit.repository.RolloutManagement;
|
||||
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
|
||||
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.StopRolloutException;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.utils.DeploymentHelper;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.ActionCancellationType;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidationCount;
|
||||
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
@@ -115,7 +111,7 @@ public class JpaDistributionSetInvalidationManagement implements DistributionSet
|
||||
}
|
||||
|
||||
private void invalidateDistributionSet(final long setId, final ActionCancellationType cancelationType) {
|
||||
final DistributionSet distributionSet = distributionSetManagement.getOrElseThrowException(setId);
|
||||
final DistributionSet distributionSet = distributionSetManagement.get(setId);
|
||||
if (!distributionSet.isComplete()) {
|
||||
throw new IncompleteDistributionSetException(
|
||||
"Distribution set of type " + distributionSet.getType().getKey() + " is incomplete: " + distributionSet.getId());
|
||||
|
||||
@@ -105,28 +105,32 @@ public class JpaDistributionSetManagement
|
||||
this.repositoryProperties = repositoryProperties;
|
||||
}
|
||||
|
||||
@SuppressWarnings("java:S1066") // java:S1066 better readable without merging the if statements
|
||||
@Override
|
||||
public JpaDistributionSet update(final Update update) {
|
||||
final JpaDistributionSet distributionSet = getValid0(update.getId());
|
||||
|
||||
// lock/unlock ONLY if locked flag is present!
|
||||
final JpaDistributionSet updated = super.update(update);
|
||||
if (Boolean.TRUE.equals(update.getLocked())) {
|
||||
if (!distributionSet.isLocked()) {
|
||||
lockSoftwareModules(distributionSet);
|
||||
distributionSet.setLocked(true);
|
||||
}
|
||||
} else if (Boolean.FALSE.equals(update.getLocked())) {
|
||||
if (distributionSet.isLocked()) {
|
||||
distributionSet.setLocked(false);
|
||||
lockSoftwareModules(updated);
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Long, JpaDistributionSet> update(final Collection<Update> updates) {
|
||||
final Map<Long, JpaDistributionSet> updated = super.update(updates);
|
||||
for (final Update update : updates) {
|
||||
final JpaDistributionSet updatedSet = updated.get(update.getId());
|
||||
if (Boolean.TRUE.equals(update.getLocked())) {
|
||||
lockSoftwareModules(updatedSet);
|
||||
}
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkUpdate(final Update update, final JpaDistributionSet distributionSet) {
|
||||
if (update.getRequiredMigrationStep() != null && !update.getRequiredMigrationStep().equals(distributionSet.isRequiredMigrationStep())) {
|
||||
assertDistributionSetIsNotAssignedToTargets(update.getId());
|
||||
}
|
||||
|
||||
return super.update(update, distributionSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -154,11 +158,6 @@ public class JpaDistributionSetManagement
|
||||
return jpaRepository.findOne(jpaRepository.byIdSpec(id), JpaDistributionSet_.GRAPH_DISTRIBUTION_SET_DETAIL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JpaDistributionSet getOrElseThrowException(final long id) {
|
||||
return getById(id);
|
||||
}
|
||||
|
||||
// implicitly lock a distribution set if not already locked and implicit lock is enabled and not to skip
|
||||
@Override
|
||||
@Transactional
|
||||
@@ -256,7 +255,7 @@ public class JpaDistributionSetManagement
|
||||
final JpaDistributionSet set = getValid0(id);
|
||||
assertDistributionSetIsNotAssignedToTargets(id);
|
||||
|
||||
final JpaSoftwareModule module = findSoftwareModuleAndThrowExceptionIfNotFound(moduleId);
|
||||
final JpaSoftwareModule module = softwareModuleRepository.getById(moduleId);
|
||||
set.removeModule(module);
|
||||
|
||||
return jpaRepository.save(set);
|
||||
@@ -364,7 +363,7 @@ public class JpaDistributionSetManagement
|
||||
}
|
||||
|
||||
private JpaDistributionSet getValid0(final long id) {
|
||||
final JpaDistributionSet distributionSet = getById(id);
|
||||
final JpaDistributionSet distributionSet = jpaRepository.getById(id);
|
||||
if (!distributionSet.isValid()) {
|
||||
throw new InvalidDistributionSetException(
|
||||
"Distribution set of type " + distributionSet.getType().getKey() + " is invalid: " + distributionSet.getId());
|
||||
@@ -375,8 +374,7 @@ public class JpaDistributionSetManagement
|
||||
private List<JpaDistributionSet> updateTag(
|
||||
final Collection<Long> dsIds, final long dsTagId,
|
||||
final BiFunction<DistributionSetTag, JpaDistributionSet, JpaDistributionSet> updater) {
|
||||
final DistributionSetTag tag = distributionSetTagManagement.get(dsTagId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSetTag.class, dsTagId));
|
||||
final DistributionSetTag tag = distributionSetTagManagement.get(dsTagId);
|
||||
final List<JpaDistributionSet> allDs = dsIds.size() == 1 ?
|
||||
jpaRepository.findById(dsIds.iterator().next())
|
||||
.map(List::of)
|
||||
@@ -395,11 +393,6 @@ public class JpaDistributionSetManagement
|
||||
}
|
||||
}
|
||||
|
||||
private JpaSoftwareModule findSoftwareModuleAndThrowExceptionIfNotFound(final Long softwareModuleId) {
|
||||
return softwareModuleRepository.findById(softwareModuleId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, softwareModuleId));
|
||||
}
|
||||
|
||||
private void assertSoftwareModuleQuota(final Long id, final int requested) {
|
||||
QuotaHelper.assertAssignmentQuota(id, requested, quotaManagement.getMaxSoftwareModulesPerDistributionSet(),
|
||||
SoftwareModule.class, DistributionSet.class, softwareModuleRepository::countByAssignedToId);
|
||||
@@ -422,17 +415,11 @@ public class JpaDistributionSetManagement
|
||||
});
|
||||
}
|
||||
|
||||
private JpaDistributionSet getById(final long id) {
|
||||
return jpaRepository
|
||||
.findById(id)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, id));
|
||||
}
|
||||
|
||||
private JpaDistributionSet toJpaDistributionSet(final DistributionSet distributionSet) {
|
||||
if (distributionSet instanceof JpaDistributionSet jpaDistributionSet) {
|
||||
return jpaDistributionSet;
|
||||
} else {
|
||||
return getById(distributionSet.getId());
|
||||
return jpaRepository.getById(distributionSet.getId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,8 +71,7 @@ public class JpaDistributionSetTypeManagement
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY))
|
||||
public void delete(final long id) {
|
||||
final JpaDistributionSetType toDelete = jpaRepository.findById(id)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSetType.class, id));
|
||||
final JpaDistributionSetType toDelete = jpaRepository.getById(id);
|
||||
|
||||
unassignDsTypeFromTargetTypes(id);
|
||||
|
||||
@@ -118,7 +117,7 @@ public class JpaDistributionSetTypeManagement
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY))
|
||||
public JpaDistributionSetType unassignSoftwareModuleType(final long id, final long softwareModuleTypeId) {
|
||||
final JpaDistributionSetType type = findDistributionSetTypeAndThrowExceptionIfNotFound(id);
|
||||
final JpaDistributionSetType type = jpaRepository.getById(id);
|
||||
checkDistributionSetTypeNotAssigned(id);
|
||||
type.removeModuleType(softwareModuleTypeRepository.getById(softwareModuleTypeId));
|
||||
return jpaRepository.save(type);
|
||||
@@ -132,7 +131,7 @@ public class JpaDistributionSetTypeManagement
|
||||
SoftwareModuleType.class, softwareModulesTypeIds, foundModules.stream().map(SoftwareModuleType::getId).toList());
|
||||
}
|
||||
|
||||
final JpaDistributionSetType type = findDistributionSetTypeAndThrowExceptionIfNotFound(dsTypeId);
|
||||
final JpaDistributionSetType type = jpaRepository.getById(dsTypeId);
|
||||
|
||||
checkDistributionSetTypeNotAssigned(dsTypeId);
|
||||
assertSoftwareModuleTypeQuota(dsTypeId, softwareModulesTypeIds.size());
|
||||
@@ -164,10 +163,6 @@ public class JpaDistributionSetTypeManagement
|
||||
});
|
||||
}
|
||||
|
||||
private JpaDistributionSetType findDistributionSetTypeAndThrowExceptionIfNotFound(final Long id) {
|
||||
return jpaRepository.findById(id).orElseThrow(() -> new EntityNotFoundException(DistributionSetType.class, id));
|
||||
}
|
||||
|
||||
private void checkDistributionSetTypeNotAssigned(final Long id) {
|
||||
if (distributionSetRepository.countByTypeId(id) > 0) {
|
||||
throw new EntityReadOnlyException(String.format(
|
||||
|
||||
@@ -162,8 +162,7 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
|
||||
|
||||
@Override
|
||||
public Page<Target> findTargetsOfRolloutGroup(final long rolloutGroupId, final Pageable page) {
|
||||
final JpaRolloutGroup rolloutGroup = rolloutGroupRepository.findById(rolloutGroupId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(RolloutGroup.class, rolloutGroupId));
|
||||
final JpaRolloutGroup rolloutGroup = rolloutGroupRepository.getById(rolloutGroupId);
|
||||
|
||||
if (isRolloutStatusReady(rolloutGroup)) {
|
||||
// in case of status ready the action has not been created yet and
|
||||
|
||||
@@ -305,7 +305,7 @@ public class JpaRolloutManagement implements RolloutManagement {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Rollout> get(final long rolloutId) {
|
||||
public Optional<Rollout> find(final long rolloutId) {
|
||||
return rolloutRepository.findById(rolloutId).map(Rollout.class::cast);
|
||||
}
|
||||
|
||||
@@ -316,7 +316,7 @@ public class JpaRolloutManagement implements RolloutManagement {
|
||||
|
||||
@Override
|
||||
public Optional<Rollout> getWithDetailedStatus(final long rolloutId) {
|
||||
final Optional<Rollout> rollout = get(rolloutId);
|
||||
final Optional<Rollout> rollout = find(rolloutId);
|
||||
if (rollout.isEmpty()) {
|
||||
return rollout;
|
||||
}
|
||||
@@ -344,7 +344,7 @@ public class JpaRolloutManagement implements RolloutManagement {
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public void pauseRollout(final long rolloutId) {
|
||||
final JpaRollout rollout = getRolloutOrThrowExceptionIfNotFound(rolloutId);
|
||||
final JpaRollout rollout = rolloutRepository.getById(rolloutId);
|
||||
if (RolloutStatus.RUNNING != rollout.getStatus()) {
|
||||
throw new RolloutIllegalStateException("Rollout can only be paused in state running but current state is " +
|
||||
rollout.getStatus().name().toLowerCase());
|
||||
@@ -361,7 +361,7 @@ public class JpaRolloutManagement implements RolloutManagement {
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public void resumeRollout(final long rolloutId) {
|
||||
final JpaRollout rollout = getRolloutOrThrowExceptionIfNotFound(rolloutId);
|
||||
final JpaRollout rollout = rolloutRepository.getById(rolloutId);
|
||||
if (RolloutStatus.PAUSED != rollout.getStatus()) {
|
||||
throw new RolloutIllegalStateException("Rollout can only be resumed in state paused but current state is " +
|
||||
rollout.getStatus().name().toLowerCase());
|
||||
@@ -388,7 +388,7 @@ public class JpaRolloutManagement implements RolloutManagement {
|
||||
|
||||
private Rollout approveOrDeny0(final long rolloutId, final Rollout.ApprovalDecision decision, final String remark) {
|
||||
log.debug("approveOrDeny rollout called for rollout {} with decision {}", rolloutId, decision);
|
||||
final JpaRollout rollout = getRolloutOrThrowExceptionIfNotFound(rolloutId);
|
||||
final JpaRollout rollout = rolloutRepository.getById(rolloutId);
|
||||
RolloutHelper.verifyRolloutInStatus(rollout, RolloutStatus.WAITING_FOR_APPROVAL);
|
||||
switch (decision) {
|
||||
case APPROVED: {
|
||||
@@ -417,7 +417,7 @@ public class JpaRolloutManagement implements RolloutManagement {
|
||||
public Rollout start(final long rolloutId) {
|
||||
log.debug("startRollout called for rollout {}", rolloutId);
|
||||
|
||||
final JpaRollout rollout = getRolloutOrThrowExceptionIfNotFound(rolloutId);
|
||||
final JpaRollout rollout = rolloutRepository.getById(rolloutId);
|
||||
RolloutHelper.checkIfRolloutCanStarted(rollout, rollout);
|
||||
rollout.setStatus(RolloutStatus.STARTING);
|
||||
rollout.setLastCheck(0);
|
||||
@@ -429,7 +429,7 @@ public class JpaRolloutManagement implements RolloutManagement {
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public Rollout update(final Update update) {
|
||||
final JpaRollout rollout = getRolloutOrThrowExceptionIfNotFound(update.getId());
|
||||
final JpaRollout rollout = rolloutRepository.getById(update.getId());
|
||||
checkIfDeleted(update.getId(), rollout.getStatus());
|
||||
|
||||
ObjectCopyUtil.copy(update, rollout, false, UnaryOperator.identity());
|
||||
@@ -441,8 +441,7 @@ public class JpaRolloutManagement implements RolloutManagement {
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public Rollout stop(long rolloutId) {
|
||||
final JpaRollout jpaRollout = rolloutRepository.findById(rolloutId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(Rollout.class, rolloutId));
|
||||
final JpaRollout jpaRollout = rolloutRepository.getById(rolloutId);
|
||||
|
||||
if (!ROLLOUT_STATUS_STOPPABLE.contains(jpaRollout.getStatus())) {
|
||||
log.debug("Failed to stop rollout {} because it is in {} status.", rolloutId, jpaRollout.getStatus());
|
||||
@@ -459,9 +458,7 @@ public class JpaRolloutManagement implements RolloutManagement {
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public void delete(final long rolloutId) {
|
||||
final JpaRollout jpaRollout = rolloutRepository.findById(rolloutId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(Rollout.class, rolloutId));
|
||||
this.delete0(jpaRollout);
|
||||
this.delete0(rolloutRepository.getById(rolloutId));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -490,7 +487,7 @@ public class JpaRolloutManagement implements RolloutManagement {
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public void triggerNextGroup(final long rolloutId) {
|
||||
final JpaRollout rollout = getRolloutOrThrowExceptionIfNotFound(rolloutId);
|
||||
final JpaRollout rollout = rolloutRepository.getById(rolloutId);
|
||||
if (RolloutStatus.RUNNING != rollout.getStatus()) {
|
||||
throw new RolloutIllegalStateException("Rollout is not in running state");
|
||||
}
|
||||
@@ -891,11 +888,6 @@ public class JpaRolloutManagement implements RolloutManagement {
|
||||
group.setErrorActionExp(errorActionExp);
|
||||
}
|
||||
|
||||
private JpaRollout getRolloutOrThrowExceptionIfNotFound(final Long rolloutId) {
|
||||
return rolloutRepository.findById(rolloutId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(Rollout.class, rolloutId));
|
||||
}
|
||||
|
||||
private @NotNull Map<Long, List<TotalTargetCountActionStatus>> getStatusCountItemForRollout(final List<Long> rollouts) {
|
||||
if (rollouts.isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
|
||||
@@ -101,21 +101,6 @@ public class JpaSoftwareModuleManagement
|
||||
return createdModule;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JpaSoftwareModule update(final Update update) {
|
||||
final JpaSoftwareModule module = jpaRepository.findById(update.getId())
|
||||
.orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, update.getId()));
|
||||
|
||||
// lock/unlock ONLY if locked flag is present!
|
||||
if (Boolean.TRUE.equals(update.getLocked())) {
|
||||
module.lock();
|
||||
} else if (Boolean.FALSE.equals(update.getLocked())) {
|
||||
module.unlock();
|
||||
}
|
||||
|
||||
return super.update(update, module);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<JpaSoftwareModule> softDelete(final Collection<JpaSoftwareModule> toDelete) {
|
||||
return toDelete.stream()
|
||||
@@ -213,16 +198,10 @@ public class JpaSoftwareModuleManagement
|
||||
if (softwareModule instanceof JpaSoftwareModule jpaSoftwareModule) {
|
||||
return jpaSoftwareModule;
|
||||
} else {
|
||||
return getById(softwareModule.getId());
|
||||
return jpaRepository.getById(softwareModule.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private JpaSoftwareModule getById(final long id) {
|
||||
return jpaRepository
|
||||
.findById(id)
|
||||
.orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, id));
|
||||
}
|
||||
|
||||
private void deleteGridFsArtifacts(final JpaSoftwareModule swModule) {
|
||||
jpaRepository.getAccessController().ifPresent(accessController ->
|
||||
accessController.assertOperationAllowed(AccessController.Operation.DELETE, swModule));
|
||||
|
||||
@@ -267,15 +267,13 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public TenantMetaData updateTenantMetadata(final long defaultDsType) {
|
||||
final JpaTenantMetaData data = (JpaTenantMetaData) getTenantMetadataWithoutDetails();
|
||||
data.setDefaultDsType(distributionSetTypeRepository.findById(defaultDsType)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSetType.class, defaultDsType)));
|
||||
data.setDefaultDsType(distributionSetTypeRepository.getById(defaultDsType));
|
||||
return tenantMetaDataRepository.save(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TenantMetaData getTenantMetadata(final long tenantId) {
|
||||
return tenantMetaDataRepository.findById(tenantId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(TenantMetaData.class, tenantId));
|
||||
return tenantMetaDataRepository.findById(tenantId).orElseThrow(() -> new EntityNotFoundException(TenantMetaData.class, tenantId));
|
||||
}
|
||||
|
||||
private static boolean isPostgreSql(final JpaProperties properties) {
|
||||
|
||||
@@ -27,7 +27,6 @@ import org.eclipse.hawkbit.repository.TargetFilterQueryFields;
|
||||
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
|
||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignActionTypeException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException;
|
||||
@@ -132,7 +131,7 @@ class JpaTargetFilterQueryManagement
|
||||
|
||||
@Override
|
||||
public Page<TargetFilterQuery> findByAutoAssignDSAndRsql(final long setId, final String rsql, final Pageable pageable) {
|
||||
final DistributionSet distributionSet = distributionSetManagement.getOrElseThrowException(setId);
|
||||
final DistributionSet distributionSet = distributionSetManagement.get(setId);
|
||||
|
||||
final List<Specification<JpaTargetFilterQuery>> specList = new ArrayList<>(2);
|
||||
specList.add(TargetFilterQuerySpecification.byAutoAssignDS(distributionSet));
|
||||
@@ -152,7 +151,7 @@ class JpaTargetFilterQueryManagement
|
||||
@Override
|
||||
@Transactional
|
||||
public TargetFilterQuery updateAutoAssignDS(final AutoAssignDistributionSetUpdate update) {
|
||||
final JpaTargetFilterQuery targetFilterQuery = findTargetFilterQueryOrThrowExceptionIfNotFound(update.targetFilterId());
|
||||
final JpaTargetFilterQuery targetFilterQuery = jpaRepository.getById(update.targetFilterId());
|
||||
if (update.dsId() == null) {
|
||||
targetFilterQuery.setAccessControlContext(null);
|
||||
targetFilterQuery.setAutoAssignDistributionSet(null);
|
||||
@@ -201,12 +200,7 @@ class JpaTargetFilterQueryManagement
|
||||
}
|
||||
|
||||
private boolean isConfirmationFlowEnabled() {
|
||||
return TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement)
|
||||
.isConfirmationFlowEnabled();
|
||||
}
|
||||
|
||||
private JpaTargetFilterQuery findTargetFilterQueryOrThrowExceptionIfNotFound(final Long queryId) {
|
||||
return jpaRepository.findById(queryId).orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, queryId));
|
||||
return TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement).isConfirmationFlowEnabled();
|
||||
}
|
||||
|
||||
private void assertMaxTargetsQuota(final String query, final String filterName, final long dsId) {
|
||||
@@ -245,7 +239,7 @@ class JpaTargetFilterQueryManagement
|
||||
}
|
||||
|
||||
private void validate(final Update update) {
|
||||
final JpaTargetFilterQuery targetFilterQuery = findTargetFilterQueryOrThrowExceptionIfNotFound(update.getId());
|
||||
final JpaTargetFilterQuery targetFilterQuery = jpaRepository.getById(update.getId());
|
||||
Optional.ofNullable(update.getQuery()).ifPresent(query -> {
|
||||
// validate the RSQL query syntax
|
||||
RsqlUtility.getInstance().validateRsqlFor(query, TargetFields.class, JpaTarget.class);
|
||||
|
||||
@@ -113,8 +113,7 @@ public class JpaTargetManagement
|
||||
public boolean isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(
|
||||
final String controllerId, final long distributionSetId, final String targetFilterQuery) {
|
||||
RsqlUtility.getInstance().validateRsqlFor(targetFilterQuery, TargetFields.class, JpaTarget.class);
|
||||
final DistributionSet ds = distributionSetManagement.get(distributionSetId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, distributionSetId));
|
||||
final DistributionSet ds = distributionSetManagement.get(distributionSetId);
|
||||
final Long distSetTypeId = ds.getType().getId();
|
||||
final List<Specification<JpaTarget>> specList = List.of(
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(targetFilterQuery, TargetFields.class),
|
||||
@@ -130,7 +129,7 @@ public class JpaTargetManagement
|
||||
@Override
|
||||
public Slice<Target> findByTargetFilterQueryAndNonDSAndCompatibleAndUpdatable(
|
||||
final long distributionSetId, final String rsql, final Pageable pageable) {
|
||||
final DistributionSet jpaDistributionSet = distributionSetManagement.getOrElseThrowException(distributionSetId);
|
||||
final DistributionSet jpaDistributionSet = distributionSetManagement.get(distributionSetId);
|
||||
final Long distSetTypeId = jpaDistributionSet.getType().getId();
|
||||
|
||||
return jpaRepository
|
||||
@@ -205,7 +204,7 @@ public class JpaTargetManagement
|
||||
|
||||
@Override
|
||||
public Page<Target> findByAssignedDistributionSet(final long distributionSetId, final Pageable pageable) {
|
||||
final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetId);
|
||||
final DistributionSet validDistSet = distributionSetManagement.get(distributionSetId);
|
||||
|
||||
return JpaManagementHelper.findAllWithCountBySpec(
|
||||
jpaRepository,
|
||||
@@ -214,7 +213,7 @@ public class JpaTargetManagement
|
||||
|
||||
@Override
|
||||
public Page<Target> findByAssignedDistributionSetAndRsql(final long distributionSetId, final String rsql, final Pageable pageable) {
|
||||
final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetId);
|
||||
final DistributionSet validDistSet = distributionSetManagement.get(distributionSetId);
|
||||
|
||||
final List<Specification<JpaTarget>> specList = List.of(
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class),
|
||||
@@ -225,7 +224,7 @@ public class JpaTargetManagement
|
||||
|
||||
@Override
|
||||
public Page<Target> findByInstalledDistributionSet(final long distributionSetId, final Pageable pageReq) {
|
||||
final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetId);
|
||||
final DistributionSet validDistSet = distributionSetManagement.get(distributionSetId);
|
||||
|
||||
return JpaManagementHelper.findAllWithCountBySpec(
|
||||
jpaRepository, List.of(TargetSpecifications.hasInstalledDistributionSet(validDistSet.getId())), pageReq);
|
||||
@@ -233,7 +232,7 @@ public class JpaTargetManagement
|
||||
|
||||
@Override
|
||||
public Page<Target> findByInstalledDistributionSetAndRsql(final long distributionSetId, final String rsql, final Pageable pageable) {
|
||||
final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetId);
|
||||
final DistributionSet validDistSet = distributionSetManagement.get(distributionSetId);
|
||||
|
||||
final List<Specification<JpaTarget>> specList = List.of(
|
||||
RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFields.class),
|
||||
@@ -275,7 +274,7 @@ public class JpaTargetManagement
|
||||
|
||||
@Override
|
||||
public long countByRsqlAndNonDsAndCompatibleAndUpdatable(final long distributionSetId, final String rsql) {
|
||||
final DistributionSet jpaDistributionSet = distributionSetManagement.getOrElseThrowException(distributionSetId);
|
||||
final DistributionSet jpaDistributionSet = distributionSetManagement.get(distributionSetId);
|
||||
final Long distSetTypeId = jpaDistributionSet.getType().getId();
|
||||
|
||||
return jpaRepository.count(
|
||||
@@ -314,7 +313,7 @@ public class JpaTargetManagement
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public void deleteByControllerId(final String controllerId) {
|
||||
jpaRepository.delete(getByControllerIdAndThrowIfNotFound(controllerId));
|
||||
jpaRepository.delete(jpaRepository.getByControllerId(controllerId));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -386,12 +385,12 @@ public class JpaTargetManagement
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public Target assignType(final String controllerId, final Long targetTypeId) {
|
||||
final JpaTarget target = getByControllerIdAndThrowIfNotFound(controllerId);
|
||||
final JpaTarget target = jpaRepository.getByControllerId(controllerId);
|
||||
|
||||
jpaRepository.getAccessController().ifPresent(acm ->
|
||||
acm.assertOperationAllowed(AccessController.Operation.UPDATE, target));
|
||||
|
||||
final JpaTargetType targetType = getTargetTypeByIdAndThrowIfNotFound(targetTypeId);
|
||||
final JpaTargetType targetType = targetTypeRepository.getById(targetTypeId);
|
||||
target.setTargetType(targetType);
|
||||
return jpaRepository.save(target);
|
||||
}
|
||||
@@ -401,7 +400,7 @@ public class JpaTargetManagement
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public Target unassignType(final String controllerId) {
|
||||
final JpaTarget target = getByControllerIdAndThrowIfNotFound(controllerId);
|
||||
final JpaTarget target = jpaRepository.getByControllerId(controllerId);
|
||||
target.setTargetType(null);
|
||||
return jpaRepository.save(target);
|
||||
}
|
||||
@@ -460,7 +459,7 @@ public class JpaTargetManagement
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public void createMetadata(final String controllerId, final String key, final String value) {
|
||||
final JpaTarget target = getByControllerIdAndThrowIfNotFound(controllerId);
|
||||
final JpaTarget target = jpaRepository.getByControllerId(controllerId);
|
||||
|
||||
// get the modifiable metadata map
|
||||
final Map<String, String> metadata = target.getMetadata();
|
||||
@@ -477,7 +476,7 @@ public class JpaTargetManagement
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public void createMetadata(final String controllerId, final Map<String, String> md) {
|
||||
final JpaTarget target = getByControllerIdAndThrowIfNotFound(controllerId);
|
||||
final JpaTarget target = jpaRepository.getByControllerId(controllerId);
|
||||
|
||||
// get the modifiable metadata map
|
||||
final Map<String, String> metadata = target.getMetadata();
|
||||
@@ -507,7 +506,7 @@ public class JpaTargetManagement
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public void deleteMetadata(final String controllerId, final String key) {
|
||||
final JpaTarget target = getByControllerIdAndThrowIfNotFound(controllerId);
|
||||
final JpaTarget target = jpaRepository.getByControllerId(controllerId);
|
||||
|
||||
// get the modifiable metadata map
|
||||
final Map<String, String> metadata = target.getMetadata();
|
||||
@@ -519,7 +518,7 @@ public class JpaTargetManagement
|
||||
}
|
||||
|
||||
private Map<String, String> getMap(final String controllerId, final MapAttribute<JpaTarget, String, String> mapAttribute) {
|
||||
getByControllerIdAndThrowIfNotFound(controllerId);
|
||||
jpaRepository.getByControllerId(controllerId);
|
||||
|
||||
final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
|
||||
final CriteriaQuery<Object[]> query = cb.createQuery(Object[].class);
|
||||
@@ -544,14 +543,6 @@ public class JpaTargetManagement
|
||||
return controllerIds.stream().filter(id -> !foundTargetMap.containsKey(id)).toList();
|
||||
}
|
||||
|
||||
private JpaTarget getByControllerIdAndThrowIfNotFound(final String controllerId) {
|
||||
return jpaRepository.getByControllerId(controllerId);
|
||||
}
|
||||
|
||||
private JpaTargetType getTargetTypeByIdAndThrowIfNotFound(final long id) {
|
||||
return targetTypeRepository.findById(id).orElseThrow(() -> new EntityNotFoundException(TargetType.class, id));
|
||||
}
|
||||
|
||||
private void assertMetadataQuota(final Long targetId, final int requested) {
|
||||
final int limit = quotaManagement.getMaxMetaDataEntriesPerTarget();
|
||||
QuotaHelper.assertAssignmentQuota(targetId, requested, limit, "Metadata", Target.class.getSimpleName(), null);
|
||||
@@ -560,8 +551,7 @@ public class JpaTargetManagement
|
||||
private List<Target> updateTag(
|
||||
final Collection<String> controllerIds, final long targetTagId, final Consumer<Collection<String>> notFoundHandler,
|
||||
final BiFunction<JpaTargetTag, JpaTarget, Target> updater) {
|
||||
final JpaTargetTag tag = targetTagRepository.findById(targetTagId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(TargetTag.class, targetTagId));
|
||||
final JpaTargetTag tag = targetTagRepository.getById(targetTagId);
|
||||
final List<JpaTarget> targets = controllerIds.size() == 1 ?
|
||||
jpaRepository.findByControllerId(controllerIds.iterator().next())
|
||||
.map(List::of)
|
||||
|
||||
@@ -99,7 +99,7 @@ public class JpaTargetTypeManagement
|
||||
dsTypes.stream().map(DistributionSetType::getId).toList());
|
||||
}
|
||||
|
||||
final JpaTargetType type = getByIdAndThrowIfNotFound(id);
|
||||
final JpaTargetType type = jpaRepository.getById(id);
|
||||
assertDistributionSetTypeQuota(id, distributionSetTypeIds.size(), typeId -> type.getDistributionSetTypes().size());
|
||||
dsTypes.forEach(type::addCompatibleDistributionSetType);
|
||||
|
||||
@@ -111,27 +111,16 @@ public class JpaTargetTypeManagement
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public TargetType unassignDistributionSetType(final long id, final long distributionSetTypeId) {
|
||||
final JpaTargetType type = getByIdAndThrowIfNotFound(id);
|
||||
assertDistributionSetTypeExists(distributionSetTypeId);
|
||||
final JpaTargetType type = jpaRepository.getById(id);
|
||||
if (!distributionSetTypeRepository.existsById(distributionSetTypeId)) {
|
||||
throw new EntityNotFoundException(DistributionSetType.class, distributionSetTypeId);
|
||||
}
|
||||
|
||||
type.removeDistributionSetType(distributionSetTypeId);
|
||||
|
||||
return jpaRepository.save(type);
|
||||
}
|
||||
|
||||
@SuppressWarnings("java:S2201") // the idea is just to check for distribution set type existence
|
||||
private void assertDistributionSetTypeExists(final Long typeId) {
|
||||
distributionSetTypeRepository
|
||||
.findById(typeId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSetType.class, typeId));
|
||||
}
|
||||
|
||||
private JpaTargetType getByIdAndThrowIfNotFound(final Long id) {
|
||||
return jpaRepository
|
||||
.findById(id)
|
||||
.orElseThrow(() -> new EntityNotFoundException(TargetType.class, id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Enforces the quota specifying the maximum number of
|
||||
* {@link DistributionSetType}s per {@link TargetType}.
|
||||
|
||||
@@ -32,7 +32,6 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Command repository operations for all {@link TenantAwareBaseEntity}s.
|
||||
*
|
||||
* @param <T> type if the entity type
|
||||
*/
|
||||
@NoRepositoryBean
|
||||
|
||||
@@ -56,6 +56,12 @@ public class BaseEntityRepositoryACM<T extends AbstractJpaBaseEntity> implements
|
||||
return repository.save(entity);
|
||||
}
|
||||
|
||||
// override because the default implementation is not protected by ACM proxy
|
||||
@Override
|
||||
public T getById(final Long id) {
|
||||
return findOne(byIdSpec(id)).orElseThrow(() -> new EntityNotFoundException(getManagementClass(), id));
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public Optional<T> findById(@NonNull final Long id) {
|
||||
|
||||
@@ -55,14 +55,6 @@ public interface LocalArtifactRepository extends BaseEntityRepository<JpaArtifac
|
||||
*/
|
||||
long countBySha1HashAndTenantAndSoftwareModuleDeletedIsFalse(@Param("sha1") String sha1, @Param("tenant") String tenant);
|
||||
|
||||
/**
|
||||
* Searches for a {@link Artifact} based on given gridFsFileName.
|
||||
*
|
||||
* @param sha1Hash to search
|
||||
* @return {@link Artifact} the first in the result list
|
||||
*/
|
||||
Optional<Artifact> findFirstBySha1Hash(String sha1Hash);
|
||||
|
||||
/**
|
||||
* Searches for a {@link Artifact} based user provided filename at upload.
|
||||
*
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
package org.eclipse.hawkbit.repository.jpa.rollout.condition;
|
||||
|
||||
import org.eclipse.hawkbit.repository.RolloutManagement;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.RolloutGroupRepository;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
@@ -55,7 +56,8 @@ 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.get(rollout.getId()).orElseThrow();
|
||||
final Rollout refreshedRollout = rolloutManagement.find(rollout.getId())
|
||||
.orElseThrow(() -> new EntityNotFoundException(Rollout.class, rollout.getId()));
|
||||
if (Rollout.RolloutStatus.PAUSED != refreshedRollout.getStatus()) {
|
||||
// if only the latest state is != paused then pause
|
||||
rolloutManagement.pauseRollout(rollout.getId());
|
||||
|
||||
Reference in New Issue
Block a user