diff --git a/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactFilesystemRepository.java b/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactFilesystemRepository.java index ef8ff84b8..f346c1d14 100644 --- a/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactFilesystemRepository.java +++ b/hawkbit-artifact-repository-filesystem/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactFilesystemRepository.java @@ -106,4 +106,8 @@ public class ArtifactFilesystemRepository extends AbstractArtifactRepository { FileUtils.deleteQuietly(Paths.get(artifactResourceProperties.getPath(), sanitizeTenant(tenant)).toFile()); } + @Override + public boolean existsByTenantAndSha1(final String tenant, final String sha1) { + return getFile(tenant, sha1).exists(); + } } diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/ApiType.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/ApiType.java index 986bef476..e683b420b 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/ApiType.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/ApiType.java @@ -22,5 +22,5 @@ public enum ApiType { /** * Support for Direct Device Integration API. */ - DDI; + DDI } diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactRepository.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactRepository.java index 527b7539d..fc2a5f8db 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactRepository.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactRepository.java @@ -84,4 +84,16 @@ public interface ArtifactRepository { * to erase */ void deleteByTenant(@NotEmpty String tenant); + + /** + * Checks if an artifact exists for a given tenant by its sha1 hash + * + * @param tenant + * the tenant + * @param sha1Hash + * the sha1-hash of the file to lookup. + * + * @return the boolean whether the atrifact exists or not + */ + boolean existsByTenantAndSha1(@NotEmpty String tenant, @NotEmpty String sha1Hash); } diff --git a/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/amqp/api/EventTopic.java b/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/amqp/api/EventTopic.java index 123f564ae..480a20302 100644 --- a/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/amqp/api/EventTopic.java +++ b/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/amqp/api/EventTopic.java @@ -46,6 +46,6 @@ public enum EventTopic { /** * Topic to send multiple actions to the device. */ - MULTI_ACTION; + MULTI_ACTION } diff --git a/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/amqp/api/MessageType.java b/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/amqp/api/MessageType.java index 6c60f8c1b..64cb28407 100644 --- a/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/amqp/api/MessageType.java +++ b/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/amqp/api/MessageType.java @@ -37,6 +37,6 @@ public enum MessageType { /** * DMF receiver health check reponse type. */ - PING_RESPONSE; + PING_RESPONSE } diff --git a/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfActionStatus.java b/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfActionStatus.java index a833ee0e7..cdd675c3d 100644 --- a/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfActionStatus.java +++ b/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfActionStatus.java @@ -64,5 +64,5 @@ public enum DmfActionStatus { /** * Action has been downloaded for this target. */ - DOWNLOADED; + DOWNLOADED } diff --git a/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfUpdateMode.java b/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfUpdateMode.java index 7c204f998..52bfcf7ca 100644 --- a/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfUpdateMode.java +++ b/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfUpdateMode.java @@ -29,6 +29,6 @@ public enum DmfUpdateMode { /** * Removal update strategy */ - REMOVE; + REMOVE } diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java index b03b3d133..45b05718f 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java @@ -77,7 +77,7 @@ public interface ArtifactManagement { * @param artifactSha1Hash * no longer needed * @param moduleId - * the garbage colelction call is made for + * the garbage collection call is made for * * @return true if an binary was actually garbage collected */ diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Action.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Action.java index bf2e7d505..456e719b4 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Action.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Action.java @@ -150,7 +150,7 @@ public interface Action extends TenantAwareBaseEntity { * Status enum declaration! * */ - public enum Status { + enum Status { /** * Action is finished successfully for this target. */ @@ -206,14 +206,14 @@ public interface Action extends TenantAwareBaseEntity { * Action has been downloaded by the target and waiting for update to * start. */ - DOWNLOADED; + DOWNLOADED } /** * The action type for this action relation. * */ - public enum ActionType { + enum ActionType { /** * Forced action execution. Target is advised to executed immediately. */ @@ -234,7 +234,7 @@ public interface Action extends TenantAwareBaseEntity { /** * Target is only advised to download, but not install */ - DOWNLOAD_ONLY; + DOWNLOAD_ONLY } /** diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Rollout.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Rollout.java index c8e8eded6..5fac43173 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Rollout.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Rollout.java @@ -106,7 +106,7 @@ public interface Rollout extends NamedEntity { * State machine for rollout. * */ - public enum RolloutStatus { + enum RolloutStatus { /** * Rollouts is being created. @@ -181,7 +181,7 @@ public interface Rollout extends NamedEntity { * @deprecated legacy status is not used anymore */ @Deprecated - ERROR_STARTING; + ERROR_STARTING } /** diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetUpdateStatus.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetUpdateStatus.java index 168133e37..b6404c6f8 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetUpdateStatus.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetUpdateStatus.java @@ -40,5 +40,5 @@ public enum TargetUpdateStatus { /** * Controller registered at SP but no {@link DistributionSet} assigned. */ - REGISTERED; + REGISTERED } diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/event/BusProtoStuffMessageConverter.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/event/BusProtoStuffMessageConverter.java index 8554303ae..7884e9808 100644 --- a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/event/BusProtoStuffMessageConverter.java +++ b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/event/BusProtoStuffMessageConverter.java @@ -122,7 +122,7 @@ public class BusProtoStuffMessageConverter extends AbstractMessageConverter { } private static byte[] writeContent(final Object payload) { - final Class serializeClass = payload.getClass(); + final Class serializeClass = payload.getClass(); @SuppressWarnings("unchecked") final Schema schema = (Schema) RuntimeSchema.getSchema(serializeClass); final LinkedBuffer buffer = LinkedBuffer.allocate(); @@ -137,7 +137,7 @@ public class BusProtoStuffMessageConverter extends AbstractMessageConverter { } @SuppressWarnings("unchecked") final Schema schema = (Schema) RuntimeSchema - .getSchema((Class) EventType.class); + .getSchema((Class) EventType.class); final LinkedBuffer buffer = LinkedBuffer.allocate(); return ProtobufIOUtil.toByteArray(clazzEventType, schema, buffer); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaArtifactManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaArtifactManagement.java index e3568cd96..137651851 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaArtifactManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaArtifactManagement.java @@ -40,6 +40,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; import org.springframework.validation.annotation.Validated; /** @@ -98,20 +99,35 @@ public class JpaArtifactManagement implements ArtifactManagement { public Artifact create(final ArtifactUpload artifactUpload) { final String filename = artifactUpload.getFilename(); final long moduleId = artifactUpload.getModuleId(); - AbstractDbArtifact result = null; final SoftwareModule softwareModule = getModuleAndThrowExceptionIfThatFails(moduleId); - final Artifact existing = checkForExistingArtifact(filename, artifactUpload.overrideExisting(), - softwareModule); + final Artifact existing = checkForExistingArtifact(filename, artifactUpload.overrideExisting(), softwareModule); assertArtifactQuota(moduleId, 1); assertMaxArtifactSizeQuota(filename, moduleId, artifactUpload.getFilesize()); assertMaxArtifactStorageQuota(filename, artifactUpload.getFilesize()); + return getOrCreateArtifact(artifactUpload) + .map(artifact -> storeArtifactMetadata(softwareModule, filename, artifact, existing)) + .orElse(null); + } + + private Optional getOrCreateArtifact(final ArtifactUpload artifactUpload) { + final String providedSha1Sum = artifactUpload.getProvidedSha1Sum(); + AbstractDbArtifact artifact = null; + + if (!StringUtils.isEmpty(providedSha1Sum)) { + artifact = artifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), providedSha1Sum); + } + artifact = (artifact == null) ? storeArtifact(artifactUpload) : artifact; + return Optional.ofNullable(artifact); + } + + private AbstractDbArtifact storeArtifact(final ArtifactUpload artifactUpload) { try { - result = artifactRepository.store(tenantAware.getCurrentTenant(), artifactUpload.getInputStream(), filename, - artifactUpload.getContentType(), + return artifactRepository.store(tenantAware.getCurrentTenant(), artifactUpload.getInputStream(), + artifactUpload.getFilename(), artifactUpload.getContentType(), new DbArtifactHash(artifactUpload.getProvidedSha1Sum(), artifactUpload.getProvidedMd5Sum())); } catch (final ArtifactStoreException e) { throw new ArtifactUploadFailedException(e); @@ -122,11 +138,6 @@ public class JpaArtifactManagement implements ArtifactManagement { throw new InvalidMD5HashException(e.getMessage(), e); } } - if (result == null) { - return null; - } - - return storeArtifactMetadata(softwareModule, filename, result, existing); } private void assertArtifactQuota(final long id, final int requested) { @@ -166,12 +177,12 @@ public class JpaArtifactManagement implements ArtifactManagement { @Retryable(include = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) public boolean clearArtifactBinary(final String sha1Hash, final long moduleId) { - - if (localArtifactRepository.existsWithSha1HashAndSoftwareModuleIdIsNot(sha1Hash, moduleId)) { + final long count = localArtifactRepository.countBySha1HashAndTenantAndSoftwareModuleDeletedIsFalse(sha1Hash, + tenantAware.getCurrentTenant()); + if (count > 1) { // there are still other artifacts that need the binary return false; } - try { LOG.debug("deleting artifact from repository {}", sha1Hash); artifactRepository.deleteBySha1(tenantAware.getCurrentTenant(), sha1Hash); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/LocalArtifactRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/LocalArtifactRepository.java index 51d6e5767..86ea6766c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/LocalArtifactRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/LocalArtifactRepository.java @@ -56,19 +56,18 @@ public interface LocalArtifactRepository extends BaseEntityRepository findBySha1Hash(String sha1Hash); /** - * Verifies if an artifact exists that has given hash and is still related - * to a {@link SoftwareModule} other than a given one and not - * {@link SoftwareModule#isDeleted()}. - * + * Counts current elements based on the sha1 and tenant, as well as having + * the {@link SoftwareModule} property 'deleted' with value 'false + * * @param sha1 - * to search for - * @param moduleId - * to ignore in relationship check + * the sha1 of the {@link Artifact} + * @param tenant + * the current tenant * - * @return true if such an artifact exists + * @return the count of the elements */ - @Query("SELECT CASE WHEN COUNT(a)>0 THEN 'true' ELSE 'false' END FROM JpaArtifact a WHERE a.sha1Hash = :sha1 AND a.softwareModule.id != :moduleId AND a.softwareModule.deleted = 0") - boolean existsWithSha1HashAndSoftwareModuleIdIsNot(@Param("sha1") String sha1, @Param("moduleId") Long moduleId); + long countBySha1HashAndTenantAndSoftwareModuleDeletedIsFalse(@Param("sha1") String sha1, + @Param("tenant") String tenant); /** * Searches for a {@link Artifact} based on given gridFsFileName. diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtility.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtility.java index 9e176b256..a23a382c2 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtility.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtility.java @@ -469,7 +469,7 @@ public final class RSQLUtility { // values JPA can do it by it's own but not for classes like enums. // So we need to transform the given value string into the enum // class. - final Class javaType = fieldPath.getJavaType(); + final Class javaType = fieldPath.getJavaType(); if (javaType != null && javaType.isEnum()) { return transformEnumValue(node, value, javaType); } @@ -485,7 +485,7 @@ public final class RSQLUtility { } private Object convertBooleanValue(final ComparisonNode node, final String value, - final Class javaType) { + final Class javaType) { try { return simpleTypeConverter.convertIfNecessary(value, javaType); } catch (final TypeMismatchException e) { @@ -513,7 +513,7 @@ public final class RSQLUtility { // https://jira.sonarsource.com/browse/SONARJAVA-1478 @SuppressWarnings({ "rawtypes", "unchecked", "squid:S2095" }) private static Object transformEnumValue(final ComparisonNode node, final String value, - final Class javaType) { + final Class javaType) { final Class tmpEnumType = (Class) javaType; try { return Enum.valueOf(tmpEnumType, value.toUpperCase()); @@ -680,13 +680,10 @@ public final class RSQLUtility { final char escapeChar) { final String escaped; - switch (database) { - case SQL_SERVER: + if (database == Database.SQL_SERVER) { escaped = transformedValue.replace("%", "[%]").replace("_", "[_]"); - break; - default: + } else { escaped = transformedValue.replace("%", escapeChar + "%").replace("_", escapeChar + "_"); - break; } return escaped.replace(LIKE_WILDCARD, '%'); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ArtifactManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ArtifactManagementTest.java index 9dce62ddd..da27566cb 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ArtifactManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ArtifactManagementTest.java @@ -17,13 +17,15 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URISyntaxException; -import java.security.NoSuchAlgorithmException; import java.util.List; +import java.util.Optional; +import java.util.concurrent.Callable; import javax.validation.ConstraintViolationException; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.RandomStringUtils; +import org.eclipse.hawkbit.artifact.repository.model.AbstractDbArtifact; import org.eclipse.hawkbit.im.authentication.SpPermission; import org.eclipse.hawkbit.repository.ArtifactManagement; import org.eclipse.hawkbit.repository.event.remote.SoftwareModuleDeletedEvent; @@ -38,6 +40,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.test.matcher.Expect; import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents; import org.eclipse.hawkbit.repository.test.util.HashGeneratorUtils; +import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule; import org.eclipse.hawkbit.repository.test.util.WithUser; import org.junit.Test; @@ -98,7 +101,7 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { @Test @Description("Test if a local artifact can be created by API including metadata.") - public void createArtifact() throws NoSuchAlgorithmException, IOException { + public void createArtifact() throws IOException { // check baseline assertThat(softwareModuleRepository.findAll()).hasSize(0); @@ -162,7 +165,7 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { @Test @Description("Verifies that the quota specifying the maximum number of artifacts per software module is enforced.") - public void createArtifactsUntilQuotaIsExceeded() throws NoSuchAlgorithmException, IOException { + public void createArtifactsUntilQuotaIsExceeded() throws IOException { // create a software module final long smId = softwareModuleRepository.save(new JpaSoftwareModule(osType, "sm1", "1.0", null, null)) @@ -193,7 +196,7 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { @Test @Description("Verifies that the quota specifying the maximum artifact storage is enforced (across software modules).") - public void createArtifactsUntilStorageQuotaIsExceeded() throws NoSuchAlgorithmException, IOException { + public void createArtifactsUntilStorageQuotaIsExceeded() throws IOException { // create as many small artifacts as possible w/o violating the storage // quota @@ -224,7 +227,7 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { @Test @Description("Verifies that the quota specifying the maximum artifact storage is enforced (across software modules).") - public void createArtifactWhichExceedsMaxStorage() throws NoSuchAlgorithmException, IOException { + public void createArtifactWhichExceedsMaxStorage() throws IOException { // create one artifact which exceeds the storage quota at once final long maxBytes = quotaManagement.getMaxArtifactStorage(); @@ -236,7 +239,7 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { @Test @Description("Verifies that you cannot create artifacts which exceed the configured maximum size.") - public void createArtifactFailsIfTooLarge() throws NoSuchAlgorithmException, IOException { + public void createArtifactFailsIfTooLarge() { // create a software module final JpaSoftwareModule sm1 = softwareModuleRepository @@ -250,7 +253,7 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { @Test @Description("Tests hard delete directly on repository.") - public void hardDeleteSoftwareModule() throws NoSuchAlgorithmException, IOException { + public void hardDeleteSoftwareModule() throws IOException { final JpaSoftwareModule sm = softwareModuleRepository .save(new JpaSoftwareModule(osType, "name 1", "version 1", null, null)); @@ -268,12 +271,10 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { * . * * @throws IOException - * @throws NoSuchAlgorithmException */ @Test @Description("Tests the deletion of a local artifact including metadata.") - public void deleteArtifact() throws NoSuchAlgorithmException, IOException { - + public void deleteArtifact() throws IOException { final JpaSoftwareModule sm = softwareModuleRepository .save(new JpaSoftwareModule(osType, "name 1", "version 1", null, null)); final JpaSoftwareModule sm2 = softwareModuleRepository @@ -304,6 +305,8 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { artifactManagement.delete(artifact1.getId()); + assertThat(artifactRepository.findAll()).hasSize(1); + assertThat( binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), artifact1.getSha1Hash())) .isNull(); @@ -323,7 +326,7 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { @Test @Description("Test the deletion of an artifact metadata where the binary is still linked to another " + "metadata element. The expected result is that the metadata is deleted but the binary kept.") - public void deleteDuplicateArtifacts() throws NoSuchAlgorithmException, IOException { + public void deleteDuplicateArtifacts() throws IOException { final JpaSoftwareModule sm = softwareModuleRepository .save(new JpaSoftwareModule(osType, "name 1", "version 1", null, null)); @@ -347,21 +350,92 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { assertThat( binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), artifact1.getSha1Hash())) .isNotNull(); + artifactManagement.delete(artifact1.getId()); assertThat( binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), artifact1.getSha1Hash())) .isNotNull(); + assertThat(artifactRepository.findAll()).hasSize(1); + assertThat(artifactRepository.existsById(artifact1.getId())).isFalse(); artifactManagement.delete(artifact2.getId()); assertThat( binaryArtifactRepository.getArtifactBySha1(tenantAware.getCurrentTenant(), artifact1.getSha1Hash())) .isNull(); + assertThat(artifactRepository.findAll()).hasSize(0); } } + @Test + @Description("Verifies that you cannot delete an artifact which exists with the same hash, in the same tenant and the SoftwareModule is not deleted .") + public void deleteArtifactWithSameHashAndSoftwareModuleIsNotDeletedInSameTenants() throws IOException { + + final JpaSoftwareModule sm = softwareModuleRepository + .save(new JpaSoftwareModule(osType, "name 1", "version 1", null, null)); + final JpaSoftwareModule sm2 = softwareModuleRepository + .save(new JpaSoftwareModule(osType, "name 2", "version 2", null, null)); + + final int artifactSize = 5 * 1024; + final byte[] randomBytes = randomBytes(artifactSize); + + try (final InputStream inputStream1 = new ByteArrayInputStream(randomBytes); + final InputStream inputStream2 = new ByteArrayInputStream(randomBytes)) { + + final Artifact artifact1 = createArtifactForSoftwareModule("file1", sm.getId(), artifactSize, inputStream1); + final Artifact artifact2 = createArtifactForSoftwareModule("file2", sm2.getId(), artifactSize, + inputStream2); + + assertEqualFileContents(artifactManagement.loadArtifactBinary(artifact2.getSha1Hash()), randomBytes); + + assertThat(artifactRepository.findAll()).hasSize(2); + + assertThat(artifact1.getSha1Hash()).isEqualTo(artifact2.getSha1Hash()); + + assertThat(artifactRepository.countBySha1HashAndTenantAndSoftwareModuleDeletedIsFalse( + artifact1.getSha1Hash(), artifact1.getTenant())).isGreaterThan(1); + + artifactRepository.deleteById(artifact1.getId()); + assertThat(artifactRepository.findAll()).hasSize(1); + + assertThat(artifactRepository.countBySha1HashAndTenantAndSoftwareModuleDeletedIsFalse( + artifact2.getSha1Hash(), artifact2.getTenant())).isLessThanOrEqualTo(1); + + artifactRepository.deleteById(artifact2.getId()); + assertThat(artifactRepository.findAll()).hasSize(0); + + } + } + + @Test + @Description("Verifies that you can not delete artifacts from another tenant which exists in another tenant with the same hash and the SoftwareModule is not deleted") + public void deleteArtifactWithSameHashAndSoftwareModuleIsNotDeletedInDifferentTenants() throws Exception { + final String tenant1 = "mytenant"; + final String tenant2 = "tenant2"; + + final SoftwareModule module = createSoftwareModuleForTenant(tenant1); + final SoftwareModule module2 = createSoftwareModuleForTenant(tenant2); + + createArtifactForTenant(tenant1, "myInput", module.getId(), "myFirstFile"); + createArtifactForTenant(tenant2, "myInput", module2.getId(), "mySecondFile"); + final Artifact artifactTenant2 = createArtifactForTenant(tenant2, "myInput", module2.getId(), "myThirdFile"); + + verifyTenantArtifactCountIs(tenant1, 1); + verifyTenantArtifactCountIs(tenant2, 2); + + assertThat(runAsTenant(tenant1, () -> artifactRepository + .countBySha1HashAndTenantAndSoftwareModuleDeletedIsFalse(artifactTenant2.getSha1Hash(), tenant2))) + .isLessThanOrEqualTo(1); + runAsTenant(tenant2, () -> { + artifactRepository.deleteById(artifactTenant2.getId()); + return null; + }); + verifyTenantArtifactCountIs(tenant1, 1); + verifyTenantArtifactCountIs(tenant2, 1); + } + @Test @Description("Loads an local artifact based on given ID.") - public void findArtifact() throws NoSuchAlgorithmException, IOException { + public void findArtifact() throws IOException { final int artifactSize = 5 * 1024; try (final InputStream inputStream = new RandomGeneratedInputStream(artifactSize)) { final Artifact artifact = createArtifactForSoftwareModule("file1", @@ -372,17 +446,13 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { @Test @Description("Loads an artifact binary based on given ID.") - public void loadStreamOfArtifact() throws NoSuchAlgorithmException, IOException { + public void loadStreamOfArtifact() throws IOException { final int artifactSize = 5 * 1024; final byte[] randomBytes = randomBytes(artifactSize); try (final InputStream input = new ByteArrayInputStream(randomBytes)) { final Artifact artifact = createArtifactForSoftwareModule("file1", testdataFactory.createSoftwareModuleOs().getId(), artifactSize, input); - try (final InputStream inputStream = artifactManagement.loadArtifactBinary(artifact.getSha1Hash()).get() - .getFileInputStream()) { - assertTrue("The stored binary matches the given binary", - IOUtils.contentEquals(new ByteArrayInputStream(randomBytes), inputStream)); - } + assertEqualFileContents(artifactManagement.loadArtifactBinary(artifact.getSha1Hash()), randomBytes); } } @@ -425,7 +495,6 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { createArtifactForSoftwareModule("file2", sm.getId(), artifactSize, inputStream2); assertThat(artifactManagement.getByFilenameAndSoftwareModule("file1", sm.getId())).isPresent(); } - } private Artifact createArtifactForSoftwareModule(final String filename, final long moduleId, final int artifactSize) @@ -437,11 +506,38 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { } private Artifact createArtifactForSoftwareModule(final String filename, final long moduleId, final int artifactSize, - final InputStream inputStream) throws IOException { + final InputStream inputStream) { return artifactManagement.create(new ArtifactUpload(inputStream, moduleId, filename, false, artifactSize)); } private static byte[] randomBytes(final int len) { return RandomStringUtils.randomAlphanumeric(len).getBytes(); } + + private T runAsTenant(final String tenant, final Callable callable) throws Exception { + return securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("user", tenant), callable); + } + + private SoftwareModule createSoftwareModuleForTenant(final String tenant) throws Exception { + return runAsTenant(tenant, () -> testdataFactory.createSoftwareModuleApp()); + } + + private Artifact createArtifactForTenant(final String tenant, final String artifactData, final long moduleId, + final String filename) throws Exception { + return runAsTenant(tenant, () -> testdataFactory.createArtifact(artifactData, moduleId, filename)); + } + + private void verifyTenantArtifactCountIs(final String tenant, final int count) throws Exception { + assertThat(runAsTenant(tenant, () -> artifactRepository.findAll())).hasSize(count); + } + + private void assertEqualFileContents(final Optional artifact, final byte[] randomBytes) + throws IOException { + try (final InputStream inputStream = artifactManagement.loadArtifactBinary(artifact.get().getHashes().getSha1()) + .get().getFileInputStream()) { + assertTrue("The stored binary matches the given binary", + IOUtils.contentEquals(new ByteArrayInputStream(randomBytes), inputStream)); + } + } + } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/tenancy/MultiTenancyEntityTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/tenancy/MultiTenancyEntityTest.java index d3dbc075f..5af03300f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/tenancy/MultiTenancyEntityTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/tenancy/MultiTenancyEntityTest.java @@ -13,6 +13,7 @@ import static org.assertj.core.api.Assertions.fail; import java.util.Arrays; import java.util.Collection; +import java.util.concurrent.Callable; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; @@ -59,7 +60,6 @@ public class MultiTenancyEntityTest extends AbstractJpaIntegrationTest { assertThat(findTargetsForAnotherTenant).hasSize(1); assertThat(findTargetsForAnotherTenant.getContent().get(0).getTenant().toUpperCase()) .isEqualTo(anotherTenant.toUpperCase()); - } @Test @@ -163,34 +163,32 @@ public class MultiTenancyEntityTest extends AbstractJpaIntegrationTest { assertThat(findDistributionSetsForAnotherTenant).hasSize(1); assertThat(findDistributionSetsForAnotherTenant.getContent().get(0).getTenant().toUpperCase()) .isEqualTo(anotherTenant.toUpperCase()); + } + private T runAsTenant(final String tenant, final Callable callable) throws Exception { + return securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("user", tenant), callable); } private Target createTargetForTenant(final String controllerId, final String tenant) throws Exception { - return securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("user", tenant), - () -> testdataFactory.createTarget(controllerId)); + return runAsTenant(tenant, () -> testdataFactory.createTarget(controllerId)); } private Slice findTargetsForTenant(final String tenant) throws Exception { - return securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("user", tenant), - () -> targetManagement.findAll(PAGE)); + return runAsTenant(tenant, () -> targetManagement.findAll(PAGE)); } private void deleteTargetsForTenant(final String tenant, final Collection targetIds) throws Exception { - securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("user", tenant), () -> { + runAsTenant(tenant, () -> { targetManagement.delete(targetIds); return null; }); } private DistributionSet createDistributionSetForTenant(final String tenant) throws Exception { - return securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("user", tenant), - () -> testdataFactory.createDistributionSet()); + return runAsTenant(tenant, () -> testdataFactory.createDistributionSet()); } private Page findDistributionSetForTenant(final String tenant) throws Exception { - return securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("user", tenant), - () -> distributionSetManagement.findByCompleted(PAGE, true)); + return runAsTenant(tenant, () -> distributionSetManagement.findByCompleted(PAGE, true)); } - } diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java index 7f38983dc..789722573 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java @@ -465,15 +465,33 @@ public class TestdataFactory { final List artifacts = new ArrayList<>(); for (int i = 0; i < 3; i++) { final String artifactData = "some test data" + i; - final InputStream stubInputStream = IOUtils.toInputStream(artifactData, Charset.forName("UTF-8")); - artifacts.add(artifactManagement.create( - new ArtifactUpload(stubInputStream, moduleId, "filename" + i, false, artifactData.length()))); - + artifacts.add(createArtifact(artifactData, moduleId, "filename" + i)); } return artifacts; } + /** + * Create an {@link Artifact} for given {@link SoftwareModule} with a small + * text payload. + * + * @param artifactData + * the {@link Artifact} Inputstream + * + * @param moduleId + * the {@link Artifact} belongs to + * + * @param filename + * that was provided during upload. + * + * @return {@link Artifact} entity. + */ + public Artifact createArtifact(final String artifactData, final Long moduleId, final String filename) { + final InputStream stubInputStream = IOUtils.toInputStream(artifactData, Charset.forName("UTF-8")); + return artifactManagement + .create(new ArtifactUpload(stubInputStream, moduleId, filename, false, artifactData.length())); + } + /** * Creates {@link SoftwareModule} with {@link #DEFAULT_VENDOR} and * {@link #DEFAULT_VERSION} and random generated diff --git a/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutCondition.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutCondition.java index d83585415..75d11c344 100644 --- a/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutCondition.java +++ b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutCondition.java @@ -65,6 +65,6 @@ public class MgmtRolloutCondition { } public enum Condition { - THRESHOLD; + THRESHOLD } } diff --git a/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutErrorAction.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutErrorAction.java index 673c58a17..db34044f4 100644 --- a/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutErrorAction.java +++ b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutErrorAction.java @@ -76,6 +76,6 @@ public class MgmtRolloutErrorAction { * Possible actions */ public enum ErrorAction { - PAUSE; + PAUSE } } diff --git a/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutSuccessAction.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutSuccessAction.java index 174aa63fa..3d6415058 100644 --- a/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutSuccessAction.java +++ b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutSuccessAction.java @@ -65,6 +65,6 @@ public class MgmtRolloutSuccessAction { } public enum SuccessAction { - NEXTGROUP; + NEXTGROUP } } diff --git a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SecurityContextTenantAware.java b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SecurityContextTenantAware.java index 4eb11aa20..eadf04a46 100644 --- a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SecurityContextTenantAware.java +++ b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SecurityContextTenantAware.java @@ -135,7 +135,7 @@ public class SecurityContextTenantAware implements TenantAware { @Override public boolean isAuthenticated() { - return (delegate != null) ? delegate.isAuthenticated() : true; + return delegate == null || delegate.isAuthenticated(); } @Override diff --git a/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/ControllerPreAuthenticateSecurityTokenFilter.java b/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/ControllerPreAuthenticateSecurityTokenFilter.java index 7a9c7b5ae..4f90d9e2f 100644 --- a/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/ControllerPreAuthenticateSecurityTokenFilter.java +++ b/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/ControllerPreAuthenticateSecurityTokenFilter.java @@ -95,10 +95,7 @@ public class ControllerPreAuthenticateSecurityTokenFilter extends AbstractContro } final Optional foundTarget = systemSecurityContext.runAsSystemAsTenant( () -> controllerManagement.get(securityToken.getTargetId()), securityToken.getTenant()); - if (!foundTarget.isPresent()) { - return null; - } - return foundTarget.get().getControllerId(); + return foundTarget.map(Target::getControllerId).orElse(null); } @Override diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTable.java index 37e3ea601..624397235 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTable.java @@ -249,10 +249,7 @@ public class SoftwareModuleTable extends AbstractNamedVersionTable softwareModule = softwareModuleManagement.get(entityId); - if (softwareModule.isPresent()) { - return softwareModule.get().getName() + ":" + softwareModule.get().getVersion(); - } - return ""; + return softwareModule.map(module -> module.getName() + ":" + module.getVersion()).orElse(""); } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/DistributionSetMetadataDetailsLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/DistributionSetMetadataDetailsLayout.java index 138483d79..2370001c1 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/DistributionSetMetadataDetailsLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/DistributionSetMetadataDetailsLayout.java @@ -8,11 +8,8 @@ */ package org.eclipse.hawkbit.ui.common.detailslayout; -import java.util.List; - import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.model.DistributionSet; -import org.eclipse.hawkbit.repository.model.DistributionSetMetadata; import org.eclipse.hawkbit.ui.distributions.dstable.DsMetadataPopupLayout; import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider; import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; @@ -64,11 +61,9 @@ public class DistributionSetMetadataDetailsLayout extends AbstractMetadataDetail return; } selectedDistSetId = distributionSet.getId(); - final List dsMetadataList = distributionSetManagement - .findMetaDataByDistributionSetId(PageRequest.of(0, MAX_METADATA_QUERY), selectedDistSetId).getContent(); - if (!dsMetadataList.isEmpty()) { - dsMetadataList.forEach(this::setMetadataProperties); - } + final PageRequest pageRequest = PageRequest.of(0, MAX_METADATA_QUERY); + distributionSetManagement.findMetaDataByDistributionSetId(pageRequest, selectedDistSetId).getContent() + .forEach(this::setMetadataProperties); } @Override diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/TargetMetadataDetailsLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/TargetMetadataDetailsLayout.java index f5821c9e7..ef2471990 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/TargetMetadataDetailsLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/TargetMetadataDetailsLayout.java @@ -8,11 +8,8 @@ */ package org.eclipse.hawkbit.ui.common.detailslayout; -import java.util.List; - import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.model.Target; -import org.eclipse.hawkbit.repository.model.TargetMetadata; import org.eclipse.hawkbit.ui.management.targettable.TargetMetadataPopupLayout; import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider; import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; @@ -63,12 +60,8 @@ public class TargetMetadataDetailsLayout extends AbstractMetadataDetailsLayout { return; } selectedTargetId = target.getId(); - final List targetMetadataList = targetManagement - .findMetaDataByControllerId(PageRequest.of(0, MAX_METADATA_QUERY), target.getControllerId()) - .getContent(); - if (!targetMetadataList.isEmpty()) { - targetMetadataList.forEach(this::setMetadataProperties); - } + targetManagement.findMetaDataByControllerId(PageRequest.of(0, MAX_METADATA_QUERY), target.getControllerId()) + .getContent().forEach(this::setMetadataProperties); } @Override diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/BaseEntityEventType.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/BaseEntityEventType.java index 4208dc5fb..4197f1437 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/BaseEntityEventType.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/BaseEntityEventType.java @@ -13,5 +13,5 @@ package org.eclipse.hawkbit.ui.common.table; * */ public enum BaseEntityEventType { - ADD_ENTITY, REMOVE_ENTITY, UPDATED_ENTITY, SELECTED_ENTITY, MAXIMIZED, MINIMIZED; + ADD_ENTITY, REMOVE_ENTITY, UPDATED_ENTITY, SELECTED_ENTITY, MAXIMIZED, MINIMIZED } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleTable.java index 198f40778..17f748127 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleTable.java @@ -338,10 +338,7 @@ public class SwModuleTable extends AbstractNamedVersionTable { @Override protected String getDeletedEntityName(final Long entityId) { final Optional softwareModule = softwareModuleManagement.get(entityId); - if (softwareModule.isPresent()) { - return softwareModule.get().getName() + ":" + softwareModule.get().getVersion(); - } - return ""; + return softwareModule.map(module -> module.getName() + ":" + module.getVersion()).orElse(""); } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/miscs/MaintenanceWindowLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/miscs/MaintenanceWindowLayout.java index 8b9d7a6c7..e5576a44f 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/miscs/MaintenanceWindowLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/miscs/MaintenanceWindowLayout.java @@ -200,11 +200,9 @@ public class MaintenanceWindowLayout extends VerticalLayout { * Get list of all time zone offsets supported. */ private static List getAllTimeZones() { - final List lst = ZoneId.getAvailableZoneIds().stream() - .map(id -> ZonedDateTime.now(ZoneId.of(id)).getOffset().getId().replace("Z", "+00:00")).distinct() - .collect(Collectors.toList()); - lst.sort(null); - return lst; + return ZoneId.getAvailableZoneIds().stream() + .map(id -> ZonedDateTime.now(ZoneId.of(id)).getOffset().getId().replace("Z", "+00:00")) + .distinct().sorted().collect(Collectors.toList()); } /** diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/menu/DashboardMenu.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/menu/DashboardMenu.java index 6d5aba757..a4a1c2253 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/menu/DashboardMenu.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/menu/DashboardMenu.java @@ -337,14 +337,9 @@ public final class DashboardMenu extends CustomComponent { * with given viewname does not exists */ public DashboardMenuItem getByViewName(final String viewName) { - final Optional findFirst = dashboardVaadinViews.stream() - .filter(view -> view.getViewName().equals(viewName)).findAny(); - if (!findFirst.isPresent()) { - return null; - } - - return findFirst.get(); + return dashboardVaadinViews.stream() + .filter(view -> view.getViewName().equals(viewName)).findAny().orElse(null); } /** @@ -355,14 +350,8 @@ public final class DashboardMenu extends CustomComponent { * @return true = denied, false = accessible */ public boolean isAccessDenied(final String viewName) { - final List accessibleViews = getAccessibleViews(); - boolean accessDeined = Boolean.TRUE.booleanValue(); - for (final DashboardMenuItem dashboardViewType : accessibleViews) { - if (dashboardViewType.getViewName().equals(viewName)) { - accessDeined = Boolean.FALSE.booleanValue(); - } - } - return accessDeined; + return getAccessibleViews().stream() + .noneMatch(dashboardMenuItem -> dashboardMenuItem.getViewName().equals(viewName)); } private class MenuToggleClickListenerMyClickListener implements ClickListener { diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/AutoStartOptionGroupLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/AutoStartOptionGroupLayout.java index 36aae13fc..7c13c776c 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/AutoStartOptionGroupLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/AutoStartOptionGroupLayout.java @@ -149,7 +149,7 @@ public class AutoStartOptionGroupLayout extends HorizontalLayout { * Rollout start options */ enum AutoStartOption { - MANUAL, AUTO_START, SCHEDULED; + MANUAL, AUTO_START, SCHEDULED }