From 9bc0e74f47ef77aab024a52559fb11ad51dd8af0 Mon Sep 17 00:00:00 2001 From: Avgustin Marinov Date: Wed, 14 Feb 2024 20:59:34 +0200 Subject: [PATCH] [#1580] Software Module & Distribution Set lock: add lock at db level (#1643) 1. add _locked_ column in the tables 2. add _locked_ field to the JPA entities 3. add lock set/get at JPA level (with lock DS checking for complete) 4. along with that little reordering of code is made to make it more structured Signed-off-by: Marinov Avgustin --- .../hawkbit/exception/SpServerError.java | 2 +- .../repository/jpa/model/JpaArtifact.java | 8 +- .../jpa/model/JpaDistributionSet.java | 299 ++++++++---------- .../jpa/model/JpaSoftwareModule.java | 149 ++++----- .../DB2/V1_12_29__add_ds_sm_locked___DB2.sql | 2 + .../H2/V1_12_29__add_ds_sm_locked___H2.sql | 2 + .../V1_12_29__add_ds_sm_locked___MYSQL.sql | 2 + ...1_12_29__add_ds_sm_locked___POSTGRESQL.sql | 2 + ...1_12_29__add_ds_sm_locked___SQL_SERVER.sql | 2 + 9 files changed, 196 insertions(+), 272 deletions(-) create mode 100644 hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_29__add_ds_sm_locked___DB2.sql create mode 100644 hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_29__add_ds_sm_locked___H2.sql create mode 100644 hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_29__add_ds_sm_locked___MYSQL.sql create mode 100644 hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_29__add_ds_sm_locked___POSTGRESQL.sql create mode 100644 hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_29__add_ds_sm_locked___SQL_SERVER.sql diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerError.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerError.java index 48cd39417..3748475e7 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerError.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerError.java @@ -204,7 +204,7 @@ public enum SpServerError { * */ SP_DS_INCOMPLETE("hawkbit.server.error.distributionset.incomplete", - "Distribution set is assigned to a target that is incomplete (i.e. mandatory modules are missing)"), + "Distribution set is assigned/locked to a target that is incomplete (i.e. mandatory modules are missing)"), /** * diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaArtifact.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaArtifact.java index 723706b5a..1caee1b90 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaArtifact.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaArtifact.java @@ -83,9 +83,10 @@ public class JpaArtifact extends AbstractJpaTenantAwareBaseEntity implements Art */ public JpaArtifact(@NotEmpty final String sha1Hash, @NotNull final String filename, final SoftwareModule softwareModule) { - setSoftwareModule(softwareModule); this.sha1Hash = sha1Hash; this.filename = filename; + this.softwareModule = (JpaSoftwareModule) softwareModule; + this.softwareModule.addArtifact(this); } @Override @@ -130,11 +131,6 @@ public class JpaArtifact extends AbstractJpaTenantAwareBaseEntity implements Art return softwareModule; } - public final void setSoftwareModule(final SoftwareModule softwareModule) { - this.softwareModule = (JpaSoftwareModule) softwareModule; - this.softwareModule.addArtifact(this); - } - @Override public String getFilename() { return filename; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java index df13239a7..48f246fbd 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java @@ -9,6 +9,7 @@ */ package org.eclipse.hawkbit.repository.jpa.model; +import java.io.Serial; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -34,10 +35,15 @@ import jakarta.persistence.Table; import jakarta.persistence.UniqueConstraint; import jakarta.validation.constraints.NotNull; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; import org.eclipse.hawkbit.repository.event.remote.DistributionSetDeletedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetUpdatedEvent; import org.eclipse.hawkbit.repository.exception.DistributionSetTypeUndefinedException; +import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException; import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -56,8 +62,10 @@ import org.springframework.context.ApplicationEvent; /** * Jpa implementation of {@link DistributionSet}. - * */ +@NoArgsConstructor // Default constructor for JPA +@Getter +@ToString(callSuper = true) @Entity @Table(name = "sp_distribution_set", uniqueConstraints = { @UniqueConstraint(columnNames = { "name", "version", "tenant" }, name = "uk_distrib_set") }, indexes = { @@ -69,12 +77,16 @@ import org.springframework.context.ApplicationEvent; // sub entities @SuppressWarnings("squid:S2160") public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implements DistributionSet, EventAwareEntity { + + @Serial private static final long serialVersionUID = 1L; private static final String DELETED_PROPERTY = "deleted"; - @Column(name = "required_migration_step") - private boolean requiredMigrationStep; + @ManyToOne(fetch = FetchType.LAZY, optional = false, targetEntity = JpaDistributionSetType.class) + @JoinColumn(name = "ds_id", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_dstype_ds")) + @NotNull + private DistributionSetType type; @CascadeOnDelete @ManyToMany(targetEntity = JpaSoftwareModule.class, fetch = FetchType.LAZY) @@ -87,97 +99,126 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen @ManyToMany(targetEntity = JpaDistributionSetTag.class) @JoinTable(name = "sp_ds_dstag", joinColumns = { @JoinColumn(name = "ds", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_dstag_ds")) }, inverseJoinColumns = { - @JoinColumn(name = "TAG", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_dstag_tag")) }) + @JoinColumn(name = "TAG", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_dstag_tag")) }) private Set tags; - @Column(name = "deleted") - private boolean deleted; - - @OneToMany(mappedBy = "assignedDistributionSet", targetEntity = JpaTarget.class, fetch = FetchType.LAZY) - private List assignedToTargets; - - @OneToMany(mappedBy = "autoAssignDistributionSet", targetEntity = JpaTargetFilterQuery.class, fetch = FetchType.LAZY) - private List autoAssignFilters; - - @OneToMany(mappedBy = "installedDistributionSet", targetEntity = JpaTarget.class, fetch = FetchType.LAZY) - private List installedAtTargets; - - @OneToMany(mappedBy = "distributionSet", targetEntity = JpaAction.class, fetch = FetchType.LAZY) - private List actions; - + @ToString.Exclude @CascadeOnDelete @OneToMany(mappedBy = "distributionSet", fetch = FetchType.LAZY, targetEntity = JpaDistributionSetMetadata.class) private List metadata; - @ManyToOne(fetch = FetchType.LAZY, optional = false, targetEntity = JpaDistributionSetType.class) - @JoinColumn(name = "ds_id", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_dstype_ds")) - @NotNull - private DistributionSetType type; - @Column(name = "complete") private boolean complete; + @Column(name = "locked") + private boolean locked; + + @Column(name = "deleted") + private boolean deleted; + @Column(name = "valid") private boolean valid; - /** - * Default constructor. - */ - public JpaDistributionSet() { - // Default constructor for JPA - } + @Column(name = "required_migration_step") + private boolean requiredMigrationStep; + + @ToString.Exclude + @OneToMany(mappedBy = "autoAssignDistributionSet", targetEntity = JpaTargetFilterQuery.class, fetch = FetchType.LAZY) + private List autoAssignFilters; + + @ToString.Exclude + @Getter(AccessLevel.NONE) + @OneToMany(mappedBy = "assignedDistributionSet", targetEntity = JpaTarget.class, fetch = FetchType.LAZY) + private List assignedToTargets; + + @ToString.Exclude + @Getter(AccessLevel.NONE) + @OneToMany(mappedBy = "installedDistributionSet", targetEntity = JpaTarget.class, fetch = FetchType.LAZY) + private List installedAtTargets; + + @ToString.Exclude + @Getter(AccessLevel.NONE) + @OneToMany(mappedBy = "distributionSet", targetEntity = JpaAction.class, fetch = FetchType.LAZY) + private List actions; /** * Parameterized constructor. - * - * @param name - * of the {@link DistributionSet} - * @param version - * of the {@link DistributionSet} - * @param description - * of the {@link DistributionSet} - * @param type - * of the {@link DistributionSet} - * @param moduleList - * {@link SoftwareModule}s of the {@link DistributionSet} - * @param requiredMigrationStep - * of the {@link DistributionSet} */ public JpaDistributionSet(final String name, final String version, final String description, final DistributionSetType type, final Collection moduleList, final boolean requiredMigrationStep) { super(name, version, description); - this.requiredMigrationStep = requiredMigrationStep; - this.valid = true; this.type = type; + // modules shall be set before type.checkComplete call if (moduleList != null) { moduleList.forEach(this::addModule); } if (this.type != null) { complete = this.type.checkComplete(this); } + + this.valid = true; + this.requiredMigrationStep = requiredMigrationStep; } /** * Parameterized constructor. - * - * @param name - * of the {@link DistributionSet} - * @param version - * of the {@link DistributionSet} - * @param description - * of the {@link DistributionSet} - * @param type - * of the {@link DistributionSet} - * @param moduleList - * {@link SoftwareModule}s of the {@link DistributionSet} */ public JpaDistributionSet(final String name, final String version, final String description, final DistributionSetType type, final Collection moduleList) { this(name, version, description, type, moduleList, false); } + public void setType(final DistributionSetType type) { + this.type = type; + } + + @Override + public Set getModules() { + if (modules == null) { + return Collections.emptySet(); + } + + return Collections.unmodifiableSet(modules); + } + + public boolean addModule(final SoftwareModule softwareModule) { + if (modules == null) { + modules = new HashSet<>(); + } + + checkTypeCompatability(softwareModule); + + final Optional found = modules.stream() + .filter(module -> module.getId().equals(softwareModule.getId())).findAny(); + + if (found.isPresent()) { + return false; + } + + final long already = modules.stream() + .filter(module -> module.getType().getKey().equals(softwareModule.getType().getKey())).count(); + + if (already >= softwareModule.getType().getMaxAssignments()) { + modules.stream().filter(module -> module.getType().getKey().equals(softwareModule.getType().getKey())) + .findAny().ifPresent(modules::remove); + } + + if (modules.add(softwareModule)) { + complete = type.checkComplete(this); + return true; + } + + return false; + } + + public void removeModule(final SoftwareModule softwareModule) { + if (modules != null && modules.removeIf(m -> m.getId().equals(softwareModule.getId()))) { + complete = type.checkComplete(this); + } + } + public Set getTags() { if (tags == null) { return Collections.emptySet(); @@ -202,11 +243,6 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen return tags.remove(tag); } - @Override - public boolean isDeleted() { - return deleted; - } - public List getMetadata() { if (metadata == null) { return Collections.emptyList(); @@ -215,6 +251,25 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen return Collections.unmodifiableList(metadata); } + public void lock() { + if (!complete) { + throw new IncompleteDistributionSetException("Could not be locked while incomplete!"); + } + locked = true; + } + + public void setDeleted(final boolean deleted) { + this.deleted = deleted; + } + + public void invalidate() { + this.valid = false; + } + + public void setRequiredMigrationStep(final boolean isRequiredMigrationStep) { + requiredMigrationStep = isRequiredMigrationStep; + } + public List getActions() { if (actions == null) { return Collections.emptyList(); @@ -223,112 +278,6 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen return Collections.unmodifiableList(actions); } - @Override - public boolean isRequiredMigrationStep() { - return requiredMigrationStep; - } - - public DistributionSet setDeleted(final boolean deleted) { - this.deleted = deleted; - return this; - } - - public DistributionSet setRequiredMigrationStep(final boolean isRequiredMigrationStep) { - requiredMigrationStep = isRequiredMigrationStep; - return this; - } - - @Override - public List getAutoAssignFilters() { - return autoAssignFilters; - } - - @Override - public String toString() { - return "DistributionSet [getName()=" + getName() + ", getOptLockRevision()=" + getOptLockRevision() - + ", getId()=" + getId() + "]"; - } - - @Override - public Set getModules() { - if (modules == null) { - return Collections.emptySet(); - } - - return Collections.unmodifiableSet(modules); - } - - public boolean addModule(final SoftwareModule softwareModule) { - if (modules == null) { - modules = new HashSet<>(); - } - - checkTypeCompatability(softwareModule); - - final Optional found = modules.stream() - .filter(module -> module.getId().equals(softwareModule.getId())).findAny(); - - if (found.isPresent()) { - return false; - } - - final long allready = modules.stream() - .filter(module -> module.getType().getKey().equals(softwareModule.getType().getKey())).count(); - - if (allready >= softwareModule.getType().getMaxAssignments()) { - modules.stream().filter(module -> module.getType().getKey().equals(softwareModule.getType().getKey())) - .findAny().ifPresent(modules::remove); - } - - if (modules.add(softwareModule)) { - complete = type.checkComplete(this); - return true; - } - - return false; - } - - private void checkTypeCompatability(final SoftwareModule softwareModule) { - // we cannot allow that modules are added without a type defined - if (type == null) { - throw new DistributionSetTypeUndefinedException(); - } - - // check if it is allowed to such a module to this DS type - if (!type.containsModuleType(softwareModule.getType())) { - throw new UnsupportedSoftwareModuleForThisDistributionSetException(); - } - } - - public void removeModule(final SoftwareModule softwareModule) { - if (modules != null && modules.removeIf(m -> m.getId().equals(softwareModule.getId()))) { - complete = type.checkComplete(this); - } - } - - @Override - public DistributionSetType getType() { - return type; - } - - public void setType(final DistributionSetType type) { - this.type = type; - } - - @Override - public boolean isComplete() { - return complete; - } - - @Override - public boolean isValid() { - return valid; - } - - public void invalidate() { - this.valid = false; - } - @Override public void fireCreateEvent(final DescriptorEvent descriptorEvent) { publishEventWithEventPublisher( @@ -337,7 +286,6 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen @Override public void fireUpdateEvent(final DescriptorEvent descriptorEvent) { - publishEventWithEventPublisher( new DistributionSetUpdatedEvent(this, EventPublisherHolder.getInstance().getApplicationId(), complete)); @@ -353,6 +301,18 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen EventPublisherHolder.getInstance().getApplicationId())); } + private void checkTypeCompatability(final SoftwareModule softwareModule) { + // we cannot allow that modules are added without a type defined + if (type == null) { + throw new DistributionSetTypeUndefinedException(); + } + + // check if it is allowed to such a module to this DS type + if (!type.containsModuleType(softwareModule.getType())) { + throw new UnsupportedSoftwareModuleForThisDistributionSetException(); + } + } + private static void publishEventWithEventPublisher(final ApplicationEvent event) { EventPublisherHolder.getInstance().getEventPublisher().publishEvent(event); } @@ -366,5 +326,4 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen return changes.stream().anyMatch(changeRecord -> DELETED_PROPERTY.equals(changeRecord.getAttribute()) && Boolean.parseBoolean(changeRecord.getNewValue().toString())); } - -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModule.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModule.java index 57e1b5d20..188b59890 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModule.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModule.java @@ -9,10 +9,10 @@ */ package org.eclipse.hawkbit.repository.jpa.model; +import java.io.Serial; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.stream.Collectors; import jakarta.persistence.CascadeType; import jakarta.persistence.Column; @@ -32,6 +32,10 @@ import jakarta.persistence.UniqueConstraint; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; import org.eclipse.hawkbit.repository.event.remote.SoftwareModuleDeletedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleUpdatedEvent; @@ -49,8 +53,10 @@ import org.eclipse.persistence.sessions.changesets.ObjectChangeSet; /** * Base Software Module that is supported by OS level provisioning mechanism on * the edge controller, e.g. OS, JVM, AgentHub. - * */ +@NoArgsConstructor // Default constructor for JPA +@Getter +@ToString(callSuper = true) @Entity @Table(name = "sp_base_software_module", uniqueConstraints = @UniqueConstraint(columnNames = { "module_type", "name", "version", "tenant" }, name = "uk_base_sw_mod"), indexes = { @@ -62,6 +68,8 @@ import org.eclipse.persistence.sessions.changesets.ObjectChangeSet; // sub entities @SuppressWarnings("squid:S2160") public class JpaSoftwareModule extends AbstractJpaNamedVersionedEntity implements SoftwareModule, EventAwareEntity { + + @Serial private static final long serialVersionUID = 1L; private static final String DELETED_PROPERTY = "deleted"; @@ -72,64 +80,43 @@ public class JpaSoftwareModule extends AbstractJpaNamedVersionedEntity implement private JpaSoftwareModuleType type; @CascadeOnDelete - @ManyToMany(mappedBy = "modules", targetEntity = JpaDistributionSet.class, fetch = FetchType.LAZY) - private List assignedTo; - - @Column(name = "deleted") - private boolean deleted; + @OneToMany(fetch = FetchType.LAZY, mappedBy = "softwareModule", cascade = { + CascadeType.PERSIST }, targetEntity = JpaArtifact.class, orphanRemoval = true) + private List artifacts; @Column(name = "vendor", nullable = true, length = SoftwareModule.VENDOR_MAX_SIZE) @Size(max = SoftwareModule.VENDOR_MAX_SIZE) private String vendor; - @CascadeOnDelete - @OneToMany(fetch = FetchType.LAZY, mappedBy = "softwareModule", cascade = { - CascadeType.PERSIST }, targetEntity = JpaArtifact.class, orphanRemoval = true) - private List artifacts; - + @ToString.Exclude @CascadeOnDelete @OneToMany(mappedBy = "softwareModule", fetch = FetchType.LAZY, targetEntity = JpaSoftwareModuleMetadata.class) private List metadata; + @Column(name = "locked") + private boolean locked; + + @Column(name = "deleted") + private boolean deleted; + @Column(name = "encrypted") private boolean encrypted; - /** - * Default constructor. - */ - public JpaSoftwareModule() { - // Default constructor for JPA - } + @ToString.Exclude + @Getter(AccessLevel.NONE) + @CascadeOnDelete + @ManyToMany(mappedBy = "modules", targetEntity = JpaDistributionSet.class, fetch = FetchType.LAZY) + private List assignedTo; /** - * parameterized constructor. - * - * @param type - * of the {@link SoftwareModule} - * @param name - * abstract name of the {@link SoftwareModule} - * @param version - * of the {@link SoftwareModule} + * Parameterized constructor. */ public JpaSoftwareModule(final SoftwareModuleType type, final String name, final String version) { this(type, name, version, null, null, false); } /** - * parameterized constructor. - * - * @param type - * of the {@link SoftwareModule} - * @param name - * abstract name of the {@link SoftwareModule} - * @param version - * of the {@link SoftwareModule} - * @param description - * of the {@link SoftwareModule} - * @param vendor - * of the {@link SoftwareModule} - * @param encrypted - * encryption flag of the {@link SoftwareModule} + * Parameterized constructor. */ public JpaSoftwareModule(final SoftwareModuleType type, final String name, final String version, final String description, final String vendor, final boolean encrypted) { @@ -139,8 +126,21 @@ public class JpaSoftwareModule extends AbstractJpaNamedVersionedEntity implement this.encrypted = encrypted; } + public void setType(final JpaSoftwareModuleType type) { + this.type = type; + } + + @Override + public List getArtifacts() { + if (artifacts == null) { + return Collections.emptyList(); + } + + return Collections.unmodifiableList(artifacts); + } + public void addArtifact(final Artifact artifact) { - if (null == artifacts) { + if (artifacts == null) { artifacts = new ArrayList<>(4); artifacts.add((JpaArtifact) artifact); return; @@ -152,25 +152,7 @@ public class JpaSoftwareModule extends AbstractJpaNamedVersionedEntity implement } /** - * @return the artifacts - */ - @Override - public List getArtifacts() { - if (artifacts == null) { - return Collections.emptyList(); - } - - return Collections.unmodifiableList(artifacts); - } - - @Override - public String getVendor() { - return vendor; - } - - /** - * @param artifact - * is removed from the assigned {@link Artifact}s. + * @param artifact is removed from the assigned {@link Artifact}s. */ public void removeArtifact(final Artifact artifact) { if (artifacts != null) { @@ -182,14 +164,8 @@ public class JpaSoftwareModule extends AbstractJpaNamedVersionedEntity implement this.vendor = vendor; } - @Override - public SoftwareModuleType getType() { - return type; - } - - @Override - public boolean isDeleted() { - return deleted; + public void lock() { + locked = true; } /** @@ -203,15 +179,6 @@ public class JpaSoftwareModule extends AbstractJpaNamedVersionedEntity implement this.deleted = deleted; } - public void setType(final JpaSoftwareModuleType type) { - this.type = type; - } - - @Override - public boolean isEncrypted() { - return encrypted; - } - /** * Marks this software module as encrypted. * @@ -223,13 +190,6 @@ public class JpaSoftwareModule extends AbstractJpaNamedVersionedEntity implement this.encrypted = encrypted; } - @Override - public String toString() { - return "SoftwareModule [deleted=" + isDeleted() + ", encrypted=" + isEncrypted() + ", name=" + getName() - + ", version=" + getVersion() + ", revision=" + getOptLockRevision() + ", Id=" + getId() + ", type=" - + getType().getName() + "]"; - } - @Override public List getAssignedTo() { if (assignedTo == null) { @@ -256,20 +216,19 @@ public class JpaSoftwareModule extends AbstractJpaNamedVersionedEntity implement } } - private static boolean isSoftDeleted(final DescriptorEvent event) { - final ObjectChangeSet changeSet = ((UpdateObjectQuery) event.getQuery()).getObjectChangeSet(); - final List changes = changeSet.getChanges().stream() - .filter(DirectToFieldChangeRecord.class::isInstance).map(DirectToFieldChangeRecord.class::cast) - .collect(Collectors.toList()); - - return changes.stream().anyMatch(changeRecord -> DELETED_PROPERTY.equals(changeRecord.getAttribute()) - && Boolean.parseBoolean(changeRecord.getNewValue().toString())); - } - @Override public void fireDeleteEvent(final DescriptorEvent descriptorEvent) { EventPublisherHolder.getInstance().getEventPublisher().publishEvent(new SoftwareModuleDeletedEvent(getTenant(), getId(), getClass(), EventPublisherHolder.getInstance().getApplicationId())); } -} + private static boolean isSoftDeleted(final DescriptorEvent event) { + final ObjectChangeSet changeSet = ((UpdateObjectQuery) event.getQuery()).getObjectChangeSet(); + final List changes = changeSet.getChanges().stream() + .filter(DirectToFieldChangeRecord.class::isInstance).map(DirectToFieldChangeRecord.class::cast) + .toList(); + + return changes.stream().anyMatch(changeRecord -> DELETED_PROPERTY.equals(changeRecord.getAttribute()) + && Boolean.parseBoolean(changeRecord.getNewValue().toString())); + } +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_29__add_ds_sm_locked___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_29__add_ds_sm_locked___DB2.sql new file mode 100644 index 000000000..c5c0de6fb --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_29__add_ds_sm_locked___DB2.sql @@ -0,0 +1,2 @@ +ALTER TABLE sp_base_software_module ADD COLUMN locked BOOLEAN NOT NULL DEFAULT true; +ALTER TABLE sp_distribution_set ADD COLUMN locked BOOLEAN NOT NULL DEFAULT true; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_29__add_ds_sm_locked___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_29__add_ds_sm_locked___H2.sql new file mode 100644 index 000000000..c5c0de6fb --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_12_29__add_ds_sm_locked___H2.sql @@ -0,0 +1,2 @@ +ALTER TABLE sp_base_software_module ADD COLUMN locked BOOLEAN NOT NULL DEFAULT true; +ALTER TABLE sp_distribution_set ADD COLUMN locked BOOLEAN NOT NULL DEFAULT true; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_29__add_ds_sm_locked___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_29__add_ds_sm_locked___MYSQL.sql new file mode 100644 index 000000000..c5c0de6fb --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_12_29__add_ds_sm_locked___MYSQL.sql @@ -0,0 +1,2 @@ +ALTER TABLE sp_base_software_module ADD COLUMN locked BOOLEAN NOT NULL DEFAULT true; +ALTER TABLE sp_distribution_set ADD COLUMN locked BOOLEAN NOT NULL DEFAULT true; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_29__add_ds_sm_locked___POSTGRESQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_29__add_ds_sm_locked___POSTGRESQL.sql new file mode 100644 index 000000000..c5c0de6fb --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/POSTGRESQL/V1_12_29__add_ds_sm_locked___POSTGRESQL.sql @@ -0,0 +1,2 @@ +ALTER TABLE sp_base_software_module ADD COLUMN locked BOOLEAN NOT NULL DEFAULT true; +ALTER TABLE sp_distribution_set ADD COLUMN locked BOOLEAN NOT NULL DEFAULT true; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_29__add_ds_sm_locked___SQL_SERVER.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_29__add_ds_sm_locked___SQL_SERVER.sql new file mode 100644 index 000000000..946d0b8e0 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_29__add_ds_sm_locked___SQL_SERVER.sql @@ -0,0 +1,2 @@ +ALTER TABLE sp_base_software_module ADD locked BIT NOT NULL DEFAULT 1; +ALTER TABLE sp_distribution_set ADD locked BIT NOT NULL DEFAULT 1; \ No newline at end of file