From 09f2d8a4812d44c462268682eac58e2376c72b93 Mon Sep 17 00:00:00 2001 From: Alexander Dobler <50330299+dobleralex@users.noreply.github.com> Date: Wed, 30 Oct 2019 11:24:33 +0100 Subject: [PATCH] Fix upload quota check and provide better error message (#893) * Adjusted upload quota check to include file size and show proper error message Signed-off-by: Alexander Dobler * Fixed failing upload quota tests Signed-off-by: Alexander Dobler * Moved quota check to stream, fixed review findings Signed-off-by: Alexander Dobler * Added missing license header to QuotaInputStream Signed-off-by: Alexander Dobler * Reworked uploadLock, ensured error messages may be translated, review fixes Signed-off-by: Alexander Dobler * Added local artifactrepo to gitignore Signed-off-by: Alexander Dobler * Fixed sonar issues and assignment quota message Signed-off-by: Alexander Dobler * PR review fixes Signed-off-by: Alexander Dobler * Split quota exceptions, PR fixes Signed-off-by: Alexander Dobler * Removed left over conversion method in quota helper Signed-off-by: Alexander Dobler * Made conversion helper class final Signed-off-by: Alexander Dobler --- .gitignore | 1 + .../hawkbit/exception/SpServerError.java | 10 +++ .../amqp/DelayedRequeueExceptionStrategy.java | 4 +- .../repository/ControllerManagement.java | 22 ++--- .../repository/DeploymentManagement.java | 8 +- .../repository/DistributionSetManagement.java | 6 +- .../DistributionSetTypeManagement.java | 6 +- .../hawkbit/repository/RolloutManagement.java | 6 +- .../repository/SizeConversionHelper.java | 40 +++++++++ .../repository/SoftwareModuleManagement.java | 6 +- .../TargetFilterQueryManagement.java | 10 +-- .../hawkbit/repository/TargetManagement.java | 4 +- ... => AssignmentQuotaExceededException.java} | 64 +++++++-------- .../FileSizeQuotaExceededException.java | 49 +++++++++++ .../StorageQuotaExceededException.java | 49 +++++++++++ .../hawkbit/repository/RolloutHelper.java | 4 +- .../repository/jpa/JpaArtifactManagement.java | 43 +++------- .../jpa/JpaDistributionSetTypeManagement.java | 4 +- ...izeAndStorageQuotaCheckingInputStream.java | 81 +++++++++++++++++++ .../repository/jpa/utils/QuotaHelper.java | 21 ++--- .../jpa/ArtifactManagementTest.java | 22 ++--- .../jpa/ControllerManagementTest.java | 28 +++---- .../jpa/DeploymentManagementTest.java | 8 +- .../jpa/DistributionSetManagementTest.java | 14 ++-- .../DistributionSetTypeManagementTest.java | 10 +-- .../repository/jpa/RolloutManagementTest.java | 10 +-- .../jpa/SoftwareModuleManagementTest.java | 8 +- .../jpa/TargetFilterQueryManagementTest.java | 8 +- .../repository/jpa/TargetManagementTest.java | 8 +- .../ddi/rest/resource/DdiConfigDataTest.java | 4 +- .../MgmtDistributionSetResourceTest.java | 6 +- .../MgmtDistributionSetTypeResourceTest.java | 6 +- .../resource/MgmtRolloutResourceTest.java | 6 +- .../MgmtSoftwareModuleResourceTest.java | 14 ++-- .../MgmtTargetFilterQueryResourceTest.java | 7 +- .../exception/ResponseExceptionHandler.java | 2 + .../upload/AbstractFileTransferHandler.java | 50 ++++++++++-- .../FileTransferHandlerStreamVariable.java | 5 +- .../FileTransferHandlerVaadinUpload.java | 5 +- .../upload/UploadDropAreaLayout.java | 9 ++- .../upload/UploadProgressButtonLayout.java | 11 ++- .../ui/components/HawkbitUIErrorHandler.java | 6 ++ .../src/main/resources/messages.properties | 5 +- 43 files changed, 477 insertions(+), 213 deletions(-) create mode 100644 hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SizeConversionHelper.java rename hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/{QuotaExceededException.java => AssignmentQuotaExceededException.java} (65%) create mode 100644 hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/FileSizeQuotaExceededException.java create mode 100644 hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/StorageQuotaExceededException.java create mode 100644 hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/FileSizeAndStorageQuotaCheckingInputStream.java diff --git a/.gitignore b/.gitignore index 6373607d8..2ae386c9d 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ target .metadata .project .idea +artifactrepo # Windows image file caches Thumbs.db 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 389f8edb9..8d50b9e72 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 @@ -137,6 +137,16 @@ public enum SpServerError { */ SP_QUOTA_EXCEEDED("hawkbit.server.error.quota.tooManyEntries", "Too many entries have been inserted."), + /** + * error that describes that size of uploaded file exceeds size quota + */ + SP_FILE_SIZE_QUOTA_EXCEEDED("hawkbit.server.error.quota.fileSizeExceeded", "File exceeds size quota."), + + /** + * error that describes that size of uploaded file exceeds storage quota + */ + SP_STORAGE_QUOTA_EXCEEDED("hawkbit.server.error.quota.storageExceeded", "Storage quota will be exceeded if file is uploaded."), + /** * error message, which describes that the action can not be canceled cause * the action is inactive. diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DelayedRequeueExceptionStrategy.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DelayedRequeueExceptionStrategy.java index 483b19324..dc917ded6 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DelayedRequeueExceptionStrategy.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DelayedRequeueExceptionStrategy.java @@ -16,7 +16,7 @@ import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.InvalidTargetAddressException; import org.eclipse.hawkbit.repository.exception.InvalidTargetAttributeException; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.TenantNotExistException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -72,7 +72,7 @@ public class DelayedRequeueExceptionStrategy extends ConditionalRejectingErrorHa } private static boolean quotaHit(final Throwable cause) { - return cause instanceof QuotaExceededException; + return cause instanceof AssignmentQuotaExceededException; } private static boolean doesNotExist(final Throwable cause) { diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java index d92d9b9a5..28e314f28 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java @@ -25,7 +25,7 @@ import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.InvalidTargetAttributeException; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.ActionStatus; @@ -56,9 +56,9 @@ public interface ControllerManagement { * @throws EntityAlreadyExistsException * if a given entity already exists * - * @throws QuotaExceededException - * if more than the allowed number of status entries or messages per - * entry are inserted + * @throws AssignmentQuotaExceededException + * if more than the allowed number of status entries or messages + * per entry are inserted * @throws EntityNotFoundException * if given action does not exist * @throws ConstraintViolationException @@ -101,9 +101,9 @@ public interface ControllerManagement { * * @return created {@link ActionStatus} entity * - * @throws QuotaExceededException - * if more than the allowed number of status entries or messages per - * entry are inserted + * @throws AssignmentQuotaExceededException + * if more than the allowed number of status entries or messages + * per entry are inserted * @throws EntityNotFoundException * if given action does not exist * @throws ConstraintViolationException @@ -123,9 +123,9 @@ public interface ControllerManagement { * * @throws EntityAlreadyExistsException * if a given entity already exists - * @throws QuotaExceededException - * if more than the allowed number of status entries or messages per - * entry are inserted + * @throws AssignmentQuotaExceededException + * if more than the allowed number of status entries or messages + * per entry are inserted * @throws EntityNotFoundException * if action status not exist * @throws ConstraintViolationException @@ -361,7 +361,7 @@ public interface ControllerManagement { * * @throws EntityNotFoundException * if target that has to be updated could not be found - * @throws QuotaExceededException + * @throws AssignmentQuotaExceededException * if maximum number of attributes per target is exceeded * @throws InvalidTargetAttributeException * if attributes violate constraints diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java index aec6bc648..32cfda0f1 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java @@ -23,7 +23,7 @@ import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException; import org.eclipse.hawkbit.repository.exception.MultiAssignmentIsNotEnabledException; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.repository.model.Action; @@ -66,7 +66,7 @@ public interface DeploymentManagement { * if either provided {@link DistributionSet} or {@link Target}s * do not exist * - * @throws QuotaExceededException + * @throws AssignmentQuotaExceededException * if the maximum number of targets the distribution set can be * assigned to at once is exceeded * @throws MultiAssignmentIsNotEnabledException @@ -97,7 +97,7 @@ public interface DeploymentManagement { * if either provided {@link DistributionSet} or {@link Target}s * do not exist * - * @throws QuotaExceededException + * @throws AssignmentQuotaExceededException * if the maximum number of targets the distribution set can be * assigned to at once is exceeded * @throws MultiAssignmentIsNotEnabledException @@ -151,7 +151,7 @@ public interface DeploymentManagement { * if either provided {@link DistributionSet} or {@link Target}s * do not exist * - * @throws QuotaExceededException + * @throws AssignmentQuotaExceededException * if the maximum number of targets the distribution set can be * assigned to at once is exceeded * diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java index 5b2606a5b..aa829582f 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java @@ -21,7 +21,7 @@ import org.eclipse.hawkbit.repository.builder.DistributionSetUpdate; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException; @@ -67,7 +67,7 @@ public interface DistributionSetManagement * if {@link SoftwareModule#getType()} is not supported by this * {@link DistributionSet#getType()}. * - * @throws QuotaExceededException + * @throws AssignmentQuotaExceededException * if the maximum number of {@link SoftwareModule}s is exceeded * for the addressed {@link DistributionSet}. */ @@ -109,7 +109,7 @@ public interface DistributionSetManagement * in case one of the meta data entry already exists for the * specific key * - * @throws QuotaExceededException + * @throws AssignmentQuotaExceededException * if the maximum number of {@link MetaData} entries is exceeded * for the addressed {@link DistributionSet} */ diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTypeManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTypeManagement.java index 1682b3870..b033380ca 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTypeManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTypeManagement.java @@ -18,7 +18,7 @@ import org.eclipse.hawkbit.repository.builder.DistributionSetTypeCreate; import org.eclipse.hawkbit.repository.builder.DistributionSetTypeUpdate; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; @@ -65,7 +65,7 @@ public interface DistributionSetTypeManagement * if the {@link DistributionSetType} while it is already in use * by a {@link DistributionSet} * - * @throws QuotaExceededException + * @throws AssignmentQuotaExceededException * if the maximum number of {@link SoftwareModuleType}s is * exceeded for the addressed {@link DistributionSetType} */ @@ -90,7 +90,7 @@ public interface DistributionSetTypeManagement * if the {@link DistributionSetType} while it is already in use * by a {@link DistributionSet} * - * @throws QuotaExceededException + * @throws AssignmentQuotaExceededException * if the maximum number of {@link SoftwareModuleType}s is * exceeded for the addressed {@link DistributionSetType} */ diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java index d51f61349..e96f73d07 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java @@ -22,7 +22,7 @@ import org.eclipse.hawkbit.repository.builder.RolloutGroupCreate; import org.eclipse.hawkbit.repository.builder.RolloutUpdate; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException; @@ -124,7 +124,7 @@ public interface RolloutManagement { * if given {@link DistributionSet} does not exist * @throws ConstraintViolationException * if rollout or group parameters are invalid. - * @throws QuotaExceededException + * @throws AssignmentQuotaExceededException * if the maximum number of allowed targets per rollout group is * exceeded. */ @@ -161,7 +161,7 @@ public interface RolloutManagement { * if given {@link DistributionSet} does not exist * @throws ConstraintViolationException * if rollout or group parameters are invalid - * @throws QuotaExceededException + * @throws AssignmentQuotaExceededException * if the maximum number of allowed targets per rollout group is * exceeded. */ diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SizeConversionHelper.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SizeConversionHelper.java new file mode 100644 index 000000000..cc1c4a471 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SizeConversionHelper.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2019 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.repository; + +/** + * Helper class that provides simple conversion of byte values to readable + * strings + */ +public final class SizeConversionHelper { + + private static final String KB = "KB"; + private static final String MB = "MB"; + + // do not allow to create instances + private SizeConversionHelper() { + } + + /** + * Convert byte values to human readable strings with units + * + * @param byteValue + * Value to convert in bytes + */ + public static String byteValueToReadableString(final long byteValue) { + double outputValue = byteValue / 1024.0; + String unit = KB; + if (outputValue >= 1024) { + outputValue = outputValue / 1024.0; + unit = MB; + } + // We cut decimal places to avoid localization handling + return (long) outputValue + " " + unit; + } +} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleManagement.java index f7465cffd..00b4d4c7d 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleManagement.java @@ -23,7 +23,7 @@ import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataUpdate; import org.eclipse.hawkbit.repository.builder.SoftwareModuleUpdate; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.repository.model.AssignedSoftwareModule; @@ -75,7 +75,7 @@ public interface SoftwareModuleManagement * @throws EntityNotFoundException * if software module with given ID does not exist * - * @throws QuotaExceededException + * @throws AssignmentQuotaExceededException * if the maximum number of {@link SoftwareModuleMetadata} * entries is exceeded for the addressed {@link SoftwareModule} */ @@ -97,7 +97,7 @@ public interface SoftwareModuleManagement * @throws EntityNotFoundException * if software module with given ID does not exist * - * @throws QuotaExceededException + * @throws AssignmentQuotaExceededException * if the maximum number of {@link SoftwareModuleMetadata} * entries is exceeded for the addressed {@link SoftwareModule} */ diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetFilterQueryManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetFilterQueryManagement.java index d23c2eea9..937f9fb4f 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetFilterQueryManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetFilterQueryManagement.java @@ -20,7 +20,7 @@ import org.eclipse.hawkbit.repository.builder.TargetFilterQueryUpdate; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignActionTypeException; import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignDistributionSetException; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.repository.model.Action.ActionType; @@ -48,7 +48,7 @@ public interface TargetFilterQueryManagement { * if fields are not filled as specified. Check * {@link TargetFilterQueryCreate} for field constraints. * - * @throws QuotaExceededException + * @throws AssignmentQuotaExceededException * if the maximum number of targets that is addressed by the * given query is exceeded (auto-assignments only) */ @@ -208,7 +208,7 @@ public interface TargetFilterQueryManagement { * if fields are not filled as specified. Check * {@link TargetFilterQueryUpdate} for field constraints. * - * @throws QuotaExceededException + * @throws AssignmentQuotaExceededException * if the update contains a new query which addresses too many * targets (auto-assignments only) */ @@ -231,7 +231,7 @@ public interface TargetFilterQueryManagement { * if either {@link TargetFilterQuery} and/or autoAssignDs are * provided but not found * - * @throws QuotaExceededException + * @throws AssignmentQuotaExceededException * if the query that is already associated with this filter * query addresses too many targets (auto-assignments only) * @@ -263,7 +263,7 @@ public interface TargetFilterQueryManagement { * if either {@link TargetFilterQuery} and/or autoAssignDs are * provided but not found * - * @throws QuotaExceededException + * @throws AssignmentQuotaExceededException * if the query that is already associated with this filter * query addresses too many targets (auto-assignments only) * diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java index b11098cc7..602c7aa72 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java @@ -23,7 +23,7 @@ import org.eclipse.hawkbit.repository.builder.TargetCreate; import org.eclipse.hawkbit.repository.builder.TargetUpdate; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -698,7 +698,7 @@ public interface TargetManagement { * in case one of the meta data entry already exists for the * specific key * - * @throws QuotaExceededException + * @throws AssignmentQuotaExceededException * if the maximum number of {@link MetaData} entries is exceeded * for the addressed {@link Target} */ diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/QuotaExceededException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/AssignmentQuotaExceededException.java similarity index 65% rename from hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/QuotaExceededException.java rename to hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/AssignmentQuotaExceededException.java index 365fbc416..33b604fa9 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/QuotaExceededException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/AssignmentQuotaExceededException.java @@ -13,44 +13,43 @@ import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.repository.model.BaseEntity; /** - * Thrown if too many entries are added to repository. - * + * Thrown if assignment quota is exceeded */ -public final class QuotaExceededException extends AbstractServerRtException { - - private static final long serialVersionUID = 1L; +public class AssignmentQuotaExceededException extends AbstractServerRtException { private static final String ASSIGNMENT_QUOTA_EXCEEDED_MESSAGE = "Quota exceeded: Cannot assign %s more %s entities to %s '%s'. The maximum is %s."; + private static final SpServerError errorType = SpServerError.SP_QUOTA_EXCEEDED; /** - * Creates a new QuotaExceededException with + * Creates a new AssignmentQuotaExceededException with * {@link SpServerError#SP_QUOTA_EXCEEDED} error. */ - public QuotaExceededException() { - super(SpServerError.SP_QUOTA_EXCEEDED); + public AssignmentQuotaExceededException() { + super(errorType); } /** - * Creates a new QuotaExceededException with a custom error message. - * + * Creates a new AssignmentQuotaExceededException with a custom error + * message. + * * @param message * The custom error message. */ - public QuotaExceededException(final String message) { - super(message, SpServerError.SP_QUOTA_EXCEEDED); + public AssignmentQuotaExceededException(final String message) { + super(message, errorType); } /** - * Creates a QuotaExceededException with a custom error message and a root - * cause. - * + * Creates a AssignmentQuotaExceededException with a custom error message + * and a root cause. + * * @param message * The custom error message. * @param cause * for the exception */ - public QuotaExceededException(final String message, final Throwable cause) { - super(message, SpServerError.SP_QUOTA_EXCEEDED, cause); + public AssignmentQuotaExceededException(final String message, final Throwable cause) { + super(message, errorType, cause); } /** @@ -61,12 +60,13 @@ public final class QuotaExceededException extends AbstractServerRtException { * @param quota * that is defined by the repository */ - public QuotaExceededException(final Class type, final long inserted, final int quota) { + public AssignmentQuotaExceededException(final Class type, final long inserted, + final int quota) { this(type.getSimpleName(), inserted, quota); } /** - * + * * @param type * that hit quota * @param inserted @@ -74,15 +74,15 @@ public final class QuotaExceededException extends AbstractServerRtException { * @param quota * that is defined by the repository */ - public QuotaExceededException(final String type, final long inserted, final int quota) { + public AssignmentQuotaExceededException(final String type, final long inserted, final int quota) { super("Request contains too many entries of {" + type + "}. {" + inserted + "} is beyond the permitted {" - + quota + "}.", SpServerError.SP_QUOTA_EXCEEDED); + + quota + "}.", errorType); } /** - * Creates a QuotaExceededException which is to be thrown when an assignment - * quota is exceeded. - * + * Creates a AssignmentQuotaExceededException which is to be thrown when an + * assignment quota is exceeded. + * * @param type * The type of the entities that shall be assigned to the * specified parent entity. @@ -97,15 +97,15 @@ public final class QuotaExceededException extends AbstractServerRtException { * The maximum number of entities that can be assigned to the * parent entity. */ - public QuotaExceededException(final Class type, final Class parentType, final Long parentId, + public AssignmentQuotaExceededException(final Class type, final Class parentType, final Long parentId, final long requested, final long quota) { this(type.getSimpleName(), parentType.getSimpleName(), parentId, requested, quota); } /** - * Creates a QuotaExceededException which is to be thrown when an assignment - * quota is exceeded. - * + * Creates a AssignmentQuotaExceededException which is to be thrown when an + * assignment quota is exceeded. + * * @param type * The type of the entities that shall be assigned to the * specified parent entity. @@ -120,11 +120,9 @@ public final class QuotaExceededException extends AbstractServerRtException { * The maximum number of entities that can be assigned to the * parent entity. */ - public QuotaExceededException(final String type, final String parentType, final Object parentId, - final long requested, - final long quota) { + public AssignmentQuotaExceededException(final String type, final String parentType, final Object parentId, + final long requested, final long quota) { super(String.format(ASSIGNMENT_QUOTA_EXCEEDED_MESSAGE, requested, type, parentType, - parentId != null ? String.valueOf(parentId) : "", quota), SpServerError.SP_QUOTA_EXCEEDED); + parentId != null ? String.valueOf(parentId) : "", quota), errorType); } - } diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/FileSizeQuotaExceededException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/FileSizeQuotaExceededException.java new file mode 100644 index 000000000..87a583021 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/FileSizeQuotaExceededException.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2019 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.repository.exception; + +import static org.eclipse.hawkbit.repository.SizeConversionHelper.byteValueToReadableString; + +import org.eclipse.hawkbit.exception.AbstractServerRtException; +import org.eclipse.hawkbit.exception.SpServerError; + +/** + * Thrown if file size quota is exceeded + */ +public class FileSizeQuotaExceededException extends AbstractServerRtException { + + private static final String MAX_ARTIFACT_SIZE_EXCEEDED = "Maximum artifact size (%s) exceeded."; + private static final SpServerError errorType = SpServerError.SP_FILE_SIZE_QUOTA_EXCEEDED; + + private final long exceededQuotaValue; + + /** + * Creates a new FileSizeQuotaExceededException with a quota value. + * + * @param exceededQuotaValue + * Value by how much the quota was exceeded + */ + public FileSizeQuotaExceededException(final long exceededQuotaValue) { + super(createQuotaErrorMessage(exceededQuotaValue), errorType); + this.exceededQuotaValue = exceededQuotaValue; + } + + /** + * Get a readable string of size quota including unit + * + * @return file size quota with unit + */ + public String getExceededQuotaValueString() { + return byteValueToReadableString(exceededQuotaValue); + } + + private static String createQuotaErrorMessage(final long exceededQuotaValue) { + return String.format(MAX_ARTIFACT_SIZE_EXCEEDED, byteValueToReadableString(exceededQuotaValue)); + } +} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/StorageQuotaExceededException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/StorageQuotaExceededException.java new file mode 100644 index 000000000..850c90863 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/StorageQuotaExceededException.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2019 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.repository.exception; + +import static org.eclipse.hawkbit.repository.SizeConversionHelper.byteValueToReadableString; + +import org.eclipse.hawkbit.exception.AbstractServerRtException; +import org.eclipse.hawkbit.exception.SpServerError; + +/** + * Thrown if storage quota is exceeded + */ +public class StorageQuotaExceededException extends AbstractServerRtException { + + private static final String MAX_ARTIFACT_SIZE_TOTAL_EXCEEDED = "Storage quota exceeded, %s left."; + private static final SpServerError errorType = SpServerError.SP_STORAGE_QUOTA_EXCEEDED; + + private final long exceededQuotaValue; + + /** + * Creates a new StorageQuotaExceededException with a quota value. + * + * @param exceededQuotaValue + * Value by how much the quota was exceeded + */ + public StorageQuotaExceededException(final long exceededQuotaValue) { + super(createQuotaErrorMessage(exceededQuotaValue), errorType); + this.exceededQuotaValue = exceededQuotaValue; + } + + /** + * Get a readable string of size quota including unit + * + * @return file size quota with unit + */ + public String getExceededQuotaValueString() { + return byteValueToReadableString(exceededQuotaValue); + } + + private static String createQuotaErrorMessage(final long exceededQuotaValue) { + return String.format(MAX_ARTIFACT_SIZE_TOTAL_EXCEEDED, byteValueToReadableString(exceededQuotaValue)); + } +} diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/RolloutHelper.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/RolloutHelper.java index 01ebfdbcf..f5e227273 100644 --- a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/RolloutHelper.java +++ b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/RolloutHelper.java @@ -14,7 +14,7 @@ import java.util.stream.Collectors; import javax.validation.ValidationException; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException; import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.RolloutGroup; @@ -78,7 +78,7 @@ public final class RolloutHelper { if (amountGroup <= 0) { throw new ValidationException("The amount of groups cannot be lower than zero"); } else if (amountGroup > quotaManagement.getMaxRolloutGroupsPerRollout()) { - throw new QuotaExceededException( + throw new AssignmentQuotaExceededException( "The amount of groups cannot be greater than " + quotaManagement.getMaxRolloutGroupsPerRollout()); } 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 a66ac0f58..f158e0455 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 @@ -8,6 +8,8 @@ */ package org.eclipse.hawkbit.repository.jpa; +import java.io.IOException; +import java.io.InputStream; import java.util.Optional; import org.eclipse.hawkbit.artifact.repository.ArtifactRepository; @@ -23,11 +25,11 @@ import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.InvalidMD5HashException; import org.eclipse.hawkbit.repository.exception.InvalidSHA1HashException; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; import org.eclipse.hawkbit.repository.jpa.configuration.Constants; import org.eclipse.hawkbit.repository.jpa.model.JpaArtifact; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; +import org.eclipse.hawkbit.repository.jpa.utils.FileSizeAndStorageQuotaCheckingInputStream; import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.ArtifactUpload; import org.eclipse.hawkbit.repository.model.SoftwareModule; @@ -53,10 +55,6 @@ public class JpaArtifactManagement implements ArtifactManagement { private static final Logger LOG = LoggerFactory.getLogger(JpaArtifactManagement.class); - private static final String MAX_ARTIFACT_SIZE_EXCEEDED = "Quota exceeded: The artifact '%s' (%s bytes) which has been uploaded for software module '%s' exceeds the maximum artifact size of %s bytes."; - - private static final String MAX_ARTIFACT_SIZE_TOTAL_EXCEEDED = "Quota exceeded: The artifact '%s' (%s bytes) cannot be uploaded. The maximum total artifact storage of %s bytes would be exceeded."; - private final LocalArtifactRepository localArtifactRepository; private final SoftwareModuleRepository softwareModuleRepository; @@ -105,8 +103,6 @@ public class JpaArtifactManagement implements ArtifactManagement { 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); @@ -125,11 +121,12 @@ public class JpaArtifactManagement implements ArtifactManagement { } private AbstractDbArtifact storeArtifact(final ArtifactUpload artifactUpload) { - try { - return artifactRepository.store(tenantAware.getCurrentTenant(), artifactUpload.getInputStream(), + try(final InputStream quotaStream = wrapInQuotaStream(artifactUpload.getInputStream())) { + return artifactRepository.store(tenantAware.getCurrentTenant(), quotaStream, artifactUpload.getFilename(), artifactUpload.getContentType(), - new DbArtifactHash(artifactUpload.getProvidedSha1Sum(), artifactUpload.getProvidedMd5Sum(), artifactUpload.getProvidedSha256Sum())); - } catch (final ArtifactStoreException e) { + new DbArtifactHash(artifactUpload.getProvidedSha1Sum(), artifactUpload.getProvidedMd5Sum(), + artifactUpload.getProvidedSha256Sum())); + } catch (final ArtifactStoreException | IOException e) { throw new ArtifactUploadFailedException(e); } catch (final HashNotMatchException e) { if (e.getHashFunction().equals(HashNotMatchException.SHA1)) { @@ -145,31 +142,13 @@ public class JpaArtifactManagement implements ArtifactManagement { Artifact.class, SoftwareModule.class, localArtifactRepository::countBySoftwareModuleId); } - private void assertMaxArtifactSizeQuota(final String filename, final long id, final long artifactSize) { + private InputStream wrapInQuotaStream(final InputStream in) { final long maxArtifactSize = quotaManagement.getMaxArtifactSize(); - if (maxArtifactSize <= 0) { - return; - } - if (artifactSize > maxArtifactSize) { - final String msg = String.format(MAX_ARTIFACT_SIZE_EXCEEDED, filename, artifactSize, id, maxArtifactSize); - LOG.warn(msg); - throw new QuotaExceededException(msg); - } - } - private void assertMaxArtifactStorageQuota(final String filename, final long artifactSize) { + final long currentlyUsed = localArtifactRepository.getSumOfUndeletedArtifactSize().orElse(0L); final long maxArtifactSizeTotal = quotaManagement.getMaxArtifactStorage(); - if (maxArtifactSizeTotal <= 0) { - return; - } - final Long currentlyUsed = localArtifactRepository.getSumOfUndeletedArtifactSize().orElse(0L); - if (currentlyUsed + artifactSize > maxArtifactSizeTotal) { - final String msg = String.format(MAX_ARTIFACT_SIZE_TOTAL_EXCEEDED, filename, artifactSize, - maxArtifactSizeTotal); - LOG.warn(msg); - throw new QuotaExceededException(msg); - } + return new FileSizeAndStorageQuotaCheckingInputStream(in, maxArtifactSize, maxArtifactSizeTotal - currentlyUsed); } @Override diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetTypeManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetTypeManagement.java index 0e2c968fa..48f34deaa 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetTypeManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetTypeManagement.java @@ -23,7 +23,7 @@ import org.eclipse.hawkbit.repository.builder.DistributionSetTypeUpdate; import org.eclipse.hawkbit.repository.builder.GenericDistributionSetTypeUpdate; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.jpa.builder.JpaDistributionSetTypeCreate; import org.eclipse.hawkbit.repository.jpa.configuration.Constants; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType; @@ -163,7 +163,7 @@ public class JpaDistributionSetTypeManagement implements DistributionSetTypeMana * @param requested * number of software module types to check * - * @throws QuotaExceededException + * @throws AssignmentQuotaExceededException * if the software module type quota is exceeded */ private void assertSoftwareModuleTypeQuota(final long id, final int requested) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/FileSizeAndStorageQuotaCheckingInputStream.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/FileSizeAndStorageQuotaCheckingInputStream.java new file mode 100644 index 000000000..334a68f15 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/FileSizeAndStorageQuotaCheckingInputStream.java @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2019 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.repository.jpa.utils; + +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.eclipse.hawkbit.repository.exception.FileSizeQuotaExceededException; +import org.eclipse.hawkbit.repository.exception.StorageQuotaExceededException; + +/** + * A FilterInputStream that ensures file size and storage quotas are enforced. It check during read operations if the + * quota will be exceeded and throws an QuotaExceededException if this happens. + */ +public class FileSizeAndStorageQuotaCheckingInputStream extends FilterInputStream { + + private final long quota; + private final long sizeLimit; + + private long size; + + /** + * Creates a QuotaInputStream using the input stream in and a + * limiting quota + * + * @param in + * Inner InputStream that read operations will be forwarded to + * @param sizeLimit + * Quota file size limit in byte + * @param storageLeft + * Storage left until quota is reached + */ + public FileSizeAndStorageQuotaCheckingInputStream(final InputStream in, final long sizeLimit, final long storageLeft) { + super(in); + + // only limit to lower bound to avoid two checks + this.quota = Math.min(sizeLimit, storageLeft); + this.sizeLimit = sizeLimit; + } + + @Override + public int read() throws IOException { + final int read = super.read(); + checkQuotaAndUpdateSize(read); + return read; + } + + @Override + public int read(final byte[] b) throws IOException { + final int read = super.read(b); + checkQuotaAndUpdateSize(read); + return read; + } + + @Override + public int read(final byte[] b, final int off, final int len) throws IOException { + final int read = super.read(b, off, len); + checkQuotaAndUpdateSize(read); + return read; + } + + private void checkQuotaAndUpdateSize(final int read) { + if ((size + read) > quota) { + // pick exception based on quota type + if (quota == sizeLimit) { + throw new FileSizeQuotaExceededException(quota); + } else { + throw new StorageQuotaExceededException(quota); + } + } else if (read >= 0) { + size += read; + } + } +} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/QuotaHelper.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/QuotaHelper.java index f078f7f45..595211332 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/QuotaHelper.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/QuotaHelper.java @@ -12,12 +12,12 @@ import java.util.function.ToLongFunction; import javax.validation.constraints.NotNull; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * Helper class to check assignment quotas. + * Helper class to check quotas. */ public final class QuotaHelper { @@ -26,6 +26,8 @@ public final class QuotaHelper { */ private static final Logger LOG = LoggerFactory.getLogger(QuotaHelper.class); + private static final String MAX_ASSIGNMENT_QUOTA_EXCEEDED = "Quota exceeded: Cannot assign %s entities at once. The maximum is %s."; + private QuotaHelper() { // no need to instantiate this class } @@ -44,7 +46,7 @@ public final class QuotaHelper { * @param parentType * The type of the parent entity. * - * @throws QuotaExceededException + * @throws AssignmentQuotaExceededException * if the assignment operation would cause the quota to be * exceeded */ @@ -72,7 +74,7 @@ public final class QuotaHelper { * Function to count the entities that are currently assigned to * the parent entity. * - * @throws QuotaExceededException + * @throws AssignmentQuotaExceededException * if the assignment operation would cause the quota to be * exceeded */ @@ -100,7 +102,7 @@ public final class QuotaHelper { * Function to count the entities that are currently assigned to * the parent entity. * - * @throws QuotaExceededException + * @throws AssignmentQuotaExceededException * if the assignment operation would cause the quota to be * exceeded */ @@ -117,7 +119,7 @@ public final class QuotaHelper { final String parentIdStr = parentId != null ? String.valueOf(parentId) : ""; LOG.warn("Cannot assign {} {} entities to {} '{}' because of the configured quota limit {}.", requested, type, parentType, parentIdStr, limit); - throw new QuotaExceededException(type, parentType, parentId, requested, limit); + throw new AssignmentQuotaExceededException(type, parentType, parentId, requested, limit); } if (parentId != null && countFct != null) { @@ -126,7 +128,7 @@ public final class QuotaHelper { LOG.warn( "Cannot assign {} {} entities to {} '{}' because of the configured quota limit {}. Currently, there are {} {} entities assigned.", requested, type, parentType, parentId, limit, currentCount, type); - throw new QuotaExceededException(type, parentType, parentId, requested, limit); + throw new AssignmentQuotaExceededException(type, parentType, parentId, requested, limit); } } } @@ -142,10 +144,9 @@ public final class QuotaHelper { */ public static void assertAssignmentRequestSizeQuota(final long requested, final long limit) { if (requested > limit) { - final String message = String.format( - "Quota exceeded: Cannot assign %s entities at once. The maximum is %s.", requested, limit); + final String message = String.format(MAX_ASSIGNMENT_QUOTA_EXCEEDED, requested, limit); LOG.warn(message); - throw new QuotaExceededException(message); + throw new AssignmentQuotaExceededException(message); } } } 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 9a9e544a0..3e6387836 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 @@ -30,8 +30,10 @@ import org.eclipse.hawkbit.im.authentication.SpPermission; import org.eclipse.hawkbit.repository.ArtifactManagement; import org.eclipse.hawkbit.repository.event.remote.SoftwareModuleDeletedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent; +import org.eclipse.hawkbit.repository.exception.FileSizeQuotaExceededException; import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; +import org.eclipse.hawkbit.repository.exception.StorageQuotaExceededException; import org.eclipse.hawkbit.repository.jpa.model.JpaArtifact; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; import org.eclipse.hawkbit.repository.model.Artifact; @@ -183,7 +185,7 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { assertThat(artifactRepository.findBySoftwareModuleId(PAGE, smId).getTotalElements()).isEqualTo(maxArtifacts); // create one mode to trigger the quota exceeded error - assertThatExceptionOfType(QuotaExceededException.class) + assertThatExceptionOfType(AssignmentQuotaExceededException.class) .isThrownBy(() -> createArtifactForSoftwareModule("file" + maxArtifacts, smId, artifactSize)); // delete one of the artifacts @@ -217,7 +219,7 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { // upload one more artifact to trigger the quota exceeded error final JpaSoftwareModule sm = softwareModuleRepository .save(new JpaSoftwareModule(osType, "smd" + numArtifacts, "1.0", null, null)); - assertThatExceptionOfType(QuotaExceededException.class) + assertThatExceptionOfType(StorageQuotaExceededException.class) .isThrownBy(() -> createArtifactForSoftwareModule("file" + numArtifacts, sm.getId(), artifactSize)); // delete one of the artifacts @@ -227,18 +229,6 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { createArtifactForSoftwareModule("fileXYZ", sm.getId(), artifactSize); } - @Test - @Description("Verifies that the quota specifying the maximum artifact storage is enforced (across software modules).") - public void createArtifactWhichExceedsMaxStorage() throws IOException { - - // create one artifact which exceeds the storage quota at once - final long maxBytes = quotaManagement.getMaxArtifactStorage(); - final JpaSoftwareModule sm = softwareModuleRepository - .save(new JpaSoftwareModule(osType, "smd345", "1.0", null, null)); - assertThatExceptionOfType(QuotaExceededException.class).isThrownBy( - () -> createArtifactForSoftwareModule("file345", sm.getId(), Math.toIntExact(maxBytes) + 128)); - } - @Test @Description("Verifies that you cannot create artifacts which exceed the configured maximum size.") public void createArtifactFailsIfTooLarge() { @@ -249,7 +239,7 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest { // create an artifact that exceeds the configured quota final long maxSize = quotaManagement.getMaxArtifactSize(); - assertThatExceptionOfType(QuotaExceededException.class) + assertThatExceptionOfType(FileSizeQuotaExceededException.class) .isThrownBy(() -> createArtifactForSoftwareModule("file", sm1.getId(), Math.toIntExact(maxSize) + 8)); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ControllerManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ControllerManagementTest.java index ebc7dc7d7..e1c18f02e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ControllerManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ControllerManagementTest.java @@ -53,7 +53,7 @@ import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.InvalidTargetAttributeException; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.Status; @@ -989,7 +989,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest { final int allowedAttributes = quotaManagement.getMaxAttributeEntriesPerTarget(); testdataFactory.createTarget(controllerId); - assertThatExceptionOfType(QuotaExceededException.class).isThrownBy(() -> securityRule + assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> securityRule .runAs(WithSpringAuthorityRule.withController("controller", CONTROLLER_ROLE_ANONYMOUS), () -> { writeAttributes(controllerId, allowedAttributes + 1, "key", "value"); return null; @@ -1008,7 +1008,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest { assertThat(targetManagement.getControllerAttributes(controllerId)).hasSize(10); // Now rite one more - assertThatExceptionOfType(QuotaExceededException.class).isThrownBy(() -> securityRule + assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> securityRule .runAs(WithSpringAuthorityRule.withController("controller", CONTROLLER_ROLE_ANONYMOUS), () -> { writeAttributes(controllerId, 1, "additional", "value1"); return null; @@ -1071,7 +1071,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest { final Long actionId = createTargetAndAssignDs(); // Fails as one entry is already in there from the assignment - assertThatExceptionOfType(QuotaExceededException.class).isThrownBy(() -> securityRule + assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> securityRule .runAs(WithSpringAuthorityRule.withController("controller", CONTROLLER_ROLE_ANONYMOUS), () -> { writeStatus(actionId, allowStatusEntries); return null; @@ -1127,7 +1127,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest { controllerManagement.addInformationalActionStatus(entityFactory.actionStatus().create(actionId1) .status(Status.WARNING).message("Msg " + i).occurredAt(System.currentTimeMillis())); } - assertThatExceptionOfType(QuotaExceededException.class).isThrownBy(() -> controllerManagement + assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> controllerManagement .addInformationalActionStatus(entityFactory.actionStatus().create(actionId1).status(Status.WARNING))); // test for update status (and mixed case) @@ -1138,7 +1138,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest { controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId2) .status(Status.WARNING).message("Msg " + i).occurredAt(System.currentTimeMillis())); } - assertThatExceptionOfType(QuotaExceededException.class).isThrownBy(() -> controllerManagement + assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> controllerManagement .addInformationalActionStatus(entityFactory.actionStatus().create(actionId2).status(Status.WARNING))); } @@ -1165,7 +1165,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest { entityFactory.actionStatus().create(actionId).messages(messages).status(Status.WARNING))).isNotNull(); messages.add("msg"); - assertThatExceptionOfType(QuotaExceededException.class) + assertThatExceptionOfType(AssignmentQuotaExceededException.class) .isThrownBy(() -> controllerManagement.addInformationalActionStatus( entityFactory.actionStatus().create(actionId).messages(messages).status(Status.WARNING))); @@ -1262,7 +1262,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest { assertThat(actionRepository.activeActionExistsForControllerId(DEFAULT_CONTROLLER_ID)).isEqualTo(false); } - @Test(expected = QuotaExceededException.class) + @Test(expected = AssignmentQuotaExceededException.class) @Description("Verifies that quota is asserted when a controller reports too many DOWNLOADED events for a " + "DOWNLOAD_ONLY action.") @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), @@ -1297,17 +1297,17 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest { final Long actionId = createAndAssignDsAsDownloadOnly("downloadOnlyDs", DEFAULT_CONTROLLER_ID); assertThat(actionId).isNotNull(); - assertThatExceptionOfType(QuotaExceededException.class) + assertThatExceptionOfType(AssignmentQuotaExceededException.class) .as("No QuotaExceededException thrown for too many DOWNLOADED updateActionStatus updates") .isThrownBy(() -> IntStream.range(0, maxMessages).forEach(i -> controllerManagement .addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.DOWNLOADED)))); - assertThatExceptionOfType(QuotaExceededException.class) + assertThatExceptionOfType(AssignmentQuotaExceededException.class) .as("No QuotaExceededException thrown for too many ERROR updateActionStatus updates") .isThrownBy(() -> IntStream.range(0, maxMessages).forEach(i -> controllerManagement .addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.ERROR)))); - assertThatExceptionOfType(QuotaExceededException.class) + assertThatExceptionOfType(AssignmentQuotaExceededException.class) .as("No QuotaExceededException thrown for too many FINISHED updateActionStatus updates") .isThrownBy(() -> IntStream.range(0, maxMessages).forEach(i -> controllerManagement .addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.FINISHED)))); @@ -1325,17 +1325,17 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest { final Long actionId = createTargetAndAssignDs(); assertThat(actionId).isNotNull(); - assertThatExceptionOfType(QuotaExceededException.class) + assertThatExceptionOfType(AssignmentQuotaExceededException.class) .as("No QuotaExceededException thrown for too many DOWNLOADED updateActionStatus updates") .isThrownBy( ()-> IntStream.range(0, maxMessages).forEach(i -> controllerManagement .addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.DOWNLOADED)))); - assertThatExceptionOfType(QuotaExceededException.class) + assertThatExceptionOfType(AssignmentQuotaExceededException.class) .as("No QuotaExceededException thrown for too many ERROR updateActionStatus updates") .isThrownBy(()->IntStream.range(0, maxMessages).forEach(i -> controllerManagement .addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.ERROR)))); - assertThatExceptionOfType(QuotaExceededException.class) + assertThatExceptionOfType(AssignmentQuotaExceededException.class) .as("No QuotaExceededException thrown for too many FINISHED updateActionStatus updates") .isThrownBy(()->IntStream.range(0, maxMessages).forEach(i -> controllerManagement .addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Status.FINISHED)))); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DeploymentManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DeploymentManagementTest.java index b0e8eb169..4de4ea3e0 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DeploymentManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DeploymentManagementTest.java @@ -39,7 +39,7 @@ import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.ForceQuitActionNotAllowedException; import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException; import org.eclipse.hawkbit.repository.exception.MultiAssignmentIsNotEnabledException; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.jpa.configuration.Constants; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus; @@ -170,7 +170,7 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest { .singletonList(new SimpleEntry(testTarget.getControllerId(), ds1.getId()))); } - assertThatExceptionOfType(QuotaExceededException.class) + assertThatExceptionOfType(AssignmentQuotaExceededException.class) .isThrownBy(() -> assignDistributionSet(ds1, Collections.singletonList(testTarget))); } @@ -185,7 +185,7 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest { assignDistributionSet(ds1, targets); targets.add(testdataFactory.createTarget("assignmentTest2")); - assertThatExceptionOfType(QuotaExceededException.class).isThrownBy(() -> assignDistributionSet(ds2, targets)); + assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> assignDistributionSet(ds2, targets)); } @Test @@ -671,7 +671,7 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest { DeploymentManagement.deploymentRequest(controllerId, dsId).build()); enableMultiAssignments(); - Assertions.assertThatExceptionOfType(QuotaExceededException.class) + Assertions.assertThatExceptionOfType(AssignmentQuotaExceededException.class) .isThrownBy(() -> deploymentManagement.assignDistributionSets(deploymentRequests)); assertThat(actionRepository.countByTargetControllerId(controllerId)).isEqualTo(0); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DistributionSetManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DistributionSetManagementTest.java index 1bb90e3bf..1f2720b39 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DistributionSetManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DistributionSetManagementTest.java @@ -34,7 +34,7 @@ import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedE import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata; @@ -351,7 +351,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest { } // quota exceeded - assertThatExceptionOfType(QuotaExceededException.class) + assertThatExceptionOfType(AssignmentQuotaExceededException.class) .isThrownBy(() -> createDistributionSetMetadata(ds1.getId(), createDistributionSetMetadata(ds1.getId(), new JpaDistributionSetMetadata("k" + maxMetaData, ds1, "v" + maxMetaData)))); @@ -362,7 +362,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest { metaData2.add(new JpaDistributionSetMetadata("k" + i, ds2, "v" + i)); } // verify quota is exceeded - assertThatExceptionOfType(QuotaExceededException.class) + assertThatExceptionOfType(AssignmentQuotaExceededException.class) .isThrownBy(() -> createDistributionSetMetadata(ds2.getId(), metaData2)); // add some meta data entries @@ -378,7 +378,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest { metaData3.add(new JpaDistributionSetMetadata("kk" + i, ds3, "vv" + i)); } // verify quota is exceeded - assertThatExceptionOfType(QuotaExceededException.class) + assertThatExceptionOfType(AssignmentQuotaExceededException.class) .isThrownBy(() -> createDistributionSetMetadata(ds3.getId(), metaData3)); } @@ -510,7 +510,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest { distributionSetManagement.assignSoftwareModules(ds1.getId(), Collections.singletonList(modules.get(i))); } // add one more to cause the quota to be exceeded - assertThatExceptionOfType(QuotaExceededException.class).isThrownBy(() -> { + assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> { distributionSetManagement.assignSoftwareModules(ds1.getId(), Collections.singletonList(modules.get(maxModules))); }); @@ -518,7 +518,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest { // assign all software modules at once final DistributionSet ds2 = testdataFactory.createDistributionSetWithNoSoftwareModules("ds2", "1.0"); // verify quota is exceeded - assertThatExceptionOfType(QuotaExceededException.class) + assertThatExceptionOfType(AssignmentQuotaExceededException.class) .isThrownBy(() -> distributionSetManagement.assignSoftwareModules(ds2.getId(), modules)); // assign some software modules @@ -528,7 +528,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest { distributionSetManagement.assignSoftwareModules(ds3.getId(), Collections.singletonList(modules.get(i))); } // assign the remaining modules to cause the quota to be exceeded - assertThatExceptionOfType(QuotaExceededException.class).isThrownBy(() -> distributionSetManagement + assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> distributionSetManagement .assignSoftwareModules(ds3.getId(), modules.subList(firstHalf, modules.size()))); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DistributionSetTypeManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DistributionSetTypeManagementTest.java index c6245abcb..77d4ffb2d 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DistributionSetTypeManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DistributionSetTypeManagementTest.java @@ -28,7 +28,7 @@ import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetTypeCre import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetUpdatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent; import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetType; @@ -242,9 +242,9 @@ public class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTes // assign all types at once final DistributionSetType dsType1 = distributionSetTypeManagement .create(entityFactory.distributionSetType().create().key("dst1").name("dst1")); - assertThatExceptionOfType(QuotaExceededException.class).isThrownBy( + assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy( () -> distributionSetTypeManagement.assignMandatorySoftwareModuleTypes(dsType1.getId(), moduleTypeIds)); - assertThatExceptionOfType(QuotaExceededException.class).isThrownBy( + assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy( () -> distributionSetTypeManagement.assignOptionalSoftwareModuleTypes(dsType1.getId(), moduleTypeIds)); // assign as many mandatory modules as possible @@ -256,7 +256,7 @@ public class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTes assertThat(distributionSetTypeManagement.get(dsType2.getId()).get().getMandatoryModuleTypes().size()) .isEqualTo(quota); // assign one more to trigger the quota exceeded error - assertThatExceptionOfType(QuotaExceededException.class) + assertThatExceptionOfType(AssignmentQuotaExceededException.class) .isThrownBy(() -> distributionSetTypeManagement.assignMandatorySoftwareModuleTypes(dsType2.getId(), Collections.singletonList(moduleTypeIds.get(quota)))); @@ -269,7 +269,7 @@ public class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTes assertThat(distributionSetTypeManagement.get(dsType3.getId()).get().getOptionalModuleTypes().size()) .isEqualTo(quota); // assign one more to trigger the quota exceeded error - assertThatExceptionOfType(QuotaExceededException.class) + assertThatExceptionOfType(AssignmentQuotaExceededException.class) .isThrownBy(() -> distributionSetTypeManagement.assignOptionalSoftwareModuleTypes(dsType3.getId(), Collections.singletonList(moduleTypeIds.get(quota)))); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RolloutManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RolloutManagementTest.java index 8692de35f..b4376001f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RolloutManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RolloutManagementTest.java @@ -42,7 +42,7 @@ import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.jpa.model.JpaRollout; @@ -1348,7 +1348,7 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest { .errorCondition(RolloutGroupErrorCondition.THRESHOLD, errorCondition) .errorAction(RolloutGroupErrorAction.PAUSE, null).build(); - assertThatExceptionOfType(QuotaExceededException.class).isThrownBy(() -> rolloutManagement.create( + assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> rolloutManagement.create( entityFactory.rollout().create().name(rolloutName).description(rolloutName) .targetFilterQuery("controllerId==" + targetPrefixName + "-*").set(distributionSet), amountGroups, conditions)); @@ -1376,7 +1376,7 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest { .targetPercentage(100.0F); // group1 exceeds the quota - assertThatExceptionOfType(QuotaExceededException.class).isThrownBy(() -> rolloutManagement.create( + assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> rolloutManagement.create( entityFactory.rollout().create().name(rolloutName).description(rolloutName) .targetFilterQuery("controllerId==" + targetPrefixName + "-*").set(distributionSet), Arrays.asList(group1, group2), conditions)); @@ -1388,7 +1388,7 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest { .targetPercentage(100.0F); // group4 exceeds the quota - assertThatExceptionOfType(QuotaExceededException.class).isThrownBy(() -> rolloutManagement.create( + assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> rolloutManagement.create( entityFactory.rollout().create().name(rolloutName).description(rolloutName) .targetFilterQuery("controllerId==" + targetPrefixName + "-*").set(distributionSet), Arrays.asList(group3, group4), conditions)); @@ -1571,7 +1571,7 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest { final RolloutGroupConditions conditions = new RolloutGroupConditionBuilder().withDefaults().build(); final RolloutCreate rollout = generateTargetsAndRollout(rolloutName, targets); - assertThatExceptionOfType(QuotaExceededException.class) + assertThatExceptionOfType(AssignmentQuotaExceededException.class) .isThrownBy(() -> rolloutManagement.create(rollout, maxGroups + 1, conditions)) .withMessageContaining("not be greater than " + maxGroups); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleManagementTest.java index 3a385cb44..7c0ae2581 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleManagementTest.java @@ -24,7 +24,7 @@ import org.apache.commons.lang3.RandomUtils; import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataCreate; import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleMetadata; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; @@ -676,7 +676,7 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { } // quota exceeded - assertThatExceptionOfType(QuotaExceededException.class) + assertThatExceptionOfType(AssignmentQuotaExceededException.class) .isThrownBy(() -> softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata() .create(module.getId()).key("k" + maxMetaData).value("v" + maxMetaData))); @@ -687,7 +687,7 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { create.add(entityFactory.softwareModuleMetadata().create(module2.getId()).key("k" + i).value("v" + i)); } // quota exceeded - assertThatExceptionOfType(QuotaExceededException.class) + assertThatExceptionOfType(AssignmentQuotaExceededException.class) .isThrownBy(() -> softwareModuleManagement.createMetaData(create)); // add some meta data entries @@ -704,7 +704,7 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { create2.add(entityFactory.softwareModuleMetadata().create(module3.getId()).key("kk" + i).value("vv" + i)); } // quota exceeded - assertThatExceptionOfType(QuotaExceededException.class) + assertThatExceptionOfType(AssignmentQuotaExceededException.class) .isThrownBy(() -> softwareModuleManagement.createMetaData(create2)); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetFilterQueryManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetFilterQueryManagementTest.java index 6ee867a96..f6c91ff7b 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetFilterQueryManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetFilterQueryManagementTest.java @@ -28,7 +28,7 @@ import org.eclipse.hawkbit.repository.event.remote.entity.TargetFilterQueryCreat import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignActionTypeException; import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignDistributionSetException; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -112,7 +112,7 @@ public class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest final DistributionSet set = testdataFactory.createDistributionSet(); // creation is supposed to work as there is no distribution set - assertThatExceptionOfType(QuotaExceededException.class) + assertThatExceptionOfType(AssignmentQuotaExceededException.class) .isThrownBy(() -> targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create() .name("testfilter").autoAssignDistributionSet(set.getId()).query("name==target*"))); } @@ -282,7 +282,7 @@ public class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest // assigning a distribution set is supposed to fail as the query // addresses too many targets - assertThatExceptionOfType(QuotaExceededException.class).isThrownBy(() -> targetFilterQueryManagement + assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> targetFilterQueryManagement .updateAutoAssignDS(targetFilterQuery.getId(), distributionSet.getId())); } @@ -300,7 +300,7 @@ public class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest .create().name("testfilter").autoAssignDistributionSet(set.getId()).query("name==foo")); // update with a query string that addresses too many targets - assertThatExceptionOfType(QuotaExceededException.class).isThrownBy(() -> targetFilterQueryManagement + assertThatExceptionOfType(AssignmentQuotaExceededException.class).isThrownBy(() -> targetFilterQueryManagement .update(entityFactory.targetFilterQuery().update(targetFilterQuery.getId()).query("name==target*"))); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementTest.java index 23949c2e3..3bb78a538 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementTest.java @@ -41,7 +41,7 @@ import org.eclipse.hawkbit.repository.event.remote.entity.TargetTagCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.InvalidTargetAddressException; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.TenantNotExistException; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetMetadata; @@ -958,7 +958,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest { } // quota exceeded - assertThatExceptionOfType(QuotaExceededException.class) + assertThatExceptionOfType(AssignmentQuotaExceededException.class) .isThrownBy(() -> insertTargetMetadata("k" + maxMetaData, "v" + maxMetaData, target1)); // add multiple meta data entries at once @@ -968,7 +968,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest { metaData2.add(new JpaTargetMetadata("k" + i, "v" + i, target2)); } // verify quota is exceeded - assertThatExceptionOfType(QuotaExceededException.class) + assertThatExceptionOfType(AssignmentQuotaExceededException.class) .isThrownBy(() -> targetManagement.createMetaData(target2.getControllerId(), metaData2)); // add some meta data entries @@ -984,7 +984,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest { metaData3.add(new JpaTargetMetadata("kk" + i, "vv" + i, target3)); } // verify quota is exceeded - assertThatExceptionOfType(QuotaExceededException.class) + assertThatExceptionOfType(AssignmentQuotaExceededException.class) .isThrownBy(() -> targetManagement.createMetaData(target3.getControllerId(), metaData3)); } diff --git a/hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiConfigDataTest.java b/hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiConfigDataTest.java index 8e675ce65..2abb328a3 100644 --- a/hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiConfigDataTest.java +++ b/hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiConfigDataTest.java @@ -25,7 +25,7 @@ import java.util.Map; import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants; import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.repository.exception.InvalidTargetAttributeException; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.rest.util.JsonBuilder; import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter; @@ -155,7 +155,7 @@ public class DdiConfigDataTest extends AbstractDDiApiIntegrationTest { mvc.perform(put("/{tenant}/controller/v1/4717/configData", tenantAware.getCurrentTenant()) .content(JsonBuilder.configData("", attributes, "closed").toString()) .contentType(MediaType.APPLICATION_JSON)).andExpect(status().isForbidden()) - .andExpect(jsonPath("$.exceptionClass", equalTo(QuotaExceededException.class.getName()))) + .andExpect(jsonPath("$.exceptionClass", equalTo(AssignmentQuotaExceededException.class.getName()))) .andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey()))); } diff --git a/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResourceTest.java b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResourceTest.java index 3f0af689d..e8ef170fb 100644 --- a/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResourceTest.java +++ b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResourceTest.java @@ -34,7 +34,7 @@ import org.apache.commons.lang3.RandomStringUtils; import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtActionType; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -210,7 +210,7 @@ public class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegr .contentType(MediaType.APPLICATION_JSON) .content(JsonBuilder.ids(Collections.singletonList(moduleIDs.get(moduleIDs.size() - 1))))) .andDo(MockMvcResultPrinter.print()).andExpect(status().isForbidden()) - .andExpect(jsonPath("$.exceptionClass", equalTo(QuotaExceededException.class.getName()))) + .andExpect(jsonPath("$.exceptionClass", equalTo(AssignmentQuotaExceededException.class.getName()))) .andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey()))); // verify quota is also enforced for bulk uploads @@ -218,7 +218,7 @@ public class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegr mvc.perform(post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/" + disSet2.getId() + "/assignedSM") .contentType(MediaType.APPLICATION_JSON).content(JsonBuilder.ids(moduleIDs))) .andDo(MockMvcResultPrinter.print()).andExpect(status().isForbidden()) - .andExpect(jsonPath("$.exceptionClass", equalTo(QuotaExceededException.class.getName()))) + .andExpect(jsonPath("$.exceptionClass", equalTo(AssignmentQuotaExceededException.class.getName()))) .andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey()))); // verify size is still 0 diff --git a/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTypeResourceTest.java b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTypeResourceTest.java index 435ae12af..b813817ae 100644 --- a/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTypeResourceTest.java +++ b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTypeResourceTest.java @@ -31,7 +31,7 @@ import org.assertj.core.util.Lists; import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeCreate; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.NamedEntity; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; @@ -274,7 +274,7 @@ public class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIn .content("{\"id\":" + moduleTypeIds.get(moduleTypeIds.size() - 1) + "}") .contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()) .andExpect(status().isForbidden()) - .andExpect(jsonPath("$.exceptionClass", equalTo(QuotaExceededException.class.getName()))) + .andExpect(jsonPath("$.exceptionClass", equalTo(AssignmentQuotaExceededException.class.getName()))) .andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey()))); // verify quota enforcement for mandatory module types @@ -293,7 +293,7 @@ public class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIn .content("{\"id\":" + moduleTypeIds.get(moduleTypeIds.size() - 1) + "}") .contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()) .andExpect(status().isForbidden()) - .andExpect(jsonPath("$.exceptionClass", equalTo(QuotaExceededException.class.getName()))) + .andExpect(jsonPath("$.exceptionClass", equalTo(AssignmentQuotaExceededException.class.getName()))) .andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey()))); } diff --git a/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResourceTest.java b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResourceTest.java index 7835531e8..d0ca9eb1e 100644 --- a/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResourceTest.java +++ b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResourceTest.java @@ -31,7 +31,7 @@ import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; import org.eclipse.hawkbit.repository.RolloutGroupManagement; import org.eclipse.hawkbit.repository.RolloutManagement; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Rollout; @@ -147,7 +147,7 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes new RolloutGroupConditionBuilder().withDefaults().build())) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print()).andExpect(status().isForbidden()) - .andExpect(jsonPath("$.exceptionClass", equalTo(QuotaExceededException.class.getName()))) + .andExpect(jsonPath("$.exceptionClass", equalTo(AssignmentQuotaExceededException.class.getName()))) .andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey()))); } @@ -165,7 +165,7 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes new RolloutGroupConditionBuilder().withDefaults().build())) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print()).andExpect(status().isForbidden()) - .andExpect(jsonPath("$.exceptionClass", equalTo(QuotaExceededException.class.getName()))) + .andExpect(jsonPath("$.exceptionClass", equalTo(AssignmentQuotaExceededException.class.getName()))) .andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey()))); } diff --git a/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java index bbb52df02..7856f3379 100644 --- a/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java +++ b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java @@ -37,7 +37,9 @@ import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.mgmt.json.model.artifact.MgmtArtifact; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; import org.eclipse.hawkbit.repository.Constants; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; +import org.eclipse.hawkbit.repository.exception.FileSizeQuotaExceededException; +import org.eclipse.hawkbit.repository.exception.StorageQuotaExceededException; import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.ArtifactUpload; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -205,7 +207,9 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra // try to upload mvc.perform(fileUpload("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file) .accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()) - .andExpect(status().isForbidden()); + .andExpect(status().isForbidden()) + .andExpect(jsonPath("$.exceptionClass", equalTo(FileSizeQuotaExceededException.class.getName()))) + .andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_FILE_SIZE_QUOTA_EXCEEDED.getKey()))); } @Test @@ -385,7 +389,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra mvc.perform(fileUpload("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file) .accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()) .andExpect(status().isForbidden()) - .andExpect(jsonPath("$.exceptionClass", equalTo(QuotaExceededException.class.getName()))) + .andExpect(jsonPath("$.exceptionClass", equalTo(AssignmentQuotaExceededException.class.getName()))) .andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey()))); } @@ -430,8 +434,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra mvc.perform(fileUpload("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file) .accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()) .andExpect(status().isForbidden()) - .andExpect(jsonPath("$.exceptionClass", equalTo(QuotaExceededException.class.getName()))) - .andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey()))); + .andExpect(jsonPath("$.exceptionClass", equalTo(StorageQuotaExceededException.class.getName()))) + .andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_STORAGE_QUOTA_EXCEEDED.getKey()))); } diff --git a/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetFilterQueryResourceTest.java b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetFilterQueryResourceTest.java index fdeadcbd1..03d232ad7 100644 --- a/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetFilterQueryResourceTest.java +++ b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetFilterQueryResourceTest.java @@ -25,13 +25,12 @@ import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtActionType; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignActionTypeException; import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignDistributionSetException; -import org.eclipse.hawkbit.repository.exception.QuotaExceededException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.rest.exception.MessageNotReadableException; import org.eclipse.hawkbit.rest.json.model.ExceptionInfo; -import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter; import org.json.JSONObject; import org.junit.Test; import org.springframework.http.MediaType; @@ -313,7 +312,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte post(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + filterQuery.getId() + "/autoAssignDS") .content("{\"id\":" + set.getId() + "}").contentType(MediaType.APPLICATION_JSON)) .andDo(print()).andExpect(status().isForbidden()) - .andExpect(jsonPath(JSON_PATH_EXCEPTION_CLASS, equalTo(QuotaExceededException.class.getName()))) + .andExpect(jsonPath(JSON_PATH_EXCEPTION_CLASS, equalTo(AssignmentQuotaExceededException.class.getName()))) .andExpect(jsonPath(JSON_PATH_ERROR_CODE, equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey()))); } @@ -345,7 +344,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte mvc.perform(put(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + filterQuery.getId()) .content("{\"query\":\"controllerId==target*\"}").contentType(MediaType.APPLICATION_JSON)) .andDo(print()).andExpect(status().isForbidden()) - .andExpect(jsonPath(JSON_PATH_EXCEPTION_CLASS, equalTo(QuotaExceededException.class.getName()))) + .andExpect(jsonPath(JSON_PATH_EXCEPTION_CLASS, equalTo(AssignmentQuotaExceededException.class.getName()))) .andExpect(jsonPath(JSON_PATH_ERROR_CODE, equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey()))); } diff --git a/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/ResponseExceptionHandler.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/ResponseExceptionHandler.java index 5d484405d..f35381d83 100644 --- a/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/ResponseExceptionHandler.java +++ b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/ResponseExceptionHandler.java @@ -61,6 +61,8 @@ public class ResponseExceptionHandler { ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_DELETE_FAILED, HttpStatus.INTERNAL_SERVER_ERROR); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_LOAD_FAILED, HttpStatus.INTERNAL_SERVER_ERROR); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_QUOTA_EXCEEDED, HttpStatus.FORBIDDEN); + ERROR_TO_HTTP_STATUS.put(SpServerError.SP_FILE_SIZE_QUOTA_EXCEEDED, HttpStatus.FORBIDDEN); + ERROR_TO_HTTP_STATUS.put(SpServerError.SP_STORAGE_QUOTA_EXCEEDED, HttpStatus.FORBIDDEN); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ACTION_NOT_CANCELABLE, HttpStatus.METHOD_NOT_ALLOWED); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ACTION_NOT_FORCE_QUITABLE, HttpStatus.METHOD_NOT_ALLOWED); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_DS_CREATION_FAILED_MISSING_MODULE, HttpStatus.BAD_REQUEST); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/AbstractFileTransferHandler.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/AbstractFileTransferHandler.java index cb260814b..255ea33af 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/AbstractFileTransferHandler.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/AbstractFileTransferHandler.java @@ -14,14 +14,18 @@ import java.io.OutputStream; import java.io.Serializable; import java.util.Optional; import java.util.concurrent.ExecutorService; +import java.util.concurrent.locks.Lock; import org.apache.commons.lang3.StringUtils; import org.eclipse.hawkbit.repository.ArtifactManagement; import org.eclipse.hawkbit.repository.RegexCharacterCollection; import org.eclipse.hawkbit.repository.RegexCharacterCollection.RegexChar; import org.eclipse.hawkbit.repository.exception.ArtifactUploadFailedException; +import org.eclipse.hawkbit.repository.exception.FileSizeQuotaExceededException; import org.eclipse.hawkbit.repository.exception.InvalidMD5HashException; import org.eclipse.hawkbit.repository.exception.InvalidSHA1HashException; +import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; +import org.eclipse.hawkbit.repository.exception.StorageQuotaExceededException; import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.ArtifactUpload; import org.eclipse.hawkbit.repository.model.SoftwareModule; @@ -36,7 +40,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.vaadin.spring.events.EventBus; import org.vaadin.spring.events.EventBus.UIEventBus; - import com.vaadin.ui.UI; /** @@ -48,6 +51,7 @@ public abstract class AbstractFileTransferHandler implements Serializable { private static final long serialVersionUID = 1L; private static final Logger LOG = LoggerFactory.getLogger(AbstractFileTransferHandler.class); + private static final String MESSAGE_UPLOAD_FAILED = "message.upload.failed"; private volatile boolean uploadInterrupted; @@ -63,15 +67,18 @@ public abstract class AbstractFileTransferHandler implements Serializable { protected final UINotification uiNotification; + private final transient Lock uploadLock; + protected static final RegexCharacterCollection ILLEGAL_FILENAME_CHARACTERS = new RegexCharacterCollection( RegexChar.GREATER_THAN, RegexChar.LESS_THAN, RegexChar.SLASHES); - AbstractFileTransferHandler(final ArtifactManagement artifactManagement, final VaadinMessageSource i18n) { + AbstractFileTransferHandler(final ArtifactManagement artifactManagement, final VaadinMessageSource i18n, final Lock uploadLock) { this.artifactManagement = artifactManagement; this.i18n = i18n; this.eventBus = SpringContextHelper.getBean(EventBus.UIEventBus.class); this.artifactUploadState = SpringContextHelper.getBean(ArtifactUploadState.class); this.uiNotification = SpringContextHelper.getBean(UINotification.class); + this.uploadLock = uploadLock; } protected boolean isUploadInterrupted() { @@ -94,7 +101,7 @@ public abstract class AbstractFileTransferHandler implements Serializable { protected void startTransferToRepositoryThread(final InputStream inputStream, final FileUploadId fileUploadId, final String mimeType) { SpringContextHelper.getBean("asyncExecutor", ExecutorService.class).execute( - new TransferArtifactToRepositoryRunnable(inputStream, fileUploadId, mimeType, UI.getCurrent())); + new TransferArtifactToRepositoryRunnable(inputStream, fileUploadId, mimeType, UI.getCurrent(), uploadLock)); } private void interruptUploadAndSetReason(final String failureReason) { @@ -103,7 +110,19 @@ public abstract class AbstractFileTransferHandler implements Serializable { } protected void interruptUploadDueToUploadFailed() { - interruptUploadAndSetReason(i18n.getMessage("message.upload.failed")); + interruptUploadAndSetReason(i18n.getMessage(MESSAGE_UPLOAD_FAILED)); + } + + protected void interruptUploadDueToAssignmentQuotaExceeded() { + interruptUploadAndSetReason(i18n.getMessage("message.upload.assignmentQuota")); + } + + protected void interruptUploadDueToFileSizeQuotaExceeded(final String exceededValue) { + interruptUploadAndSetReason(i18n.getMessage("message.upload.fileSizeQuota", exceededValue)); + } + + protected void interruptUploadDueToStorageQuotaExceeded(final String exceededValue) { + interruptUploadAndSetReason(i18n.getMessage("message.upload.storageQuota", exceededValue)); } protected void interruptUploadDueToDuplicateFile() { @@ -177,7 +196,7 @@ public abstract class AbstractFileTransferHandler implements Serializable { final FileUploadProgress fileUploadProgress = new FileUploadProgress(fileUploadId, FileUploadStatus.UPLOAD_FAILED, - StringUtils.isBlank(failureReason) ? i18n.getMessage("message.upload.failed") : failureReason); + StringUtils.isBlank(failureReason) ? i18n.getMessage(MESSAGE_UPLOAD_FAILED) : failureReason); artifactUploadState.updateFileUploadProgress(fileUploadId, fileUploadProgress); eventBus.publish(this, fileUploadProgress); publishUploadFinishedEvent(fileUploadId); @@ -216,26 +235,45 @@ public abstract class AbstractFileTransferHandler implements Serializable { private final FileUploadId fileUploadId; private final String mimeType; private final UI vaadinUi; + private final Lock uploadLock; public TransferArtifactToRepositoryRunnable(final InputStream inputStream, final FileUploadId fileUploadId, - final String mimeType, final UI vaadinUi) { + final String mimeType, final UI vaadinUi, final Lock uploadLock) { this.inputStream = inputStream; this.fileUploadId = fileUploadId; this.mimeType = mimeType; this.vaadinUi = vaadinUi; + this.uploadLock = uploadLock; } + /** + * a lock object is used here that is propagated down from + * {@link org.eclipse.hawkbit.ui.artifacts.UploadArtifactView}. It ensures that from within the same UI instance + * all uploads are executed sequentially to avoid issues that occur when multiple files are processed at the + * same time (e.g. regarding quota checks) + */ @Override public void run() { try { UI.setCurrent(vaadinUi); + uploadLock.lock(); streamToRepository(); + } catch (final FileSizeQuotaExceededException e) { + interruptUploadDueToFileSizeQuotaExceeded(e.getExceededQuotaValueString()); + LOG.debug("Upload failed due to file size quota exceeded:", e); + } catch (final StorageQuotaExceededException e) { + interruptUploadDueToStorageQuotaExceeded(e.getExceededQuotaValueString()); + LOG.debug("Upload failed due to storage quota exceeded:", e); + } catch (final AssignmentQuotaExceededException e) { + interruptUploadDueToAssignmentQuotaExceeded(); + LOG.debug("Upload failed due to assignment quota exceeded:", e); } catch (final RuntimeException e) { interruptUploadDueToUploadFailed(); publishUploadFailedAndFinishedEvent(fileUploadId, e); LOG.error("Failed to transfer file to repository", e); } finally { tryToCloseIOStream(inputStream); + uploadLock.unlock(); } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/FileTransferHandlerStreamVariable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/FileTransferHandlerStreamVariable.java index 36de30312..f2a9d0a94 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/FileTransferHandlerStreamVariable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/FileTransferHandlerStreamVariable.java @@ -12,6 +12,7 @@ import java.io.IOException; import java.io.OutputStream; import java.io.PipedInputStream; import java.io.PipedOutputStream; +import java.util.concurrent.locks.Lock; import org.eclipse.hawkbit.repository.ArtifactManagement; import org.eclipse.hawkbit.repository.RegexCharacterCollection; @@ -48,8 +49,8 @@ public class FileTransferHandlerStreamVariable extends AbstractFileTransferHandl FileTransferHandlerStreamVariable(final String fileName, final long fileSize, final long maxSize, final String mimeType, final SoftwareModule selectedSw, final ArtifactManagement artifactManagement, - final VaadinMessageSource i18n) { - super(artifactManagement, i18n); + final VaadinMessageSource i18n, final Lock uploadLock) { + super(artifactManagement, i18n, uploadLock); this.fileSize = fileSize; this.maxSize = maxSize; this.mimeType = mimeType; diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/FileTransferHandlerVaadinUpload.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/FileTransferHandlerVaadinUpload.java index b215ba8af..81701aed1 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/FileTransferHandlerVaadinUpload.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/FileTransferHandlerVaadinUpload.java @@ -12,6 +12,7 @@ import java.io.IOException; import java.io.OutputStream; import java.io.PipedInputStream; import java.io.PipedOutputStream; +import java.util.concurrent.locks.Lock; import org.eclipse.hawkbit.repository.ArtifactManagement; import org.eclipse.hawkbit.repository.RegexCharacterCollection; @@ -55,8 +56,8 @@ public class FileTransferHandlerVaadinUpload extends AbstractFileTransferHandler private volatile FileUploadId fileUploadId; FileTransferHandlerVaadinUpload(final long maxSize, final SoftwareModuleManagement softwareManagement, - final ArtifactManagement artifactManagement, final VaadinMessageSource i18n) { - super(artifactManagement, i18n); + final ArtifactManagement artifactManagement, final VaadinMessageSource i18n, final Lock uploadLock) { + super(artifactManagement, i18n, uploadLock); this.maxSize = maxSize; this.softwareModuleManagement = softwareManagement; } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadDropAreaLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadDropAreaLayout.java index d3d55265a..a6b89b7f5 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadDropAreaLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadDropAreaLayout.java @@ -42,6 +42,9 @@ import com.vaadin.ui.Label; import com.vaadin.ui.UI; import com.vaadin.ui.VerticalLayout; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + /** * Container for drag and drop area in the upload view. */ @@ -68,6 +71,8 @@ public class UploadDropAreaLayout extends AbstractComponent { private final UploadProgressButtonLayout uploadButtonLayout; + private final transient Lock uploadLock = new ReentrantLock(); + /** * Creates a new {@link UploadDropAreaLayout} instance. * @@ -99,7 +104,7 @@ public class UploadDropAreaLayout extends AbstractComponent { this.softwareManagement = softwareManagement; this.artifactManagement = artifactManagement; this.uploadButtonLayout = new UploadProgressButtonLayout(i18n, eventBus, artifactUploadState, - multipartConfigElement, artifactManagement, softwareManagement); + multipartConfigElement, artifactManagement, softwareManagement, uploadLock); buildLayout(); @@ -186,7 +191,7 @@ public class UploadDropAreaLayout extends AbstractComponent { } else { file.setStreamVariable(new FileTransferHandlerStreamVariable(file.getFileName(), file.getFileSize(), multipartConfigElement.getMaxFileSize(), file.getType(), softwareModule, artifactManagement, - i18n)); + i18n, uploadLock)); } } if (duplicateFound) { diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadProgressButtonLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadProgressButtonLayout.java index 0eae30f84..9848e4696 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadProgressButtonLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadProgressButtonLayout.java @@ -29,6 +29,8 @@ import com.vaadin.ui.Button; import com.vaadin.ui.UI; import com.vaadin.ui.VerticalLayout; +import java.util.concurrent.locks.Lock; + /** * Container for upload and progress button. */ @@ -54,6 +56,8 @@ public class UploadProgressButtonLayout extends VerticalLayout { private final ArtifactUploadState artifactUploadState; + private final transient Lock uploadLock; + /** * Creates a new {@link UploadProgressButtonLayout} instance. * @@ -71,10 +75,12 @@ public class UploadProgressButtonLayout extends VerticalLayout { * @param artifactManagement * the {@link ArtifactManagement} for storing the uploaded * artifacts + * @param uploadLock + * A common upload lock that enforced sequential upload within an UI instance */ public UploadProgressButtonLayout(final VaadinMessageSource i18n, final UIEventBus eventBus, final ArtifactUploadState artifactUploadState, final MultipartConfigElement multipartConfigElement, - final ArtifactManagement artifactManagement, final SoftwareModuleManagement softwareManagement) { + final ArtifactManagement artifactManagement, final SoftwareModuleManagement softwareManagement, final Lock uploadLock) { this.artifactUploadState = artifactUploadState; this.artifactManagement = artifactManagement; this.uploadInfoWindow = new UploadProgressInfoWindow(eventBus, artifactUploadState, i18n); @@ -89,6 +95,7 @@ public class UploadProgressButtonLayout extends VerticalLayout { this.multipartConfigElement = multipartConfigElement; this.softwareModuleManagement = softwareManagement; this.upload = new UploadFixed(); + this.uploadLock = uploadLock; createComponents(); buildLayout(); @@ -144,7 +151,7 @@ public class UploadProgressButtonLayout extends VerticalLayout { private void buildLayout() { final FileTransferHandlerVaadinUpload uploadHandler = new FileTransferHandlerVaadinUpload( - multipartConfigElement.getMaxFileSize(), softwareModuleManagement, artifactManagement, i18n); + multipartConfigElement.getMaxFileSize(), softwareModuleManagement, artifactManagement, i18n, uploadLock); upload.setButtonCaption(i18n.getMessage("upload.file")); upload.setImmediate(true); upload.setReceiver(uploadHandler); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/HawkbitUIErrorHandler.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/HawkbitUIErrorHandler.java index e07277d22..f25145560 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/HawkbitUIErrorHandler.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/HawkbitUIErrorHandler.java @@ -25,6 +25,7 @@ import com.vaadin.server.ClientConnector.ConnectorErrorEvent; import com.vaadin.server.DefaultErrorHandler; import com.vaadin.server.ErrorEvent; import com.vaadin.server.Page; +import com.vaadin.server.UploadException; import com.vaadin.shared.Connector; import com.vaadin.ui.Component; import com.vaadin.ui.Notification.Type; @@ -45,6 +46,11 @@ public class HawkbitUIErrorHandler extends DefaultErrorHandler { @Override public void error(final ErrorEvent event) { + // filter upload exceptions + if (event.getThrowable() instanceof UploadException) { + return; + } + final HawkbitErrorNotificationMessage message = buildNotification(getRootExceptionFrom(event)); if (event instanceof ConnectorErrorEvent) { final Connector connector = ((ConnectorErrorEvent) event).getConnector(); diff --git a/hawkbit-ui/src/main/resources/messages.properties b/hawkbit-ui/src/main/resources/messages.properties index 6e02df9bc..3948ecf94 100644 --- a/hawkbit-ui/src/main/resources/messages.properties +++ b/hawkbit-ui/src/main/resources/messages.properties @@ -465,7 +465,10 @@ message.no.duplicateFiles = Duplicate files selected message.delete.artifact = Are you sure you want to delete artifact {0} ? message.swModule.deleted = {0} Software Module(s) deleted message.error.swModule.notDeleted = Upload is running for Software Module(s) -message.upload.failed = Streaming Failed +message.upload.failed = Upload failed +message.upload.assignmentQuota = Max assignments per software module exceeded +message.upload.fileSizeQuota = Maximum artifact size ({0}) exceeded +message.upload.storageQuota = Storage quota exceeded, {0} left message.uploadedfile.size.exceeded = File size exceeded. Allowed size {0} bytes message.uploadedfile.illegalFilename = Filename contains illegal characters message.artifact.deleted = Artifact with file {0} deleted successfully