diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/RepositoryApplicationConfiguration.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/RepositoryApplicationConfiguration.java
index d5e8db96f..1c562364f 100644
--- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/RepositoryApplicationConfiguration.java
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/RepositoryApplicationConfiguration.java
@@ -12,8 +12,8 @@ import java.util.HashMap;
import java.util.Map;
import org.eclipse.hawkbit.aspects.ExceptionMappingAspectHandler;
-import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
+import org.eclipse.hawkbit.repository.jpa.SystemManagement;
import org.eclipse.hawkbit.repository.model.helper.AfterTransactionCommitExecutorHolder;
import org.eclipse.hawkbit.repository.model.helper.CacheManagerHolder;
import org.eclipse.hawkbit.repository.model.helper.SecurityTokenGeneratorHolder;
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/EntityChangeEventListener.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/EntityChangeEventListener.java
index 7bfbd957e..2f63a3122 100644
--- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/EntityChangeEventListener.java
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/EntityChangeEventListener.java
@@ -19,7 +19,7 @@ import org.eclipse.hawkbit.eventbus.event.TargetCreatedEvent;
import org.eclipse.hawkbit.eventbus.event.TargetDeletedEvent;
import org.eclipse.hawkbit.eventbus.event.TargetInfoUpdateEvent;
import org.eclipse.hawkbit.executor.AfterTransactionCommitExecutor;
-import org.eclipse.hawkbit.repository.TargetRepository;
+import org.eclipse.hawkbit.repository.jpa.TargetRepository;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetInfo;
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
@@ -66,7 +66,7 @@ public class EntityChangeEventListener {
* in case exception happens in the
* {@link ProceedingJoinPoint#proceed()}
*/
- @Around("execution(* org.eclipse.hawkbit.repository.TargetInfoRepository.save(..))")
+ @Around("execution(* org.eclipse.hawkbit.repository.jpa.TargetInfoRepository.save(..))")
// Exception squid:S00112 - Is aspectJ proxy
@SuppressWarnings({ "squid:S00112" })
public Object targetCreated(final ProceedingJoinPoint joinpoint) throws Throwable {
@@ -93,7 +93,7 @@ public class EntityChangeEventListener {
* in case exception happens in the
* {@link ProceedingJoinPoint#proceed()}
*/
- @Around("execution(* org.eclipse.hawkbit.repository.TargetRepository.deleteByIdIn(..))")
+ @Around("execution(* org.eclipse.hawkbit.repository.jpa.TargetRepository.deleteByIdIn(..))")
// Exception squid:S00112 - Is aspectJ proxy
@SuppressWarnings({ "squid:S00112" })
public Object targetDeletedById(final ProceedingJoinPoint joinpoint) throws Throwable {
@@ -115,8 +115,8 @@ public class EntityChangeEventListener {
* in case exception happens in the
* {@link ProceedingJoinPoint#proceed()}
*/
- @Around("execution(* org.eclipse.hawkbit.repository.TargetRepository.delete(..))")
- // Exception squid:S00112 - Is aspectJ proxy
+ @Around("execution(* org.eclipse.hawkbit.repository.jpa.TargetRepository.delete(..))")
+ // Exception squid:S00112 - Is aspectJ proxy
@SuppressWarnings({ "squid:S00112", "unchecked" })
public Object targetDeleted(final ProceedingJoinPoint joinpoint) throws Throwable {
final String currentTenant = tenantAware.getCurrentTenant();
@@ -146,7 +146,7 @@ public class EntityChangeEventListener {
afterCommit.afterCommit(() -> eventBus.post(new TargetDeletedEvent(tenant, targetId)));
}
- private boolean isTargetInfoNew(final Object targetInfo) {
+ private static boolean isTargetInfoNew(final Object targetInfo) {
return ((TargetInfo) targetInfo).isNew();
}
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java
index 024ec11cb..977b9f171 100644
--- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java
@@ -13,11 +13,7 @@ import java.util.List;
import javax.validation.constraints.NotNull;
-import org.eclipse.hawkbit.artifact.repository.ArtifactRepository;
-import org.eclipse.hawkbit.artifact.repository.ArtifactStoreException;
-import org.eclipse.hawkbit.artifact.repository.HashNotMatchException;
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
-import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.exception.ArtifactDeleteFailedException;
import org.eclipse.hawkbit.repository.exception.ArtifactUploadFailedException;
@@ -31,47 +27,110 @@ import org.eclipse.hawkbit.repository.model.ExternalArtifact;
import org.eclipse.hawkbit.repository.model.ExternalArtifactProvider;
import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
-import org.eclipse.hawkbit.repository.specifications.SoftwareModuleSpecification;
import org.hibernate.validator.constraints.NotEmpty;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
-import org.springframework.data.jpa.domain.Specification;
-import org.springframework.data.jpa.repository.Modifying;
import org.springframework.hateoas.Identifiable;
import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
-import org.springframework.validation.annotation.Validated;
/**
* Service for {@link Artifact} management operations.
*
*/
-@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
-@Validated
-@Service
-public class ArtifactManagement {
+public interface ArtifactManagement {
- private static final Logger LOG = LoggerFactory.getLogger(ArtifactManagement.class);
+ /**
+ * Creates {@link ExternalArtifact} based on given provider.
+ *
+ * @param externalRepository
+ * the artifact is located in
+ * @param urlSuffix
+ * of the artifact
+ * {@link ExternalArtifactProvider#getDefaultSuffix()} is used if
+ * empty.
+ * @param moduleId
+ * to assign the artifact to
+ *
+ * @return created {@link ExternalArtifact}
+ *
+ * @throws EntityNotFoundException
+ * if {@link SoftwareModule} with given ID does not exist
+ */
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY)
+ ExternalArtifact createExternalArtifact(@NotNull ExternalArtifactProvider externalRepository, String urlSuffix,
+ @NotNull Long moduleId);
- @Autowired
- private LocalArtifactRepository localArtifactRepository;
+ /**
+ * Persists {@link ExternalArtifactProvider} based on given properties.
+ *
+ * @param name
+ * of the provided
+ * @param description
+ * which is optional
+ * @param basePath
+ * of all {@link ExternalArtifact}s of the provider
+ * @param defaultUrlSuffix
+ * that is used if {@link ExternalArtifact#getUrlSuffix()} is
+ * empty.
+ * @return created {@link ExternalArtifactProvider}
+ */
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY)
+ ExternalArtifactProvider createExternalArtifactProvider(@NotEmpty String name, String description,
+ @NotNull String basePath, String defaultUrlSuffix);
- @Autowired
- private ExternalArtifactRepository externalArtifactRepository;
+ /**
+ * Persists artifact binary as provided by given InputStream. assign the
+ * artifact in addition to given {@link SoftwareModule}.
+ *
+ * @param inputStream
+ * to read from for artifact binary
+ * @param moduleId
+ * to assign the new artifact to
+ * @param filename
+ * of the artifact
+ * @param overrideExisting
+ * to true if the artifact binary can be overridden
+ * if it already exists
+ *
+ * @return uploaded {@link LocalArtifact}
+ *
+ * @throw ArtifactUploadFailedException if upload fails
+ */
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
+ @Transactional(isolation = Isolation.READ_UNCOMMITTED)
+ default LocalArtifact createLocalArtifact(final InputStream inputStream, final Long moduleId, final String filename,
+ final boolean overrideExisting) {
+ return createLocalArtifact(inputStream, moduleId, filename, null, null, overrideExisting, null);
+ }
- @Autowired
- private SoftwareModuleRepository softwareModuleRepository;
-
- @Autowired
- private ExternalArtifactProviderRepository externalArtifactProviderRepository;
-
- @Autowired
- private ArtifactRepository artifactRepository;
+ /**
+ * Persists artifact binary as provided by given InputStream. assign the
+ * artifact in addition to given {@link SoftwareModule}.
+ *
+ * @param inputStream
+ * to read from for artifact binary
+ * @param moduleId
+ * to assign the new artifact to
+ * @param filename
+ * of the artifact
+ * @param overrideExisting
+ * to true if the artifact binary can be overridden
+ * if it already exists
+ * @param contentType
+ * the contentType of the file
+ *
+ * @return uploaded {@link LocalArtifact}
+ *
+ * @throw ArtifactUploadFailedException if upload fails
+ */
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
+ @Transactional(isolation = Isolation.READ_UNCOMMITTED)
+ default LocalArtifact createLocalArtifact(final InputStream inputStream, final Long moduleId, final String filename,
+ final boolean overrideExisting, final String contentType) {
+ return createLocalArtifact(inputStream, moduleId, filename, null, null, overrideExisting, contentType);
+ }
/**
* Persists artifact binary as provided by given InputStream. assign the
@@ -105,59 +164,112 @@ public class ArtifactManagement {
* @throws InvalidSHA1HashException
* if check against provided SHA1 checksum failed
*/
- @Modifying
- @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY)
- public LocalArtifact createLocalArtifact(@NotNull final InputStream stream, @NotNull final Long moduleId,
- @NotEmpty final String filename, final String providedMd5Sum, final String providedSha1Sum,
- final boolean overrideExisting, final String contentType) {
- DbArtifact result = null;
+ LocalArtifact createLocalArtifact(@NotNull InputStream stream, @NotNull Long moduleId, @NotEmpty String filename,
+ String providedMd5Sum, String providedSha1Sum, boolean overrideExisting, String contentType);
- final SoftwareModule softwareModule = getModuleAndThrowExceptionIfThatFails(moduleId);
+ /**
+ * Deletes {@link Artifact} based on given id.
+ *
+ * @param id
+ * of the {@link Artifact} that has to be deleted.
+ * @throws ArtifactDeleteFailedException
+ * if deletion failed (MongoDB is not available)
+ *
+ */
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY)
+ void deleteExternalArtifact(@NotNull Long id);
- final LocalArtifact existing = checkForExistingArtifact(filename, overrideExisting, softwareModule);
+ /**
+ * Deletes a local artifact.
+ *
+ * @param existing
+ * the related local artifact
+ */
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY)
+ void deleteLocalArtifact(@NotNull LocalArtifact existing);
- try {
- result = artifactRepository.store(stream, filename, contentType,
- new DbArtifactHash(providedSha1Sum, providedMd5Sum));
- } catch (final ArtifactStoreException e) {
- throw new ArtifactUploadFailedException(e);
- } catch (final HashNotMatchException e) {
- if (e.getHashFunction().equals(HashNotMatchException.SHA1)) {
- throw new InvalidSHA1HashException(e.getMessage(), e);
- } else {
- throw new InvalidMD5HashException(e.getMessage(), e);
- }
- }
- if (result == null) {
- return null;
- }
+ /**
+ * Deletes {@link Artifact} based on given id.
+ *
+ * @param id
+ * of the {@link Artifact} that has to be deleted.
+ * @throws ArtifactDeleteFailedException
+ * if deletion failed (MongoDB is not available)
+ *
+ */
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY)
+ void deleteLocalArtifact(@NotNull Long id);
- return storeArtifactMetadata(softwareModule, filename, result, existing);
- }
+ /**
+ * Searches for {@link Artifact} with given {@link Identifiable}.
+ *
+ * @param id
+ * to search for
+ * @return found {@link Artifact} or null is it could not be
+ * found.
+ */
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
+ Artifact findArtifact(@NotNull Long id);
- private static LocalArtifact checkForExistingArtifact(final String filename, final boolean overrideExisting,
- final SoftwareModule softwareModule) {
- if (softwareModule.getLocalArtifactByFilename(filename).isPresent()) {
- if (overrideExisting) {
- LOG.debug("overriding existing artifact with new filename {}", filename);
- return softwareModule.getLocalArtifactByFilename(filename).get();
- } else {
- throw new EntityAlreadyExistsException("File with that name already exists in the Software Module");
- }
- }
- return null;
- }
+ /**
+ * Find by artifact by software module id and filename.
+ *
+ * @param filename
+ * file name
+ * @param softwareModuleId
+ * software module id.
+ * @return LocalArtifact if artifact present
+ */
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
+ + SpringEvalExpressions.IS_CONTROLLER)
+ List findByFilenameAndSoftwareModule(@NotNull String filename, @NotNull Long softwareModuleId);
- private SoftwareModule getModuleAndThrowExceptionIfThatFails(final Long moduleId) {
- final SoftwareModule softwareModule = findSoftwareModuleWithDetails(moduleId);
+ /**
+ * Find all local artifact by sha1 and return the first artifact.
+ *
+ * @param sha1
+ * the sha1
+ * @return the first local artifact
+ */
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
+ + SpringEvalExpressions.IS_CONTROLLER)
+ LocalArtifact findFirstLocalArtifactsBySHA1(@NotNull String sha1);
- if (softwareModule == null) {
- LOG.debug("no software module with ID {} exists", moduleId);
- throw new EntityNotFoundException("Software Module: " + moduleId);
- }
- return softwareModule;
- }
+ /**
+ * Searches for {@link Artifact} with given file name.
+ *
+ * @param filename
+ * to search for
+ * @return found List of {@link LocalArtifact}s.
+ */
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
+ + SpringEvalExpressions.IS_CONTROLLER)
+ List findLocalArtifactByFilename(@NotNull String filename);
+
+ /**
+ * Get local artifact for a base software module.
+ *
+ * @param pageReq
+ * Pageable
+ * @param swId
+ * software module id
+ * @return Page
+ */
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
+ Page findLocalArtifactBySoftwareModule(@NotNull Pageable pageReq, @NotNull Long swId);
+
+ /**
+ * Finds {@link SoftwareModule} by given id.
+ *
+ * @param id
+ * to search for
+ * @return the found {@link SoftwareModule}s or null if not
+ * found.
+ */
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
+ + SpringEvalExpressions.IS_CONTROLLER)
+ SoftwareModule findSoftwareModuleById(@NotNull Long id);
/**
* Retrieves software module including details (
@@ -170,7 +282,7 @@ public class ArtifactManagement {
* @return the found {@link SoftwareModule}s
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
- protected SoftwareModule findSoftwareModuleWithDetails(@NotNull final Long id) {
+ default SoftwareModule findSoftwareModuleWithDetails(@NotNull final Long id) {
final SoftwareModule result = findSoftwareModuleById(id);
if (result != null) {
result.getArtifacts().size();
@@ -179,211 +291,6 @@ public class ArtifactManagement {
return result;
}
- /**
- * Find all local artifact by sha1 and return the first artifact.
- *
- * @param sha1
- * the sha1
- * @return the first local artifact
- */
- @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
- + SpringEvalExpressions.IS_CONTROLLER)
- public LocalArtifact findFirstLocalArtifactsBySHA1(final String sha1) {
- return localArtifactRepository.findFirstByGridFsFileName(sha1);
- }
-
- /**
- * Finds {@link SoftwareModule} by given id.
- *
- * @param id
- * to search for
- * @return the found {@link SoftwareModule}s or null if not
- * found.
- */
- @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
- + SpringEvalExpressions.IS_CONTROLLER)
- protected SoftwareModule findSoftwareModuleById(@NotNull final Long id) {
-
- final Specification spec = SoftwareModuleSpecification.byId(id);
-
- return softwareModuleRepository.findOne(spec);
- }
-
- private LocalArtifact storeArtifactMetadata(final SoftwareModule softwareModule, final String providedFilename,
- final DbArtifact result, final LocalArtifact existing) {
- LocalArtifact artifact = existing;
- if (existing == null) {
- artifact = new LocalArtifact(result.getHashes().getSha1(), providedFilename, softwareModule);
- }
- artifact.setMd5Hash(result.getHashes().getMd5());
- artifact.setSha1Hash(result.getHashes().getSha1());
- artifact.setSize(result.getSize());
-
- LOG.debug("storing new artifact into repository {}", artifact);
- return localArtifactRepository.save(artifact);
- }
-
- /**
- * Persists {@link ExternalArtifactProvider} based on given properties.
- *
- * @param name
- * of the provided
- * @param description
- * which is optional
- * @param basePath
- * of all {@link ExternalArtifact}s of the provider
- * @param defaultUrlSuffix
- * that is used if {@link ExternalArtifact#getUrlSuffix()} is
- * empty.
- * @return created {@link ExternalArtifactProvider}
- */
- @Modifying
- @Transactional(isolation = Isolation.READ_UNCOMMITTED)
- @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY)
- public ExternalArtifactProvider createExternalArtifactProvider(@NotEmpty final String name,
- final String description, @NotNull final String basePath, final String defaultUrlSuffix) {
- return externalArtifactProviderRepository
- .save(new ExternalArtifactProvider(name, description, basePath, defaultUrlSuffix));
- }
-
- /**
- * Creates {@link ExternalArtifact} based on given provider.
- *
- * @param externalRepository
- * the artifact is located in
- * @param urlSuffix
- * of the artifact
- * {@link ExternalArtifactProvider#getDefaultSuffix()} is used if
- * empty.
- * @param moduleId
- * to assign the artifact to
- *
- * @return created {@link ExternalArtifact}
- *
- * @throws EntityNotFoundException
- * if {@link SoftwareModule} with given ID does not exist
- */
- @Modifying
- @Transactional(isolation = Isolation.READ_UNCOMMITTED)
- @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY)
- public ExternalArtifact createExternalArtifact(@NotNull final ExternalArtifactProvider externalRepository,
- final String urlSuffix, @NotNull final Long moduleId) {
-
- final SoftwareModule module = getModuleAndThrowExceptionIfThatFails(moduleId);
- return externalArtifactRepository.save(new ExternalArtifact(externalRepository, urlSuffix, module));
- }
-
- /**
- * Deletes {@link Artifact} based on given id.
- *
- * @param id
- * of the {@link Artifact} that has to be deleted.
- * @throws ArtifactDeleteFailedException
- * if deletion failed (MongoDB is not available)
- *
- */
- @Modifying
- @Transactional(isolation = Isolation.READ_UNCOMMITTED)
- @PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY)
- public void deleteLocalArtifact(@NotNull final Long id) {
- final LocalArtifact existing = localArtifactRepository.findOne(id);
-
- if (null == existing) {
- return;
- }
-
- deleteGridFsArtifact(existing);
-
- existing.getSoftwareModule().removeArtifact(existing);
- softwareModuleRepository.save(existing.getSoftwareModule());
- localArtifactRepository.delete(id);
- }
-
- /**
- * Delete a grid fs file.
- *
- * @param existing
- * the related local artifact
- */
- @Modifying
- @Transactional(isolation = Isolation.READ_UNCOMMITTED)
- @PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY)
- public void deleteGridFsArtifact(@NotNull final LocalArtifact existing) {
- if (existing == null) {
- return;
- }
-
- boolean artifactIsOnlyUsedByOneSoftwareModule = true;
- for (final LocalArtifact lArtifact : localArtifactRepository
- .findByGridFsFileName(existing.getGridFsFileName())) {
- if (!lArtifact.getSoftwareModule().isDeleted()
- && Long.compare(lArtifact.getSoftwareModule().getId(), existing.getSoftwareModule().getId()) != 0) {
- artifactIsOnlyUsedByOneSoftwareModule = false;
- break;
- }
- }
-
- if (artifactIsOnlyUsedByOneSoftwareModule) {
- try {
- LOG.debug("deleting artifact from repository {}", existing.getGridFsFileName());
- artifactRepository.deleteBySha1(existing.getGridFsFileName());
- } catch (final ArtifactStoreException e) {
- throw new ArtifactDeleteFailedException(e);
- }
- }
- }
-
- /**
- * Deletes {@link Artifact} based on given id.
- *
- * @param id
- * of the {@link Artifact} that has to be deleted.
- * @throws ArtifactDeleteFailedException
- * if deletion failed (MongoDB is not available)
- *
- */
- @Modifying
- @Transactional(isolation = Isolation.READ_UNCOMMITTED)
- @PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY)
- public void deleteExternalArtifact(@NotNull final Long id) {
- final ExternalArtifact existing = externalArtifactRepository.findOne(id);
-
- if (null == existing) {
- return;
- }
-
- existing.getSoftwareModule().removeArtifact(existing);
- softwareModuleRepository.save(existing.getSoftwareModule());
- externalArtifactRepository.delete(id);
- }
-
- /**
- * Searches for {@link Artifact} with given file name.
- *
- * @param filename
- * to search for
- * @return found List of {@link LocalArtifact}s.
- */
- @NotNull
- @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
- + SpringEvalExpressions.IS_CONTROLLER)
- public List findLocalArtifactByFilename(@NotNull final String filename) {
- return localArtifactRepository.findByFilename(filename);
- }
-
- /**
- * Searches for {@link Artifact} with given {@link Identifiable}.
- *
- * @param id
- * to search for
- * @return found {@link Artifact} or null is it could not be
- * found.
- */
- @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
- public Artifact findArtifact(@NotNull final Long id) {
- return localArtifactRepository.findOne(id);
- }
-
/**
* Loads {@link org.eclipse.hawkbit.artifact.server.json.model.Artifact}
* from store for given {@link LocalArtifact}.
@@ -398,98 +305,6 @@ public class ArtifactManagement {
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_DOWNLOAD_ARTIFACT + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.HAS_CONTROLLER_DOWNLOAD)
- public DbArtifact loadLocalArtifactBinary(@NotNull final LocalArtifact artifact) {
- final DbArtifact result = artifactRepository.getArtifactBySha1(artifact.getGridFsFileName());
- if (result == null) {
- throw new GridFSDBFileNotFoundException(artifact.getGridFsFileName());
- }
+ DbArtifact loadLocalArtifactBinary(@NotNull LocalArtifact artifact);
- return result;
- }
-
- /**
- * Persists artifact binary as provided by given InputStream. assign the
- * artifact in addition to given {@link SoftwareModule}.
- *
- * @param inputStream
- * to read from for artifact binary
- * @param moduleId
- * to assign the new artifact to
- * @param filename
- * of the artifact
- * @param overrideExisting
- * to true if the artifact binary can be overridden
- * if it already exists
- * @param contentType
- * the contentType of the file
- *
- * @return uploaded {@link LocalArtifact}
- *
- * @throw ArtifactUploadFailedException if upload fails
- */
- @Modifying
- @Transactional(isolation = Isolation.READ_UNCOMMITTED)
- @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
- public LocalArtifact createLocalArtifact(final InputStream inputStream, final Long moduleId, final String filename,
- final boolean overrideExisting, final String contentType) {
- return createLocalArtifact(inputStream, moduleId, filename, null, null, overrideExisting, contentType);
- }
-
- /**
- * Persists artifact binary as provided by given InputStream. assign the
- * artifact in addition to given {@link SoftwareModule}.
- *
- * @param inputStream
- * to read from for artifact binary
- * @param moduleId
- * to assign the new artifact to
- * @param filename
- * of the artifact
- * @param overrideExisting
- * to true if the artifact binary can be overdiden
- * if it already exists
- *
- * @return uploaded {@link LocalArtifact}
- *
- * @throw ArtifactUploadFailedException if upload failes
- */
- @Modifying
- @Transactional(isolation = Isolation.READ_UNCOMMITTED)
- @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
- public LocalArtifact createLocalArtifact(final InputStream inputStream, final Long moduleId, final String filename,
- final boolean overrideExisting) {
- return createLocalArtifact(inputStream, moduleId, filename, null, null, overrideExisting, null);
- }
-
- /**
- * Get local artifact for a base software module.
- *
- * @param pageReq
- * Pageable
- * @param swId
- * software module id
- * @return Page
- */
- @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
- public Page findLocalArtifactBySoftwareModule(@NotNull final Pageable pageReq,
- @NotNull final Long swId) {
- return localArtifactRepository.findBySoftwareModuleId(pageReq, swId);
- }
-
- /**
- * Find by artifact by software module id and filename.
- *
- * @param filename
- * file name
- * @param softwareModuleId
- * software module id.
- * @return LocalArtifact if artifact present
- */
- @NotNull
- @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
- + SpringEvalExpressions.IS_CONTROLLER)
- public List findByFilenameAndSoftwareModule(@NotNull final String filename,
- @NotNull final Long softwareModuleId) {
- return localArtifactRepository.findByFilenameAndSoftwareModuleId(filename, softwareModuleId);
- }
-}
+}
\ No newline at end of file
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java
index 11879edfd..b70ad3bdd 100644
--- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java
@@ -12,10 +12,6 @@ import java.net.URI;
import java.util.List;
import java.util.Map;
-import javax.persistence.EntityManager;
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Root;
import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
@@ -26,78 +22,102 @@ import org.eclipse.hawkbit.repository.exception.ToManyStatusEntriesException;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.ActionStatus;
-import org.eclipse.hawkbit.repository.model.ActionStatus_;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetInfo;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
-import org.eclipse.hawkbit.repository.model.Target_;
-import org.eclipse.hawkbit.repository.model.TenantConfiguration;
-import org.eclipse.hawkbit.repository.specifications.ActionSpecifications;
-import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
import org.hibernate.validator.constraints.NotEmpty;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.jpa.domain.Specification;
-import org.springframework.data.jpa.repository.Modifying;
import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
-import org.springframework.validation.annotation.Validated;
/**
- * Service layer for all operations of the controller API (with access
- * permissions only for the controller).
- *
- *
+ * Service layer for all operations of the DDI API (with access permissions only
+ * for the controller).
*
*/
-@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
-@Validated
-@Service
-public class ControllerManagement {
- private static final Logger LOG = LoggerFactory.getLogger(ControllerManagement.class);
- private static final Logger LOG_DOS = LoggerFactory.getLogger("server-security.dos");
+public interface ControllerManagement {
- public static final String SERVER_MESSAGE_PREFIX = "Update Server: ";
+ String SERVER_MESSAGE_PREFIX = "Update Server: ";
- @Autowired
- private EntityManager entityManager;
+ /**
+ * Simple addition of a new {@link ActionStatus} entry to the {@link Action}
+ * . No state changes.
+ *
+ * @param statusMessage
+ * to add to the action
+ */
+ @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
+ void addInformationalActionStatus(@NotNull ActionStatus statusMessage);
- @Autowired
- private ActionRepository actionRepository;
+ /**
+ * Adds an {@link ActionStatus} for a cancel {@link Action} including
+ * potential state changes for the target and the {@link Action} itself.
+ *
+ * @param actionStatus
+ * to be added
+ * @return the persisted {@link Action}
+ *
+ * @throws EntityAlreadyExistsException
+ * if a given entity already exists
+ *
+ */
+ @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
+ Action addCancelActionStatus(@NotNull ActionStatus actionStatus);
- @Autowired
- private TargetRepository targetRepository;
+ /**
+ * Adds an {@link ActionStatus} entry for an update {@link Action} including
+ * potential state changes for the target and the {@link Action} itself.
+ *
+ * @param actionStatus
+ * to be added
+ * @return the updated {@link Action}
+ *
+ * @throws EntityAlreadyExistsException
+ * if a given entity already exists
+ * @throws ToManyStatusEntriesException
+ * if more than the allowed number of status entries are
+ * inserted
+ */
+ @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
+ Action addUpdateActionStatus(@NotNull ActionStatus actionStatus);
- @Autowired
- private TargetManagement targetManagement;
+ /**
+ * Retrieves all {@link Action}s which are active and assigned to a
+ * {@link Target}.
+ *
+ * @param target
+ * the target to retrieve the actions from
+ * @return a list of actions assigned to given target which are active
+ */
+ @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
+ List findActionByTargetAndActive(@NotNull Target target);
- @Autowired
- private DeploymentManagement deploymentManagement;
+ /**
+ * Get the {@link Action} entity for given actionId with all lazy
+ * attributes.
+ *
+ * @param actionId
+ * to be id of the action
+ * @return the corresponding {@link Action}
+ */
+ @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
+ Action findActionWithDetails(@NotNull Long actionId);
- @Autowired
- private TargetInfoRepository targetInfoRepository;
-
- @Autowired
- private SoftwareModuleRepository softwareModuleRepository;
-
- @Autowired
- private ActionStatusRepository actionStatusRepository;
-
- @Autowired
- private HawkbitSecurityProperties securityProperties;
-
- @Autowired
- private TenantConfigurationRepository tenantConfigurationRepository;
-
- @Autowired
- private TenantConfigurationManagement tenantConfigurationManagement;
+ /**
+ * register new target in the repository (plug-and-play).
+ *
+ * @param controllerId
+ * reference
+ * @param address
+ * the client IP address of the target, might be {@code null}
+ * @return target reference
+ */
+ @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
+ Target findOrRegisterTargetIfItDoesNotexist(@NotEmpty String controllerId, URI address);
/**
* Retrieves all {@link SoftwareModule}s which are assigned to the given
@@ -110,46 +130,13 @@ public class ControllerManagement {
* {@code distributionSet}
*/
@PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
- public String findPollingTime() {
- final TenantConfigurationKey configurationKey = TenantConfigurationKey.POLLING_TIME_INTERVAL;
- final Class propertyType = String.class;
- tenantConfigurationManagement.validateTenantConfigurationDataType(configurationKey, propertyType);
- final TenantConfiguration tenantConfiguration = tenantConfigurationRepository
- .findByKey(configurationKey.getKeyName());
- return tenantConfigurationManagement
- .buildTenantConfigurationValueByKey(configurationKey, propertyType, tenantConfiguration).getValue();
- }
-
- /**
- * Refreshes the time of the last time the controller has been connected to
- * the server.
- *
- * @param targetid
- * of the target to to update
- * @param address
- * the client address of the target, might be {@code null}
- * @return the updated target
- *
- * @throws EntityNotFoundException
- * if target with given ID could not be found
- */
- @Modifying
- @Transactional(isolation = Isolation.READ_UNCOMMITTED)
- @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
- public Target updateLastTargetQuery(@NotEmpty final String targetid, final URI address) {
- final Target target = targetRepository.findByControllerId(targetid);
- if (target == null) {
- throw new EntityNotFoundException(targetid);
- }
-
- return updateLastTargetQuery(target.getTargetInfo(), address).getTarget();
- }
+ List findSoftwareModulesByDistributionSet(@NotNull DistributionSet distributionSet);
/**
* Retrieves last {@link UpdateAction} for a download of an artifact of
* given module and target.
*
- * @param targetId
+ * @param controllerId
* to look for
* @param module
* that should be assigned to the target
@@ -159,17 +146,28 @@ public class ControllerManagement {
* if action for given combination could not be found
*/
@PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
- public Action getActionForDownloadByTargetAndSoftwareModule(@NotNull final String targetId,
- @NotNull final SoftwareModule module) {
- final List action = actionRepository.findActionByTargetAndSoftwareModule(targetId, module);
+ Action getActionForDownloadByTargetAndSoftwareModule(@NotEmpty String controllerId, @NotNull SoftwareModule module);
- if (action.isEmpty() || action.get(0).isCancelingOrCanceled()) {
- throw new EntityNotFoundException(
- "No assigment found for module " + module.getId() + " to target " + targetId);
- }
+ /**
+ * @return current {@link TenantConfigurationKey#POLLING_TIME_INTERVAL}.
+ */
+ @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
+ String getPollingTime();
- return action.get(0);
- }
+ /**
+ * An direct access to the security token of an
+ * {@link Target#getSecurityToken()} without authorization. This is
+ * necessary to be able to access the security-token without any
+ * security-context information because the security-token is used for
+ * authentication.
+ *
+ * @param controllerId
+ * the ID of the controller to retrieve the security token for
+ * @return the security context of the target, in case no target exists for
+ * the given controllerId {@code null} is returned
+ */
+ @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
+ String getSecurityTokenByControllerId(@NotEmpty String controllerId);
/**
* Checks if a given target has currently or has even been assigned to the
@@ -178,7 +176,7 @@ public class ControllerManagement {
* assigned or had ever been assigned to the target and so it's visible to a
* specific target e.g. for downloading.
*
- * @param targetId
+ * @param controllerId
* the ID of the target to check
* @param localArtifact
* the artifact to verify if the given target had even been
@@ -187,14 +185,56 @@ public class ControllerManagement {
* relation to the given artifact through the action history,
* otherwise {@code false}
*/
- public boolean hasTargetArtifactAssigned(@NotNull final String targetId,
- @NotNull final LocalArtifact localArtifact) {
- final Target target = targetRepository.findByControllerId(targetId);
- if (target == null) {
- return false;
- }
- return actionRepository.count(ActionSpecifications.hasTargetAssignedArtifact(target, localArtifact)) > 0;
- }
+ @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
+ boolean hasTargetArtifactAssigned(@NotNull String controllerId, @NotNull LocalArtifact localArtifact);
+
+ /**
+ * Registers retrieved status for given {@link Target} and {@link Action} if
+ * it does not exist yet.
+ *
+ * @param action
+ * to the handle status for
+ * @param message
+ * for the status
+ * @return the update action in case the status has been changed to
+ * {@link Status#RETRIEVED}
+ */
+ @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
+ Action registerRetrieved(@NotNull Action action, String message);
+
+ /**
+ * Updates attributes of the controller.
+ *
+ * @param controllerId
+ * to update
+ * @param attributes
+ * to insert
+ *
+ * @return updated {@link Target}
+ *
+ * @throws EntityNotFoundException
+ * if target that has to be updated could not be found
+ * @throws ToManyAttributeEntriesException
+ * if maximum
+ */
+ @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
+ Target updateControllerAttributes(@NotEmpty String controllerId, @NotNull Map attributes);
+
+ /**
+ * Refreshes the time of the last time the controller has been connected to
+ * the server.
+ *
+ * @param controllerId
+ * of the target to to update
+ * @param address
+ * the client address of the target, might be {@code null}
+ * @return the updated target
+ *
+ * @throws EntityNotFoundException
+ * if target with given ID could not be found
+ */
+ @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
+ Target updateLastTargetQuery(@NotEmpty String controllerId, URI address);
/**
* Refreshes the time of the last time the controller has been connected to
@@ -207,83 +247,12 @@ public class ControllerManagement {
* @return the updated target
*
*/
- @Modifying
- @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
- public TargetInfo updateLastTargetQuery(@NotNull final TargetInfo target, final URI address) {
+ @Transactional(isolation = Isolation.READ_UNCOMMITTED)
+ default TargetInfo updateLastTargetQuery(@NotNull final TargetInfo target, @NotNull final URI address) {
return updateTargetStatus(target, null, System.currentTimeMillis(), address);
}
- /**
- * Retrieves all {@link Action}s which are active and assigned to a
- * {@link Target}.
- *
- * @param target
- * the target to retrieve the actions from
- * @return a list of actions assigned to given target which are active
- */
- @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
- public List findActionByTargetAndActive(final Target target) {
- return actionRepository.findByTargetAndActiveOrderByIdAsc(target, true);
- }
-
- /**
- * Retrieves all {@link SoftwareModule}s which are assigned to the given
- * {@link DistributionSet}.
- *
- * @param distributionSet
- * the distribution set which should be assigned to the returned
- * {@link SoftwareModule}s
- * @return a list of {@link SoftwareModule}s assigned to given
- * {@code distributionSet}
- */
- @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
- public List findSoftwareModulesByDistributionSet(final DistributionSet distributionSet) {
- return softwareModuleRepository.findByAssignedTo(distributionSet);
- }
-
- /**
- * Get the {@link Action} entity for given actionId with all lazy
- * attributes.
- *
- * @param actionId
- * to be id of the action
- * @return the corresponding {@link Action}
- */
- @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
- public Action findActionWithDetails(@NotNull final Long actionId) {
- return actionRepository.findById(actionId);
- }
-
- /**
- * register new target in the repository (plug-and-play).
- *
- * @param targetid
- * reference
- * @param address
- * the client IP address of the target, might be {@code null}
- * @return target reference
- */
- @Modifying
- @Transactional(isolation = Isolation.READ_UNCOMMITTED)
- @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
- public Target findOrRegisterTargetIfItDoesNotexist(@NotEmpty final String targetid, final URI address) {
- final Specification spec = (targetRoot, query, cb) -> cb.equal(targetRoot.get(Target_.controllerId),
- targetid);
-
- Target target = targetRepository.findOne(spec);
-
- if (target == null) {
- target = new Target(targetid);
- target.setDescription("Plug and Play target: " + targetid);
- target.setName(targetid);
- return targetManagement.createTarget(target, TargetUpdateStatus.REGISTERED, System.currentTimeMillis(),
- address);
- }
-
- return updateLastTargetQuery(target.getTargetInfo(), address).getTarget();
- }
-
/**
* Update selective the target status of a given {@code target}.
*
@@ -300,313 +269,8 @@ public class ControllerManagement {
* the client address of the target, might be {@code null}
* @return the updated TargetInfo
*/
- @Modifying
- @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
- public TargetInfo updateTargetStatus(@NotNull final TargetInfo targetInfo, final TargetUpdateStatus status,
- final Long lastTargetQuery, final URI address) {
- final TargetInfo mtargetInfo = entityManager.merge(targetInfo);
- if (status != null) {
- mtargetInfo.setUpdateStatus(status);
- }
- if (lastTargetQuery != null) {
- mtargetInfo.setLastTargetQuery(lastTargetQuery);
- }
- if (address != null) {
- mtargetInfo.setAddress(address.toString());
- }
- return targetInfoRepository.save(mtargetInfo);
- }
+ TargetInfo updateTargetStatus(@NotNull TargetInfo targetInfo, TargetUpdateStatus status, Long lastTargetQuery,
+ URI address);
- /**
- * Adds an {@link ActionStatus} for a {@link UpdateAction} and cancels the
- * {@link UpdateAction} if necessary.
- *
- * @param actionStatus
- * to be updated
- * @param action
- * the status is for
- * @return the persisted {@link Action}
- *
- */
- @Modifying
- @Transactional(isolation = Isolation.READ_UNCOMMITTED)
- @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
- public Action addCancelActionStatus(@NotNull final ActionStatus actionStatus, final Action action) {
-
- checkForToManyStatusEntries(action);
- action.setStatus(actionStatus.getStatus());
-
- switch (actionStatus.getStatus()) {
- case WARNING:
- case ERROR:
- case RUNNING:
- break;
- case CANCELED:
- case FINISHED:
- // in case of successful cancellation we also report the success at
- // the canceled action itself.
- actionStatus.addMessage(
- ControllerManagement.SERVER_MESSAGE_PREFIX + "Cancellation completion is finished sucessfully.");
- deploymentManagement.successCancellation(action);
- break;
- case RETRIEVED:
- actionStatus.addMessage(ControllerManagement.SERVER_MESSAGE_PREFIX + "Cancellation request retrieved.");
- break;
- default:
- }
- actionRepository.save(action);
- actionStatusRepository.save(actionStatus);
-
- return action;
- }
-
- /**
- * Updates an {@link ActionStatus} for a {@link UpdateAction}.
- *
- * @param actionStatus
- * to be updated
- * @param action
- * the update is for
- * @return the persisted {@link Action}
- *
- * @throws EntityAlreadyExistsException
- * if a given entity already exists
- * @throws ToManyStatusEntriesException
- * if more than the allowed number of status entries are
- * inserted
- */
- @Modifying
- @Transactional(isolation = Isolation.READ_UNCOMMITTED)
- @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
- public Action addUpdateActionStatus(@NotNull final ActionStatus actionStatus, final Action action) {
-
- if (!action.isActive()) {
- LOG.debug("Update of actionStatus {} for action {} not possible since action not active anymore.",
- actionStatus.getId(), action.getId());
- return action;
- }
- return handleAddUpdateActionStatus(actionStatus, action);
- }
-
- /**
- * Sets {@link TargetUpdateStatus} based on given {@link ActionStatus}.
- *
- * @param actionStatus
- * @param action
- * @return
- */
- public Action handleAddUpdateActionStatus(final ActionStatus actionStatus, final Action action) {
- LOG.debug("addUpdateActionStatus for action {}", action.getId());
-
- final Action mergedAction = entityManager.merge(action);
- Target mergedTarget = mergedAction.getTarget();
- // check for a potential DOS attack
- checkForToManyStatusEntries(action);
-
- switch (actionStatus.getStatus()) {
- case ERROR:
- mergedTarget = deploymentManagement.updateTargetInfo(mergedTarget, TargetUpdateStatus.ERROR, false);
- handleErrorOnAction(mergedAction, mergedTarget);
- break;
- case FINISHED:
- handleFinishedAndStoreInTargetStatus(mergedTarget, mergedAction);
- break;
- case CANCELED:
- case WARNING:
- case RUNNING:
- deploymentManagement.updateTargetInfo(mergedTarget, TargetUpdateStatus.PENDING, false);
- break;
- default:
- break;
- }
-
- actionStatusRepository.save(actionStatus);
-
- LOG.debug("addUpdateActionStatus {} for target {} is finished.", action.getId(), mergedTarget.getId());
-
- return actionRepository.save(mergedAction);
- }
-
- private void handleErrorOnAction(final Action mergedAction, final Target mergedTarget) {
- mergedAction.setActive(false);
- mergedAction.setStatus(Status.ERROR);
- mergedTarget.setAssignedDistributionSet(null);
- targetManagement.updateTarget(mergedTarget);
- }
-
- private void checkForToManyStatusEntries(final Action action) {
- if (securityProperties.getDos().getMaxStatusEntriesPerAction() > 0) {
-
- final Long statusCount = actionStatusRepository.countByAction(action);
-
- if (statusCount >= securityProperties.getDos().getMaxStatusEntriesPerAction()) {
- LOG_DOS.error(
- "Potential denial of service (DOS) attack identfied. More status entries in the system than permitted ({})!",
- securityProperties.getDos().getMaxStatusEntriesPerAction());
- throw new ToManyStatusEntriesException(
- String.valueOf(securityProperties.getDos().getMaxStatusEntriesPerAction()));
- }
- }
- }
-
- private void handleFinishedAndStoreInTargetStatus(final Target target, final Action action) {
- action.setActive(false);
- action.setStatus(Status.FINISHED);
- final TargetInfo targetInfo = target.getTargetInfo();
- final DistributionSet ds = entityManager.merge(action.getDistributionSet());
- targetInfo.setInstalledDistributionSet(ds);
- if (target.getAssignedDistributionSet() != null && targetInfo.getInstalledDistributionSet() != null && target
- .getAssignedDistributionSet().getId().equals(targetInfo.getInstalledDistributionSet().getId())) {
- targetInfo.setUpdateStatus(TargetUpdateStatus.IN_SYNC);
- targetInfo.setInstallationDate(System.currentTimeMillis());
- } else {
- targetInfo.setUpdateStatus(TargetUpdateStatus.PENDING);
- targetInfo.setInstallationDate(System.currentTimeMillis());
- }
- targetInfoRepository.save(targetInfo);
- entityManager.detach(ds);
- }
-
- /**
- * Updates attributes of the controller.
- *
- * @param targetid
- * to update
- * @param data
- * to insert
- *
- * @return updated {@link Target}
- *
- * @throws EntityNotFoundException
- * if target that has to be updated could not be found
- * @throws ToManyAttributeEntriesException
- * if maximum
- */
- @Modifying
- @NotNull
- @Transactional(isolation = Isolation.READ_UNCOMMITTED)
- @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
- public Target updateControllerAttributes(@NotEmpty final String targetid, @NotNull final Map data) {
- final Target target = targetRepository.findByControllerId(targetid);
-
- if (target == null) {
- throw new EntityNotFoundException(targetid);
- }
-
- target.getTargetInfo().getControllerAttributes().putAll(data);
-
- if (target.getTargetInfo().getControllerAttributes().size() > securityProperties.getDos()
- .getMaxAttributeEntriesPerTarget()) {
- LOG_DOS.info("Target tries to insert more than the allowed number of entries ({}). DOS attack anticipated!",
- securityProperties.getDos().getMaxAttributeEntriesPerTarget());
- throw new ToManyAttributeEntriesException(
- String.valueOf(securityProperties.getDos().getMaxAttributeEntriesPerTarget()));
- }
-
- target.getTargetInfo().setLastTargetQuery(System.currentTimeMillis());
- target.getTargetInfo().setRequestControllerAttributes(false);
- return targetRepository.save(target);
- }
-
- /**
- * Registers retrieved status for given {@link Target} and {@link Action} if
- * it does not exist yet.
- *
- * @param action
- * to the handle status for
- * @param target
- * to the handle status for
- * @param message
- * for the status
- * @return the update action in case the status has been changed to
- * {@link Status#RETRIEVED}
- */
- @Modifying
- @Transactional(isolation = Isolation.READ_UNCOMMITTED)
- @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
- public Action registerRetrieved(final Action action, final String message) {
- return handleRegisterRetrieved(action, message);
- }
-
- /**
- * Registers retrieved status for given {@link Target} and {@link Action} if
- * it does not exist yet.
- *
- * @param action
- * to the handle status for
- * @param message
- * for the status
- * @return the updated action in case the status has been changed to
- * {@link Status#RETRIEVED}
- */
- public Action handleRegisterRetrieved(final Action action, final String message) {
- // 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.
- final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
- final CriteriaQuery