From 80d9f1b8fcc61f60fd97816462f413f74cb7c794 Mon Sep 17 00:00:00 2001 From: Kai Zimmermann Date: Sat, 16 Dec 2017 17:17:54 +0100 Subject: [PATCH] Software module metadata available to targets (in DMF and DDI) (#608) * Software module metadata can be configure as target visible. Signed-off-by: kaizimmerm * Added metadata to DDI. Signed-off-by: kaizimmerm * Managed by UI. Signed-off-by: kaizimmerm * Complete DMF integration and started UI. Signed-off-by: kaizimmerm * Add DMF tests and completed UI. Signed-off-by: kaizimmerm * Add RSQL test. Fix sonar issues. Signed-off-by: kaizimmerm * Add JavaDocs. foreachtenant robustness. Signed-off-by: kaizimmerm * Review feedback included. Signed-off-by: kaizimmerm * Updated DMF docs. Signed-off-by: kaizimmerm * targetVisible optional in builder. Signed-off-by: kaizimmerm * Fix typos. Signed-off-by: kaizimmerm * Fix checkbox ID. Signed-off-by: kaizimmerm * DB optimization. Signed-off-by: kaizimmerm * Fix component ID of sm metadat details tab. Signed-off-by: kaizimmerm --- README.md | 6 +- .../documentation/interfaces/dmf-api.md | 17 +- .../SoftwareModuleMetadataFields.java | 7 +- .../hawkbit/ddi/json/model/DdiChunk.java | 22 ++- .../hawkbit/ddi/json/model/DdiDeployment.java | 7 +- .../hawkbit/ddi/json/model/DdiMetadata.java | 41 ++++ .../rest/resource/DataConversionHelper.java | 21 +- .../ddi/rest/resource/DdiRootController.java | 8 +- .../rest/resource/DdiDeploymentBaseTest.java | 39 ++-- .../hawkbit/amqp/AmqpConfiguration.java | 7 +- .../amqp/AmqpMessageDispatcherService.java | 60 ++++-- .../amqp/AmqpMessageHandlerService.java | 17 +- .../AmqpMessageDispatcherServiceTest.java | 10 +- .../amqp/AmqpMessageHandlerServiceTest.java | 3 +- ...ssageDispatcherServiceIntegrationTest.java | 4 + ...pMessageHandlerServiceIntegrationTest.java | 13 ++ .../AmqpServiceIntegrationTest.java | 8 + .../matcher/SoftwareModuleJsonMatcher.java | 17 +- .../dmf/json/model/DmfArtifactHash.java | 1 - .../hawkbit/dmf/json/model/DmfMetadata.java | 82 ++++++++ .../dmf/json/model/DmfSoftwareModule.java | 15 +- .../hawkbit/mgmt/json/model/MgmtMetadata.java | 16 +- .../mgmt/json/model/MgmtMetadataBodyPut.java | 34 ++++ .../MgmtSoftwareModuleMetadata.java | 55 ++++++ .../MgmtSoftwareModuleMetadataBodyPut.java | 44 +++++ .../rest/api/MgmtDistributionSetRestApi.java | 6 +- .../mgmt/rest/api/MgmtRestConstants.java | 3 + .../rest/api/MgmtSoftwareModuleRestApi.java | 21 +- .../resource/MgmtDistributionSetResource.java | 6 +- .../resource/MgmtSoftwareModuleMapper.java | 20 +- .../resource/MgmtSoftwareModuleResource.java | 27 +-- .../MgmtSoftwareModuleResourceTest.java | 102 +++++----- .../repository/ControllerManagement.java | 17 +- .../hawkbit/repository/EntityFactory.java | 11 +- .../repository/RepositoryConstants.java | 9 + .../repository/SoftwareModuleManagement.java | 40 ++-- .../hawkbit/repository/SystemManagement.java | 2 + .../SoftwareModuleMetadataBuilder.java | 37 ++++ .../builder/SoftwareModuleMetadataCreate.java | 53 +++++ .../builder/SoftwareModuleMetadataUpdate.java | 37 ++++ .../model/DistributionSetMetadata.java | 5 + .../hawkbit/repository/model/MetaData.java | 14 ++ .../model/SoftwareModuleMetadata.java | 11 ++ .../builder/AbstractMetadataUpdateCreate.java | 41 ++++ ...actSoftwareModuleMetadataUpdateCreate.java | 41 ++++ .../GenericSoftwareModuleMetadataUpdate.java | 23 +++ .../jpa/JpaControllerManagement.java | 17 ++ .../repository/jpa/JpaEntityFactory.java | 13 +- .../jpa/JpaSoftwareModuleManagement.java | 52 +++-- .../repository/jpa/JpaSystemManagement.java | 11 +- .../RepositoryApplicationConfiguration.java | 8 + .../jpa/RolloutGroupRepository.java | 4 +- .../jpa/SoftwareModuleMetadataRepository.java | 13 ++ .../JpaSoftwareModuleMetadataBuilder.java | 40 ++++ .../JpaSoftwareModuleMetadataCreate.java | 46 +++++ ...MetaData.java => AbstractJpaMetaData.java} | 20 +- .../jpa/model/JpaDistributionSetMetadata.java | 6 +- .../jpa/model/JpaSoftwareModuleMetadata.java | 28 ++- .../V1_11_3__add_module_md_targetvis__H2.sql | 1 + ...1_11_3__add_module_md_targetvis__MYSQL.sql | 1 + .../jpa/ControllerManagementTest.java | 19 ++ .../jpa/DistributionSetManagementTest.java | 14 +- .../jpa/SoftwareModuleManagementTest.java | 117 +++++++---- .../jpa/rsql/RSQLSoftwareModuleFieldTest.java | 27 +-- .../RSQLSoftwareModuleMetadataFieldsTest.java | 34 +++- .../repository/test/util/TestdataFactory.java | 69 +++++-- .../hawkbit/ui/SpPermissionChecker.java | 30 ++- .../ui/artifacts/UploadArtifactView.java | 6 +- .../footer/SMDeleteActionsLayout.java | 2 +- .../smtable/SoftwareModuleDetails.java | 5 +- .../smtable/SoftwareModuleTableLayout.java | 2 +- .../artifacts/smtype/SMTypeFilterHeader.java | 4 +- .../common/AbstractMetadataPopupLayout.java | 133 ++++++++----- .../AbstractDistributionSetDetails.java | 16 +- .../AbstractMetadataDetailsLayout.java | 95 +++++++++ .../AbstractSoftwareModuleDetails.java | 35 +--- .../DistributionSetMetadataDetailsLayout.java | 87 ++++++++ .../DistributionSetMetadatadetailsLayout.java | 165 ---------------- .../SoftwareModuleDetailsTable.java | 4 +- .../SoftwareModuleMetadataDetailsLayout.java | 85 ++++++++ .../SoftwareModuleMetadatadetailslayout.java | 185 ------------------ .../AbstractDistributionSetTableHeader.java | 2 +- .../AbstractSoftwareModuleTableHeader.java | 2 +- .../tagdetails/DistributionTagToken.java | 2 +- .../ui/distributions/DistributionsView.java | 4 +- .../disttype/DSTypeFilterHeader.java | 2 +- .../dstable/DistributionSetDetails.java | 24 +-- .../dstable/DistributionSetTable.java | 2 +- .../dstable/DistributionSetTableLayout.java | 2 +- .../dstable/DsMetadataPopupLayout.java | 17 +- .../ui/distributions/event/MetadataEvent.java | 49 ----- .../footer/DSDeleteActionsLayout.java | 4 +- .../smtable/SwMetadataPopupLayout.java | 142 +++++++++++--- .../smtable/SwModuleDetails.java | 5 +- .../smtable/SwModuleTableLayout.java | 7 +- .../smtype/DistSMTypeFilterHeader.java | 2 +- .../ui/layouts/CreateUpdateTypeLayout.java | 6 +- .../hawkbit/ui/management/DeploymentView.java | 12 +- .../dstable/DistributionDetails.java | 8 +- .../dstable/DistributionTableLayout.java | 2 +- ...eateUpdateDistributionTagLayoutWindow.java | 6 +- .../dstag/DistributionTagHeader.java | 2 +- .../event/DistributionTagDropEvent.java | 2 +- .../footer/DeleteActionsLayout.java | 6 +- .../ui/push/DelayedEventBusPushStrategy.java | 8 +- .../DefaultDistributionSetTypeLayout.java | 2 +- .../ui/utils/UIComponentIdProvider.java | 5 + .../src/main/resources/messages.properties | 1 + 108 files changed, 1883 insertions(+), 917 deletions(-) create mode 100644 hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiMetadata.java create mode 100644 hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfMetadata.java create mode 100644 hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMetadataBodyPut.java create mode 100644 hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleMetadata.java create mode 100644 hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleMetadataBodyPut.java create mode 100644 hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataBuilder.java create mode 100644 hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataCreate.java create mode 100644 hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataUpdate.java create mode 100644 hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractMetadataUpdateCreate.java create mode 100644 hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractSoftwareModuleMetadataUpdateCreate.java create mode 100644 hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/GenericSoftwareModuleMetadataUpdate.java create mode 100644 hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleMetadataBuilder.java create mode 100644 hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleMetadataCreate.java rename hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/{JpaMetaData.java => AbstractJpaMetaData.java} (79%) create mode 100644 hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_11_3__add_module_md_targetvis__H2.sql create mode 100644 hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_11_3__add_module_md_targetvis__MYSQL.sql create mode 100644 hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/AbstractMetadataDetailsLayout.java create mode 100644 hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/DistributionSetMetadataDetailsLayout.java delete mode 100644 hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/DistributionSetMetadatadetailsLayout.java create mode 100644 hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleMetadataDetailsLayout.java delete mode 100644 hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleMetadatadetailslayout.java delete mode 100644 hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/MetadataEvent.java diff --git a/README.md b/README.md index 5ca2799b9..2fde2b3d8 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,10 @@ We offer a sandbox installation that is free for everyone to try out hawkBit. Ho https://hawkbit.eu-gb.mybluemix.net/UI/ +In addition the following vendors offer free trial accounts for their hawkBit compatible products: + +- [Bosch IoT Rollouts](https://www.bosch-iot-suite.com/rollouts/) + # Device Integration hawkBit does not provide off the shelf clients for devices as part of the project. The long term goal is to provide an [Eclipse hono](https://github.com/eclipse/hono) integration which will provide connectivity through various IoT protocols and as a result allows a wide range of clients to connect to hawkBit. However, the hawkBit [Direct Device Integration (API) API](http://www.eclipse.org/hawkbit/documentation/interfaces/ddi-api.html) is HTTP/JSon based which should allow any update client to integrate quite easily. @@ -83,7 +87,7 @@ $ java -jar ./hawkbit-device-simulator/target/hawkbit-device-simulator-#version# ## Generate getting started data with the [Management API example](https://github.com/eclipse/hawkbit-examples/tree/master/hawkbit-example-mgmt-simulator) (optional) ``` -$ java -jar ./hawkbit-example-mgmt-simulator/target/hawkbit-example-mgmt-simulator-#version#.jar +$ java -jar ./hawkbit-example-mgmt-simulator/target/hawkbit-example-mgmt-simulator-#version#-exec.jar ``` # Releases and Roadmap diff --git a/docs/src/main/resources/documentation/interfaces/dmf-api.md b/docs/src/main/resources/documentation/interfaces/dmf-api.md index b2dc47361..e7c24beee 100644 --- a/docs/src/main/resources/documentation/interfaces/dmf-api.md +++ b/docs/src/main/resources/documentation/interfaces/dmf-api.md @@ -237,7 +237,13 @@ Payload Template "sha1":"String" }, "size":long - }] + }], + "metadata":[ + { + "key":"String", + "value":"String" + } + ] }] } ``` @@ -249,7 +255,6 @@ Payload Template | type=EVENT
tenant=tenant123
thingId=abc
topic=DOWNLOAD\_AND\_INSTALL | content_type=application/json ```json -{ "actionId":137, "targetSecurityToken":"bH7XXAprK1ChnLfKSdtlsp7NOlPnZAYY", "softwareModules":[ @@ -269,7 +274,13 @@ Payload Template "sha1":"sha1hash" }, "size":512 - }] + }], + "metadata":[ + { + "key":"installationType", + "value":"5784K#" + } + ] }] } ``` \ No newline at end of file diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleMetadataFields.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleMetadataFields.java index 8286170cd..725d0f206 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleMetadataFields.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleMetadataFields.java @@ -24,7 +24,12 @@ public enum SoftwareModuleMetadataFields implements FieldNameProvider { /** * The key field. */ - KEY("key"); + KEY("key"), + + /** + * The target visible field. + */ + TARGETVISIBLE("targetVisible"); private final String fieldName; diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiChunk.java b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiChunk.java index 8f1172c39..fcb33598a 100644 --- a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiChunk.java +++ b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiChunk.java @@ -13,22 +13,33 @@ import java.util.List; import javax.validation.constraints.NotNull; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + /** * Deployment chunks. */ public class DdiChunk { + @JsonProperty("part") @NotNull private String part; + @JsonProperty("version") @NotNull private String version; + @JsonProperty("name") @NotNull private String name; + @JsonProperty("artifacts") private List artifacts; + @JsonProperty("metadata") + @JsonInclude(JsonInclude.Include.NON_NULL) + private List metadata; + public DdiChunk() { // needed for json create } @@ -44,13 +55,16 @@ public class DdiChunk { * of the artifact * @param artifacts * download information + * @param metadata + * optional as additional information for the target/device */ - public DdiChunk(final String part, final String version, final String name, final List artifacts) { - super(); + public DdiChunk(final String part, final String version, final String name, final List artifacts, + final List metadata) { this.part = part; this.version = version; this.name = name; this.artifacts = artifacts; + this.metadata = metadata; } public String getPart() { @@ -73,4 +87,8 @@ public class DdiChunk { return Collections.unmodifiableList(artifacts); } + public List getMetadata() { + return metadata; + } + } diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiDeployment.java b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiDeployment.java index 2f7fd593e..2d62035e2 100644 --- a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiDeployment.java +++ b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiDeployment.java @@ -11,6 +11,9 @@ package org.eclipse.hawkbit.ddi.json.model; import java.util.Collections; import java.util.List; +import javax.validation.constraints.NotNull; + +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonValue; /** @@ -22,6 +25,8 @@ public class DdiDeployment { private HandlingType update; + @JsonProperty("chunks") + @NotNull private List chunks; /** @@ -59,7 +64,7 @@ public class DdiDeployment { if (chunks == null) { return Collections.emptyList(); } - + return Collections.unmodifiableList(chunks); } diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiMetadata.java b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiMetadata.java new file mode 100644 index 000000000..94b458840 --- /dev/null +++ b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiMetadata.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2015 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.ddi.json.model; + +import javax.validation.constraints.NotNull; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Additional metadata to be provided for the target/device. + * + */ +public class DdiMetadata { + @JsonProperty + @NotNull + private final String key; + + @JsonProperty + @NotNull + private final String value; + + public DdiMetadata(final String key, final String value) { + this.key = key; + this.value = value; + } + + public String getKey() { + return key; + } + + public String getValue() { + return value; + } + +} diff --git a/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DataConversionHelper.java b/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DataConversionHelper.java index 0cc0b93a6..b5077379e 100644 --- a/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DataConversionHelper.java +++ b/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DataConversionHelper.java @@ -9,6 +9,7 @@ package org.eclipse.hawkbit.ddi.rest.resource; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import org.eclipse.hawkbit.api.ApiType; @@ -20,17 +21,22 @@ import org.eclipse.hawkbit.ddi.json.model.DdiArtifactHash; import org.eclipse.hawkbit.ddi.json.model.DdiChunk; import org.eclipse.hawkbit.ddi.json.model.DdiConfig; import org.eclipse.hawkbit.ddi.json.model.DdiControllerBase; +import org.eclipse.hawkbit.ddi.json.model.DdiMetadata; import org.eclipse.hawkbit.ddi.json.model.DdiPolling; import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants; +import org.eclipse.hawkbit.repository.ControllerManagement; import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Artifact; +import org.eclipse.hawkbit.repository.model.SoftwareModule; +import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.rest.data.ResponseList; import org.eclipse.hawkbit.tenancy.TenantAware; import org.springframework.hateoas.Link; import org.springframework.hateoas.mvc.ControllerLinkBuilder; import org.springframework.http.HttpRequest; +import org.springframework.util.CollectionUtils; /** * Utility class for the DDI API. @@ -43,15 +49,26 @@ public final class DataConversionHelper { static List createChunks(final Target target, final Action uAction, final ArtifactUrlHandler artifactUrlHandler, final SystemManagement systemManagement, - final HttpRequest request) { + final HttpRequest request, final ControllerManagement controllerManagement) { + + final Map> metadata = controllerManagement + .findTargetVisibleMetaDataBySoftwareModuleId(uAction.getDistributionSet().getModules().stream() + .map(SoftwareModule::getId).collect(Collectors.toList())); + return uAction.getDistributionSet().getModules().stream() .map(module -> new DdiChunk(mapChunkLegacyKeys(module.getType().getKey()), module.getVersion(), module.getName(), - createArtifacts(target, module, artifactUrlHandler, systemManagement, request))) + createArtifacts(target, module, artifactUrlHandler, systemManagement, request), + mapMetadata(metadata.get(module.getId())))) .collect(Collectors.toList()); } + private static List mapMetadata(final List metadata) { + return CollectionUtils.isEmpty(metadata) ? null + : metadata.stream().map(md -> new DdiMetadata(md.getKey(), md.getValue())).collect(Collectors.toList()); + } + private static String mapChunkLegacyKeys(final String key) { if ("application".equals(key)) { return "bApp"; diff --git a/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java b/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java index 71c955149..c858768c6 100644 --- a/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java +++ b/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java @@ -20,6 +20,7 @@ import org.eclipse.hawkbit.api.ArtifactUrlHandler; import org.eclipse.hawkbit.artifact.repository.model.AbstractDbArtifact; import org.eclipse.hawkbit.ddi.json.model.DdiActionFeedback; import org.eclipse.hawkbit.ddi.json.model.DdiActionHistory; +import org.eclipse.hawkbit.ddi.json.model.DdiArtifact; import org.eclipse.hawkbit.ddi.json.model.DdiCancel; import org.eclipse.hawkbit.ddi.json.model.DdiCancelActionToStop; import org.eclipse.hawkbit.ddi.json.model.DdiChunk; @@ -115,8 +116,8 @@ public class DdiRootController implements DdiRootControllerRestApi { private EntityFactory entityFactory; @Override - public ResponseEntity> getSoftwareModulesArtifacts( - @PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId, + public ResponseEntity> getSoftwareModulesArtifacts(@PathVariable("tenant") final String tenant, + @PathVariable("controllerId") final String controllerId, @PathVariable("softwareModuleId") final Long softwareModuleId) { LOG.debug("getSoftwareModulesArtifacts({})", controllerId); @@ -270,7 +271,8 @@ public class DdiRootController implements DdiRootControllerRestApi { final List chunks = DataConversionHelper.createChunks(target, action, artifactUrlHandler, systemManagement, - new ServletServerHttpRequest(requestResponseContextHolder.getHttpServletRequest())); + new ServletServerHttpRequest(requestResponseContextHolder.getHttpServletRequest()), + controllerManagement); final HandlingType handlingType = action.isForce() ? HandlingType.FORCED : HandlingType.ATTEMPT; diff --git a/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java b/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java index a7a4409eb..c4d6371b3 100644 --- a/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java +++ b/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java @@ -111,10 +111,10 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true); final byte random[] = RandomUtils.nextBytes(5 * 1024); - final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds), - "test1", false); - final Artifact artifactSignature = artifactManagement.create(new ByteArrayInputStream(random), - getOsModule(ds), "test1.signature", false); + final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds), "test1", + false); + final Artifact artifactSignature = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds), + "test1.signature", false); final Target savedTarget = testdataFactory.createTarget("4712"); @@ -265,12 +265,19 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { // Prepare test data final DistributionSet ds = testdataFactory.createDistributionSet("", true); final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true); + final String visibleMetadataOsKey = "metaDataVisible"; + final String visibleMetadataOsValue = "withValue"; final byte random[] = RandomUtils.nextBytes(5 * 1024); - final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds), - "test1", false); - final Artifact artifactSignature = artifactManagement.create(new ByteArrayInputStream(random), - getOsModule(ds), "test1.signature", false); + final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds), "test1", + false); + final Artifact artifactSignature = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds), + "test1.signature", false); + + softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata().create(getOsModule(ds)) + .key(visibleMetadataOsKey).value(visibleMetadataOsValue).targetVisible(true)); + softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata().create(getOsModule(ds)) + .key("metaDataNotVisible").value("withValue").targetVisible(false)); final Target savedTarget = testdataFactory.createTarget("4712"); @@ -328,6 +335,9 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { contains(ds.findFirstModuleByType(osType).get().getName()))) .andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].version", contains(ds.findFirstModuleByType(osType).get().getVersion()))) + .andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].metadata[0].key").value(visibleMetadataOsKey)) + .andExpect( + jsonPath("$.deployment.chunks[?(@.part==os)].metadata[0].value").value(visibleMetadataOsValue)) .andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[0].size", contains(5 * 1024))) .andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[0].filename", contains("test1"))) .andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[0].hashes.md5", @@ -362,8 +372,9 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { + "/artifacts/test1.signature.MD5SUM"))) .andExpect(jsonPath("$.deployment.chunks[?(@.part==bApp)].version", contains(ds.findFirstModuleByType(appType).get().getVersion()))) - .andExpect(jsonPath("$.deployment.chunks[?(@.part==bApp)].name", - contains(ds.findFirstModuleByType(appType).get().getName()))); + .andExpect(jsonPath("$.deployment.chunks[?(@.part==bApp)].metadata").doesNotExist()) + .andExpect(jsonPath("$.deployment.chunks[?(@.part==bApp)].name") + .value(ds.findFirstModuleByType(appType).get().getName())); // Retrieved is reported final List actionStatusMessages = deploymentManagement @@ -381,10 +392,10 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true); final byte random[] = RandomUtils.nextBytes(5 * 1024); - final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds), - "test1", false); - final Artifact artifactSignature = artifactManagement.create(new ByteArrayInputStream(random), - getOsModule(ds), "test1.signature", false); + final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds), "test1", + false); + final Artifact artifactSignature = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds), + "test1.signature", false); final Target savedTarget = testdataFactory.createTarget("4712"); diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpConfiguration.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpConfiguration.java index a840e6747..7b0674c88 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpConfiguration.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpConfiguration.java @@ -19,6 +19,7 @@ import org.eclipse.hawkbit.repository.ArtifactManagement; import org.eclipse.hawkbit.repository.ControllerManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.EntityFactory; +import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement; @@ -311,9 +312,11 @@ public class AmqpConfiguration { AmqpMessageDispatcherService amqpMessageDispatcherService(final RabbitTemplate rabbitTemplate, final AmqpMessageSenderService amqpSenderService, final ArtifactUrlHandler artifactUrlHandler, final SystemSecurityContext systemSecurityContext, final SystemManagement systemManagement, - final TargetManagement targetManagement, final DistributionSetManagement distributionSetManagement) { + final TargetManagement targetManagement, final DistributionSetManagement distributionSetManagement, + final SoftwareModuleManagement softwareModuleManagement) { return new AmqpMessageDispatcherService(rabbitTemplate, amqpSenderService, artifactUrlHandler, - systemSecurityContext, systemManagement, targetManagement, serviceMatcher, distributionSetManagement); + systemSecurityContext, systemManagement, targetManagement, serviceMatcher, distributionSetManagement, + softwareModuleManagement); } private static Map getTTLMaxArgsAuthenticationQueue() { diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherService.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherService.java index 38ea6a66a..51770bcde 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherService.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherService.java @@ -9,9 +9,10 @@ package org.eclipse.hawkbit.amqp; import java.net.URI; -import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import java.util.stream.Collectors; import org.eclipse.hawkbit.api.ApiType; @@ -25,8 +26,11 @@ import org.eclipse.hawkbit.dmf.amqp.api.MessageType; import org.eclipse.hawkbit.dmf.json.model.DmfArtifact; import org.eclipse.hawkbit.dmf.json.model.DmfArtifactHash; import org.eclipse.hawkbit.dmf.json.model.DmfDownloadAndUpdateRequest; +import org.eclipse.hawkbit.dmf.json.model.DmfMetadata; import org.eclipse.hawkbit.dmf.json.model.DmfSoftwareModule; import org.eclipse.hawkbit.repository.DistributionSetManagement; +import org.eclipse.hawkbit.repository.RepositoryConstants; +import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent; @@ -34,6 +38,7 @@ import org.eclipse.hawkbit.repository.event.remote.TargetDeletedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.CancelTargetAssignmentEvent; import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.SoftwareModule; +import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.util.IpUtil; @@ -46,6 +51,9 @@ import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.cloud.bus.ServiceMatcher; import org.springframework.cloud.bus.event.RemoteApplicationEvent; import org.springframework.context.event.EventListener; +import org.springframework.data.domain.PageRequest; + +import com.google.common.collect.Maps; /** * {@link AmqpMessageDispatcherService} create all outgoing AMQP messages and @@ -66,6 +74,7 @@ public class AmqpMessageDispatcherService extends BaseAmqpService { private final TargetManagement targetManagement; private final ServiceMatcher serviceMatcher; private final DistributionSetManagement distributionSetManagement; + private final SoftwareModuleManagement softwareModuleManagement; /** * Constructor. @@ -92,7 +101,8 @@ public class AmqpMessageDispatcherService extends BaseAmqpService { final AmqpMessageSenderService amqpSenderService, final ArtifactUrlHandler artifactUrlHandler, final SystemSecurityContext systemSecurityContext, final SystemManagement systemManagement, final TargetManagement targetManagement, final ServiceMatcher serviceMatcher, - final DistributionSetManagement distributionSetManagement) { + final DistributionSetManagement distributionSetManagement, + final SoftwareModuleManagement softwareModuleManagement) { super(rabbitTemplate); this.artifactUrlHandler = artifactUrlHandler; this.amqpSenderService = amqpSenderService; @@ -101,6 +111,7 @@ public class AmqpMessageDispatcherService extends BaseAmqpService { this.targetManagement = targetManagement; this.serviceMatcher = serviceMatcher; this.distributionSetManagement = distributionSetManagement; + this.softwareModuleManagement = softwareModuleManagement; } /** @@ -118,11 +129,22 @@ public class AmqpMessageDispatcherService extends BaseAmqpService { LOG.debug("targetAssignDistributionSet retrieved. I will forward it to DMF broker."); - distributionSetManagement.get(assignedEvent.getDistributionSetId()).ifPresent(set -> + distributionSetManagement.get(assignedEvent.getDistributionSetId()).ifPresent(set -> { - targetManagement.getByControllerID(assignedEvent.getActions().keySet()) - .forEach(target -> sendUpdateMessageToTarget(assignedEvent.getTenant(), target, - assignedEvent.getActions().get(target.getControllerId()), set.getModules()))); + final Map> modules = Maps + .newHashMapWithExpectedSize(set.getModules().size()); + set.getModules() + .forEach( + module -> modules.put(module, + softwareModuleManagement.findMetaDataBySoftwareModuleIdAndTargetVisible( + new PageRequest(0, RepositoryConstants.MAX_META_DATA_COUNT), module.getId()) + .getContent())); + + targetManagement.getByControllerID(assignedEvent.getActions().keySet()) + .forEach(target -> sendUpdateMessageToTarget(assignedEvent.getTenant(), target, + assignedEvent.getActions().get(target.getControllerId()), modules)); + + }); } /** @@ -159,7 +181,7 @@ public class AmqpMessageDispatcherService extends BaseAmqpService { } protected void sendUpdateMessageToTarget(final String tenant, final Target target, final Long actionId, - final Collection modules) { + final Map> modules) { final URI targetAdress = target.getAddress(); if (!IpUtil.isAmqpUri(targetAdress)) { @@ -172,10 +194,11 @@ public class AmqpMessageDispatcherService extends BaseAmqpService { final String targetSecurityToken = systemSecurityContext.runAsSystem(target::getSecurityToken); downloadAndUpdateRequest.setTargetSecurityToken(targetSecurityToken); - for (final SoftwareModule softwareModule : modules) { - final DmfSoftwareModule amqpSoftwareModule = convertToAmqpSoftwareModule(target, softwareModule); + modules.entrySet().forEach(entry -> { + + final DmfSoftwareModule amqpSoftwareModule = convertToAmqpSoftwareModule(target, entry); downloadAndUpdateRequest.addSoftwareModule(amqpSoftwareModule); - } + }); final Message message = getMessageConverter().toMessage(downloadAndUpdateRequest, createConnectorMessagePropertiesEvent(tenant, target.getControllerId(), @@ -248,17 +271,22 @@ public class AmqpMessageDispatcherService extends BaseAmqpService { return messageProperties; } - private DmfSoftwareModule convertToAmqpSoftwareModule(final Target target, final SoftwareModule softwareModule) { + private DmfSoftwareModule convertToAmqpSoftwareModule(final Target target, + final Entry> entry) { final DmfSoftwareModule amqpSoftwareModule = new DmfSoftwareModule(); - amqpSoftwareModule.setModuleId(softwareModule.getId()); - amqpSoftwareModule.setModuleType(softwareModule.getType().getKey()); - amqpSoftwareModule.setModuleVersion(softwareModule.getVersion()); + amqpSoftwareModule.setModuleId(entry.getKey().getId()); + amqpSoftwareModule.setModuleType(entry.getKey().getType().getKey()); + amqpSoftwareModule.setModuleVersion(entry.getKey().getVersion()); + amqpSoftwareModule.setArtifacts(convertArtifacts(target, entry.getKey().getArtifacts())); + amqpSoftwareModule.setMetadata(convertMetadata(entry.getValue())); - final List artifacts = convertArtifacts(target, softwareModule.getArtifacts()); - amqpSoftwareModule.setArtifacts(artifacts); return amqpSoftwareModule; } + private List convertMetadata(final List metadata) { + return metadata.stream().map(md -> new DmfMetadata(md.getKey(), md.getValue())).collect(Collectors.toList()); + } + private List convertArtifacts(final Target target, final List localArtifacts) { if (localArtifacts.isEmpty()) { return Collections.emptyList(); diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java index 1ad903c4e..9c62de00e 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java @@ -12,8 +12,10 @@ import java.net.URI; import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.UUID; +import java.util.stream.Collectors; import org.eclipse.hawkbit.dmf.amqp.api.EventTopic; import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey; @@ -28,6 +30,8 @@ import org.eclipse.hawkbit.repository.RepositoryConstants; import org.eclipse.hawkbit.repository.builder.ActionStatusCreate; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.Status; +import org.eclipse.hawkbit.repository.model.SoftwareModule; +import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.util.IpUtil; import org.slf4j.Logger; @@ -45,6 +49,8 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextImpl; import org.springframework.util.StringUtils; +import com.google.common.collect.Maps; + /** * * {@link AmqpMessageHandlerService} handles all incoming target interaction @@ -199,8 +205,17 @@ public class AmqpMessageHandlerService extends BaseAmqpService { return; } + final Map> modules = Maps + .newHashMapWithExpectedSize(action.getDistributionSet().getModules().size()); + + final Map> metadata = controllerManagement + .findTargetVisibleMetaDataBySoftwareModuleId(action.getDistributionSet().getModules().stream() + .map(SoftwareModule::getId).collect(Collectors.toList())); + + action.getDistributionSet().getModules().forEach(module -> modules.put(module, metadata.get(module.getId()))); + amqpMessageDispatcherService.sendUpdateMessageToTarget(action.getTenant(), action.getTarget(), action.getId(), - action.getDistributionSet().getModules()); + modules); } /** diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherServiceTest.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherServiceTest.java index 483ff6eba..d4ff8d147 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherServiceTest.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherServiceTest.java @@ -34,6 +34,7 @@ import org.eclipse.hawkbit.dmf.amqp.api.EventTopic; import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey; import org.eclipse.hawkbit.dmf.amqp.api.MessageType; import org.eclipse.hawkbit.dmf.json.model.DmfDownloadAndUpdateRequest; +import org.eclipse.hawkbit.dmf.json.model.DmfMetadata; import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent; import org.eclipse.hawkbit.repository.event.remote.TargetDeletedEvent; @@ -46,6 +47,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TenantMetaData; import org.eclipse.hawkbit.repository.test.util.AbstractIntegrationTest; +import org.eclipse.hawkbit.repository.test.util.TestdataFactory; import org.eclipse.hawkbit.util.IpUtil; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -109,7 +111,7 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest { amqpMessageDispatcherService = new AmqpMessageDispatcherService(rabbitTemplate, senderService, artifactUrlHandlerMock, systemSecurityContext, systemManagement, targetManagement, serviceMatcher, - distributionSetManagement); + distributionSetManagement, softwareModuleManagement); } @@ -129,6 +131,8 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest { public void testSendDownloadRequesWithSoftwareModulesAndNoArtifacts() { final DistributionSet createDistributionSet = testdataFactory .createDistributionSet(UUID.randomUUID().toString()); + testdataFactory.addSoftwareModuleMetadata(createDistributionSet); + final Action action = createAction(createDistributionSet); final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent( @@ -142,6 +146,10 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest { for (final org.eclipse.hawkbit.dmf.json.model.DmfSoftwareModule softwareModule : downloadAndUpdateRequest .getSoftwareModules()) { assertTrue("Artifact list for softwaremodule should be empty", softwareModule.getArtifacts().isEmpty()); + + assertThat(softwareModule.getMetadata()).containsExactly( + new DmfMetadata(TestdataFactory.VISIBLE_SM_MD_KEY, TestdataFactory.VISIBLE_SM_MD_VALUE)); + for (final SoftwareModule softwareModule2 : action.getDistributionSet().getModules()) { assertNotNull("Sofware module ID should be set", softwareModule.getModuleId()); if (!softwareModule.getModuleId().equals(softwareModule2.getId())) { diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java index 7b8e8c44e..5f6fbad24 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java @@ -22,7 +22,6 @@ import java.lang.reflect.Field; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; -import java.util.Collection; import java.util.Map; import java.util.Optional; @@ -421,7 +420,7 @@ public class AmqpMessageHandlerServiceTest { final ArgumentCaptor actionIdCaptor = ArgumentCaptor.forClass(Long.class); verify(amqpMessageDispatcherServiceMock, times(1)).sendUpdateMessageToTarget(tenantCaptor.capture(), - targetCaptor.capture(), actionIdCaptor.capture(), any(Collection.class)); + targetCaptor.capture(), actionIdCaptor.capture(), any(Map.class)); final String tenant = tenantCaptor.getValue(); final String controllerId = targetCaptor.getValue().getControllerId(); final Long actionId = actionIdCaptor.getValue(); diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageDispatcherServiceIntegrationTest.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageDispatcherServiceIntegrationTest.java index 60e129ca2..fe2fdc05b 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageDispatcherServiceIntegrationTest.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageDispatcherServiceIntegrationTest.java @@ -20,6 +20,7 @@ import org.eclipse.hawkbit.repository.event.remote.entity.ActionUpdatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.CancelTargetAssignmentEvent; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent; +import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleUpdatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -45,6 +46,7 @@ public class AmqpMessageDispatcherServiceIntegrationTest extends AmqpServiceInte @Expect(type = TargetAssignDistributionSetEvent.class, count = 1), @Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), + @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6), @Expect(type = DistributionSetCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 2) }) public void sendDownloadAndInstallStatus() { @@ -63,6 +65,7 @@ public class AmqpMessageDispatcherServiceIntegrationTest extends AmqpServiceInte @Expect(type = CancelTargetAssignmentEvent.class, count = 1), @Expect(type = ActionCreatedEvent.class, count = 2), @Expect(type = ActionUpdatedEvent.class, count = 1), @Expect(type = SoftwareModuleCreatedEvent.class, count = 6), + @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6), @Expect(type = DistributionSetCreatedEvent.class, count = 2), @Expect(type = TargetUpdatedEvent.class, count = 2), @Expect(type = TargetPollEvent.class, count = 3) }) public void assignDistributionSetMultipleTimes() { @@ -88,6 +91,7 @@ public class AmqpMessageDispatcherServiceIntegrationTest extends AmqpServiceInte @Expect(type = CancelTargetAssignmentEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 1), @Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), + @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6), @Expect(type = DistributionSetCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 2) }) public void sendCancelStatus() { diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageHandlerServiceIntegrationTest.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageHandlerServiceIntegrationTest.java index 7bb7e4515..89554a4b4 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageHandlerServiceIntegrationTest.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageHandlerServiceIntegrationTest.java @@ -30,6 +30,7 @@ import org.eclipse.hawkbit.repository.event.remote.entity.ActionUpdatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.CancelTargetAssignmentEvent; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent; +import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleUpdatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent; import org.eclipse.hawkbit.repository.model.Action.Status; @@ -363,6 +364,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra @Expect(type = TargetAssignDistributionSetEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 1), @Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), + @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6), @Expect(type = DistributionSetCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 2), @Expect(type = TargetPollEvent.class, count = 1) }) public void finishActionStatus() { @@ -376,6 +378,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra @Expect(type = TargetAssignDistributionSetEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 0), @Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), + @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6), @Expect(type = DistributionSetCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) }) public void runningActionStatus() { @@ -389,6 +392,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra @Expect(type = TargetAssignDistributionSetEvent.class, count = 1), @Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), + @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6), @Expect(type = DistributionSetCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) }) public void downloadActionStatus() { @@ -402,6 +406,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra @Expect(type = TargetAssignDistributionSetEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 1), @Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), + @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6), @Expect(type = DistributionSetCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 2), @Expect(type = TargetPollEvent.class, count = 1) }) public void errorActionStatus() { @@ -415,6 +420,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra @Expect(type = TargetAssignDistributionSetEvent.class, count = 1), @Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), + @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6), @Expect(type = DistributionSetCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) }) public void warningActionStatus() { @@ -428,6 +434,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra @Expect(type = TargetAssignDistributionSetEvent.class, count = 1), @Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), + @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6), @Expect(type = DistributionSetCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) }) public void retrievedActionStatus() { @@ -441,6 +448,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra @Expect(type = TargetAssignDistributionSetEvent.class, count = 1), @Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), + @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6), @Expect(type = DistributionSetCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) }) public void cancelNotAllowActionStatus() { @@ -455,6 +463,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra @Expect(type = TargetAssignDistributionSetEvent.class, count = 1), @Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), + @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6), @Expect(type = DistributionSetCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 2) }) public void receiveDownLoadAndInstallMessageAfterAssignment() { @@ -463,6 +472,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra // setup createAndSendTarget(controllerId, TENANT_EXIST); final DistributionSet distributionSet = testdataFactory.createDistributionSet(UUID.randomUUID().toString()); + testdataFactory.addSoftwareModuleMetadata(distributionSet); assignDistributionSet(distributionSet.getId(), controllerId); // test @@ -507,6 +517,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra @Expect(type = TargetAssignDistributionSetEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 1), @Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), + @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6), @Expect(type = CancelTargetAssignmentEvent.class, count = 1), @Expect(type = DistributionSetCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) }) @@ -526,6 +537,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra @Expect(type = TargetAssignDistributionSetEvent.class, count = 1), @Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), + @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6), @Expect(type = DistributionSetCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) }) public void canceledRejectedNotAllowActionStatus() { @@ -541,6 +553,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra @Expect(type = CancelTargetAssignmentEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 1), @Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), + @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6), @Expect(type = DistributionSetCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) }) public void canceledRejectedActionStatus() { diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpServiceIntegrationTest.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpServiceIntegrationTest.java index 62e83e3c3..3cdb34eb7 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpServiceIntegrationTest.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpServiceIntegrationTest.java @@ -24,6 +24,7 @@ import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey; import org.eclipse.hawkbit.dmf.amqp.api.MessageType; import org.eclipse.hawkbit.dmf.json.model.DmfAttributeUpdate; import org.eclipse.hawkbit.dmf.json.model.DmfDownloadAndUpdateRequest; +import org.eclipse.hawkbit.dmf.json.model.DmfMetadata; import org.eclipse.hawkbit.integration.listener.DeadletterListener; import org.eclipse.hawkbit.integration.listener.ReplyToListener; import org.eclipse.hawkbit.matcher.SoftwareModuleJsonMatcher; @@ -35,6 +36,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; +import org.eclipse.hawkbit.repository.test.util.TestdataFactory; import org.eclipse.hawkbit.util.IpUtil; import org.junit.Assert; import org.junit.Before; @@ -107,6 +109,8 @@ public abstract class AmqpServiceIntegrationTest extends AbstractAmqpIntegration protected DistributionSetAssignmentResult registerTargetAndAssignDistributionSet(final String controllerId) { distributionSet = testdataFactory.createDistributionSet(UUID.randomUUID().toString()); + testdataFactory.addSoftwareModuleMetadata(distributionSet); + return registerTargetAndAssignDistributionSet(distributionSet.getId(), TargetUpdateStatus.REGISTERED, distributionSet.getModules(), controllerId); } @@ -165,6 +169,10 @@ public abstract class AmqpServiceIntegrationTest extends AbstractAmqpIntegration Assert.assertThat(dsModules, SoftwareModuleJsonMatcher.containsExactly(downloadAndUpdateRequest.getSoftwareModules())); + downloadAndUpdateRequest.getSoftwareModules() + .forEach(dmfModule -> assertThat(dmfModule.getMetadata()).containsExactly( + new DmfMetadata(TestdataFactory.VISIBLE_SM_MD_KEY, TestdataFactory.VISIBLE_SM_MD_VALUE))); + final Target updatedTarget = waitUntilIsPresent(() -> targetManagement.getByControllerID(controllerId)); assertThat(updatedTarget.getSecurityToken()).isEqualTo(downloadAndUpdateRequest.getTargetSecurityToken()); diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/matcher/SoftwareModuleJsonMatcher.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/matcher/SoftwareModuleJsonMatcher.java index ad0ca16f1..1e29fc2bc 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/matcher/SoftwareModuleJsonMatcher.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/matcher/SoftwareModuleJsonMatcher.java @@ -12,6 +12,7 @@ import java.util.Collection; import java.util.List; import java.util.Set; +import org.eclipse.hawkbit.dmf.json.model.DmfSoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.hamcrest.BaseMatcher; import org.hamcrest.Description; @@ -44,21 +45,19 @@ public final class SoftwareModuleJsonMatcher { * the json sofware modules. */ @Factory - public static SoftwareModulesMatcher containsExactly( - final List expectedModules) { + public static SoftwareModulesMatcher containsExactly(final List expectedModules) { return new SoftwareModulesMatcher(expectedModules); } private static class SoftwareModulesMatcher extends BaseMatcher> { - private final List expectedModules; + private final List expectedModules; - public SoftwareModulesMatcher(List expectedModules) { + public SoftwareModulesMatcher(final List expectedModules) { this.expectedModules = expectedModules; } - static boolean containsExactly(Object actual, - List expected) { + static boolean containsExactly(final Object actual, final List expected) { if (actual == null) { return expected == null; } @@ -73,7 +72,7 @@ public final class SoftwareModuleJsonMatcher { for (final SoftwareModule repoSoftwareModule : modules) { boolean containsElement = false; - for (final org.eclipse.hawkbit.dmf.json.model.DmfSoftwareModule jsonSoftwareModule : expected) { + for (final DmfSoftwareModule jsonSoftwareModule : expected) { if (!jsonSoftwareModule.getModuleId().equals(repoSoftwareModule.getId())) { continue; } @@ -100,12 +99,12 @@ public final class SoftwareModuleJsonMatcher { } @Override - public boolean matches(Object actualValue) { + public boolean matches(final Object actualValue) { return containsExactly(actualValue, expectedModules); } @Override - public void describeTo(Description description) { + public void describeTo(final Description description) { description.appendValue(expectedModules); } } diff --git a/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfArtifactHash.java b/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfArtifactHash.java index d8f8a9426..ffc159530 100644 --- a/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfArtifactHash.java +++ b/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfArtifactHash.java @@ -32,7 +32,6 @@ public class DmfArtifactHash { */ @JsonCreator public DmfArtifactHash(@JsonProperty("sha1") final String sha1, @JsonProperty("md5") final String md5) { - super(); this.sha1 = sha1; this.md5 = md5; } diff --git a/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfMetadata.java b/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfMetadata.java new file mode 100644 index 000000000..2f7ca7acc --- /dev/null +++ b/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfMetadata.java @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2015 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.dmf.json.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Additional metadata to be provided for the target/device. + * + */ +@JsonInclude(Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class DmfMetadata { + @JsonProperty + private final String key; + + @JsonProperty + private final String value; + + @JsonCreator + public DmfMetadata(@JsonProperty("key") final String key, @JsonProperty("value") final String value) { + this.key = key; + this.value = value; + } + + public String getKey() { + return key; + } + + public String getValue() { + return value; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((key == null) ? 0 : key.hashCode()); + result = prime * result + ((value == null) ? 0 : value.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final DmfMetadata other = (DmfMetadata) obj; + if (key == null) { + if (other.key != null) { + return false; + } + } else if (!key.equals(other.key)) { + return false; + } + if (value == null) { + if (other.value != null) { + return false; + } + } else if (!value.equals(other.value)) { + return false; + } + return true; + } + +} diff --git a/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfSoftwareModule.java b/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfSoftwareModule.java index d85643f23..4b89ea712 100644 --- a/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfSoftwareModule.java +++ b/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfSoftwareModule.java @@ -20,9 +20,6 @@ import com.fasterxml.jackson.annotation.JsonProperty; /** * JSON representation of a software module. * - * - * - * */ @JsonInclude(Include.NON_NULL) @JsonIgnoreProperties(ignoreUnknown = true) @@ -36,6 +33,8 @@ public class DmfSoftwareModule { private String moduleVersion; @JsonProperty private List artifacts; + @JsonProperty + private List metadata; public String getModuleType() { return moduleType; @@ -74,4 +73,14 @@ public class DmfSoftwareModule { this.artifacts = artifacts; } + public List getMetadata() { + return metadata; + } + + public void setMetadata(final List metadata) { + if (metadata != null && !metadata.isEmpty()) { + this.metadata = metadata; + } + } + } diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMetadata.java b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMetadata.java index 6a6371d6b..73bd372c3 100644 --- a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMetadata.java +++ b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMetadata.java @@ -14,7 +14,7 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; /** - * The representation of an meta data in the REST API. + * The representation of an meta data in the REST API for POST/Create. * */ @JsonInclude(Include.NON_NULL) @@ -26,32 +26,18 @@ public class MgmtMetadata { @JsonProperty private String value; - /** - * @return the key - */ public String getKey() { return key; } - /** - * @param key - * the key to set - */ public void setKey(final String key) { this.key = key; } - /** - * @return the value - */ public String getValue() { return value; } - /** - * @param value - * the value to set - */ public void setValue(final String value) { this.value = value; } diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMetadataBodyPut.java b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMetadataBodyPut.java new file mode 100644 index 000000000..eaf7e8ca8 --- /dev/null +++ b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMetadataBodyPut.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2015 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.mgmt.json.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * The representation of an meta data in the REST API for PUT/Update. + * + */ +@JsonInclude(Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class MgmtMetadataBodyPut { + + @JsonProperty + private String value; + + public String getValue() { + return value; + } + + public void setValue(final String value) { + this.value = value; + } +} diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleMetadata.java b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleMetadata.java new file mode 100644 index 000000000..01750d26d --- /dev/null +++ b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleMetadata.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2015 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.mgmt.json.model.softwaremodule; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * The representation of SoftwareModuleMetadata in the REST API for POST/Create. + * + */ +@JsonInclude(Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class MgmtSoftwareModuleMetadata { + + @JsonProperty(required = true) + private String key; + @JsonProperty + private String value; + @JsonProperty + private boolean targetVisible; + + public String getKey() { + return key; + } + + public void setKey(final String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(final String value) { + this.value = value; + } + + public boolean isTargetVisible() { + return targetVisible; + } + + public void setTargetVisible(final boolean targetVisible) { + this.targetVisible = targetVisible; + } + +} diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleMetadataBodyPut.java b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleMetadataBodyPut.java new file mode 100644 index 000000000..67d6b39b1 --- /dev/null +++ b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleMetadataBodyPut.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2015 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.mgmt.json.model.softwaremodule; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * The representation of an meta data in the REST API for PUT/Update. + * + */ +@JsonInclude(Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class MgmtSoftwareModuleMetadataBodyPut { + + @JsonProperty + private String value; + @JsonProperty + private Boolean targetVisible; + + public String getValue() { + return value; + } + + public void setValue(final String value) { + this.value = value; + } + + public Boolean isTargetVisible() { + return targetVisible; + } + + public void setTargetVisible(final Boolean targetVisible) { + this.targetVisible = targetVisible; + } +} diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDistributionSetRestApi.java b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDistributionSetRestApi.java index b4200494c..0be8711e3 100644 --- a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDistributionSetRestApi.java +++ b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDistributionSetRestApi.java @@ -11,6 +11,7 @@ package org.eclipse.hawkbit.mgmt.rest.api; import java.util.List; import org.eclipse.hawkbit.mgmt.json.model.MgmtMetadata; +import org.eclipse.hawkbit.mgmt.json.model.MgmtMetadataBodyPut; import org.eclipse.hawkbit.mgmt.json.model.PagedList; import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSet; import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSetRequestBodyPost; @@ -256,7 +257,8 @@ public interface MgmtDistributionSetRestApi { */ @RequestMapping(method = RequestMethod.GET, value = "/{distributionSetId}/metadata", produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }) - ResponseEntity> getMetadata(@PathVariable("distributionSetId") Long distributionSetId, + ResponseEntity> getMetadata( + @PathVariable("distributionSetId") Long distributionSetId, @RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) int pagingOffsetParam, @RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) int pagingLimitParam, @RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) String sortParam, @@ -292,7 +294,7 @@ public interface MgmtDistributionSetRestApi { @RequestMapping(method = RequestMethod.PUT, value = "/{distributionSetId}/metadata/{metadataKey}", produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }) ResponseEntity updateMetadata(@PathVariable("distributionSetId") Long distributionSetId, - @PathVariable("metadataKey") String metadataKey, MgmtMetadata metadata); + @PathVariable("metadataKey") String metadataKey, MgmtMetadataBodyPut metadata); /** * Deletes a single meta data entry from the distribution set. diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtRestConstants.java b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtRestConstants.java index 46b195031..5893eaba0 100644 --- a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtRestConstants.java +++ b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtRestConstants.java @@ -185,6 +185,9 @@ public final class MgmtRestConstants { */ public static final String SOFTWAREMODULETYPE_V1_REQUEST_MAPPING = BASE_V1_REQUEST_MAPPING + "/softwaremoduletypes"; + /** + * The distributon set base resource. + */ public static final String DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING = BASE_V1_REQUEST_MAPPING + "/distributionsettypes"; diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSoftwareModuleRestApi.java b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSoftwareModuleRestApi.java index 37c6b1eab..d271335fd 100644 --- a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSoftwareModuleRestApi.java +++ b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSoftwareModuleRestApi.java @@ -10,10 +10,11 @@ package org.eclipse.hawkbit.mgmt.rest.api; import java.util.List; -import org.eclipse.hawkbit.mgmt.json.model.MgmtMetadata; import org.eclipse.hawkbit.mgmt.json.model.PagedList; import org.eclipse.hawkbit.mgmt.json.model.artifact.MgmtArtifact; import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModule; +import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleMetadata; +import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleMetadataBodyPut; import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleRequestBodyPost; import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleRequestBodyPut; import org.springframework.hateoas.MediaTypes; @@ -214,7 +215,8 @@ public interface MgmtSoftwareModuleRestApi { */ @RequestMapping(method = RequestMethod.GET, value = "/{softwareModuleId}/metadata", produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }) - ResponseEntity> getMetadata(@PathVariable("softwareModuleId") final Long softwareModuleId, + ResponseEntity> getMetadata( + @PathVariable("softwareModuleId") final Long softwareModuleId, @RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam, @RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam, @RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam, @@ -232,7 +234,8 @@ public interface MgmtSoftwareModuleRestApi { */ @RequestMapping(method = RequestMethod.GET, value = "/{softwareModuleId}/metadata/{metadataKey}", produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }) - ResponseEntity getMetadataValue(@PathVariable("softwareModuleId") final Long softwareModuleId, + ResponseEntity getMetadataValue( + @PathVariable("softwareModuleId") final Long softwareModuleId, @PathVariable("metadataKey") final String metadataKey); /** @@ -242,13 +245,16 @@ public interface MgmtSoftwareModuleRestApi { * the ID of the software module to update the meta data entry * @param metadataKey * the key of the meta data to update the value + * @param metadata + * body to update * @return status OK if the update request is successful and the updated * meta data result */ @RequestMapping(method = RequestMethod.PUT, value = "/{softwareModuleId}/metadata/{metadataKey}", produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }) - ResponseEntity updateMetadata(@PathVariable("softwareModuleId") final Long softwareModuleId, - @PathVariable("metadataKey") final String metadataKey, final MgmtMetadata metadata); + ResponseEntity updateMetadata( + @PathVariable("softwareModuleId") final Long softwareModuleId, + @PathVariable("metadataKey") final String metadataKey, final MgmtSoftwareModuleMetadataBodyPut metadata); /** * Deletes a single meta data entry from the software module. @@ -276,7 +282,8 @@ public interface MgmtSoftwareModuleRestApi { @RequestMapping(method = RequestMethod.POST, value = "/{softwareModuleId}/metadata", consumes = { MediaType.APPLICATION_JSON_VALUE, MediaTypes.HAL_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }) - ResponseEntity> createMetadata(@PathVariable("softwareModuleId") final Long softwareModuleId, - final List metadataRest); + ResponseEntity> createMetadata( + @PathVariable("softwareModuleId") final Long softwareModuleId, + final List metadataRest); } diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResource.java b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResource.java index 896b15078..b9b89f2ff 100644 --- a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResource.java +++ b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResource.java @@ -13,6 +13,7 @@ import java.util.List; import java.util.stream.Collectors; import org.eclipse.hawkbit.mgmt.json.model.MgmtMetadata; +import org.eclipse.hawkbit.mgmt.json.model.MgmtMetadataBodyPut; import org.eclipse.hawkbit.mgmt.json.model.PagedList; import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSet; import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSetRequestBodyPost; @@ -298,8 +299,9 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi { } @Override - public ResponseEntity updateMetadata(@PathVariable("distributionSetId") final Long distributionSetId, - @PathVariable("metadataKey") final String metadataKey, @RequestBody final MgmtMetadata metadata) { + public ResponseEntity updateMetadata( + @PathVariable("distributionSetId") final Long distributionSetId, + @PathVariable("metadataKey") final String metadataKey, @RequestBody final MgmtMetadataBodyPut metadata) { // check if distribution set exists otherwise throw exception // immediately final DistributionSetMetadata updated = distributionSetManagement.updateMetaData(distributionSetId, diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleMapper.java b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleMapper.java index bf09750e4..bb8952285 100644 --- a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleMapper.java +++ b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleMapper.java @@ -16,18 +16,18 @@ import java.util.Collections; import java.util.List; import java.util.stream.Collectors; -import org.eclipse.hawkbit.mgmt.json.model.MgmtMetadata; import org.eclipse.hawkbit.mgmt.json.model.artifact.MgmtArtifact; import org.eclipse.hawkbit.mgmt.json.model.artifact.MgmtArtifactHash; import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModule; +import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleMetadata; import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleRequestBodyPost; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; import org.eclipse.hawkbit.mgmt.rest.api.MgmtSoftwareModuleRestApi; import org.eclipse.hawkbit.mgmt.rest.api.MgmtSoftwareModuleTypeRestApi; import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.builder.SoftwareModuleCreate; +import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataCreate; import org.eclipse.hawkbit.repository.model.Artifact; -import org.eclipse.hawkbit.repository.model.MetaData; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; import org.eclipse.hawkbit.rest.data.ResponseList; @@ -48,14 +48,16 @@ public final class MgmtSoftwareModuleMapper { .version(smsRest.getVersion()).description(smsRest.getDescription()).vendor(smsRest.getVendor()); } - static List fromRequestSwMetadata(final EntityFactory entityFactory, - final Collection metadata) { + static List fromRequestSwMetadata(final EntityFactory entityFactory, + final Long softwareModuleId, final Collection metadata) { if (metadata == null) { return Collections.emptyList(); } return metadata.stream() - .map(metadataRest -> entityFactory.generateMetadata(metadataRest.getKey(), metadataRest.getValue())) + .map(metadataRest -> entityFactory.softwareModuleMetadata().create(softwareModuleId) + .key(metadataRest.getKey()).value(metadataRest.getValue()) + .targetVisible(metadataRest.isTargetVisible())) .collect(Collectors.toList()); } @@ -77,7 +79,8 @@ public final class MgmtSoftwareModuleMapper { softwareModules.stream().map(MgmtSoftwareModuleMapper::toResponse).collect(Collectors.toList())); } - static List toResponseSwMetadata(final Collection metadata) { + static List toResponseSwMetadata( + final Collection metadata) { if (metadata == null) { return Collections.emptyList(); } @@ -85,10 +88,11 @@ public final class MgmtSoftwareModuleMapper { return metadata.stream().map(MgmtSoftwareModuleMapper::toResponseSwMetadata).collect(Collectors.toList()); } - static MgmtMetadata toResponseSwMetadata(final SoftwareModuleMetadata metadata) { - final MgmtMetadata metadataRest = new MgmtMetadata(); + static MgmtSoftwareModuleMetadata toResponseSwMetadata(final SoftwareModuleMetadata metadata) { + final MgmtSoftwareModuleMetadata metadataRest = new MgmtSoftwareModuleMetadata(); metadataRest.setKey(metadata.getKey()); metadataRest.setValue(metadata.getValue()); + metadataRest.setTargetVisible(metadata.isTargetVisible()); return metadataRest; } diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java index acd8159ff..ab9ad091a 100644 --- a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java +++ b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java @@ -12,10 +12,11 @@ import java.io.IOException; import java.util.Collection; import java.util.List; -import org.eclipse.hawkbit.mgmt.json.model.MgmtMetadata; import org.eclipse.hawkbit.mgmt.json.model.PagedList; import org.eclipse.hawkbit.mgmt.json.model.artifact.MgmtArtifact; import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModule; +import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleMetadata; +import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleMetadataBodyPut; import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleRequestBodyPost; import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleRequestBodyPut; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; @@ -205,7 +206,7 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi { } @Override - public ResponseEntity> getMetadata( + public ResponseEntity> getMetadata( @PathVariable("softwareModuleId") final Long softwareModuleId, @RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam, @RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam, @@ -234,7 +235,8 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi { } @Override - public ResponseEntity getMetadataValue(@PathVariable("softwareModuleId") final Long softwareModuleId, + public ResponseEntity getMetadataValue( + @PathVariable("softwareModuleId") final Long softwareModuleId, @PathVariable("metadataKey") final String metadataKey) { final SoftwareModuleMetadata findOne = softwareModuleManagement @@ -245,10 +247,13 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi { } @Override - public ResponseEntity updateMetadata(@PathVariable("softwareModuleId") final Long softwareModuleId, - @PathVariable("metadataKey") final String metadataKey, @RequestBody final MgmtMetadata metadata) { - final SoftwareModuleMetadata updated = softwareModuleManagement.updateMetaData(softwareModuleId, - entityFactory.generateMetadata(metadataKey, metadata.getValue())); + public ResponseEntity updateMetadata( + @PathVariable("softwareModuleId") final Long softwareModuleId, + @PathVariable("metadataKey") final String metadataKey, + @RequestBody final MgmtSoftwareModuleMetadataBodyPut metadata) { + final SoftwareModuleMetadata updated = softwareModuleManagement + .updateMetaData(entityFactory.softwareModuleMetadata().update(softwareModuleId, metadataKey) + .value(metadata.getValue()).targetVisible(metadata.isTargetVisible())); return ResponseEntity.ok(MgmtSoftwareModuleMapper.toResponseSwMetadata(updated)); } @@ -262,12 +267,12 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi { } @Override - public ResponseEntity> createMetadata( + public ResponseEntity> createMetadata( @PathVariable("softwareModuleId") final Long softwareModuleId, - @RequestBody final List metadataRest) { + @RequestBody final List metadataRest) { - final List created = softwareModuleManagement.createMetaData(softwareModuleId, - MgmtSoftwareModuleMapper.fromRequestSwMetadata(entityFactory, metadataRest)); + final List created = softwareModuleManagement.createMetaData( + MgmtSoftwareModuleMapper.fromRequestSwMetadata(entityFactory, softwareModuleId, metadataRest)); return ResponseEntity.status(HttpStatus.CREATED).body(MgmtSoftwareModuleMapper.toResponseSwMetadata(created)); } diff --git a/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java b/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java index 80fa141fc..d410d29cf 100644 --- a/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java +++ b/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java @@ -85,9 +85,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra final String updateVendor = "newVendor1"; final String updateDescription = "newDescription1"; - SoftwareModule sm = softwareModuleManagement - .create(entityFactory.softwareModule().create().type(osType).name(knownSWName) - .version(knownSWVersion).description(knownSWDescription).vendor(knownSWVendor)); + SoftwareModule sm = softwareModuleManagement.create(entityFactory.softwareModule().create().type(osType) + .name(knownSWName).version(knownSWVersion).description(knownSWDescription).vendor(knownSWVendor)); assertThat(sm.getName()).as("Wrong name of the software module").isEqualTo(knownSWName); @@ -140,8 +139,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra // check rest of response compared to DB final MgmtArtifact artResult = ResourceUtility .convertArtifactResponse(mvcResult.getResponse().getContentAsString()); - final Long artId = softwareModuleManagement.get(sm.getId()).get().getArtifacts().get(0) - .getId(); + final Long artId = softwareModuleManagement.get(sm.getId()).get().getArtifacts().get(0).getId(); assertThat(artResult.getArtifactId()).as("Wrong artifact id").isEqualTo(artId); assertThat(JsonPath.compile("$._links.self.href").read(mvcResult.getResponse().getContentAsString()).toString()) .as("Link contains no self url") @@ -159,8 +157,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra assertThat(artifactManagement.count()).as("Wrong artifact size").isEqualTo(1); // binary - try (InputStream fileInputStream = artifactManagement.loadArtifactBinary( - softwareModuleManagement.get(sm.getId()).get().getArtifacts().get(0).getSha1Hash()) + try (InputStream fileInputStream = artifactManagement + .loadArtifactBinary(softwareModuleManagement.get(sm.getId()).get().getArtifacts().get(0).getSha1Hash()) .get().getFileInputStream()) { assertTrue("Wrong artifact content", IOUtils.contentEquals(new ByteArrayInputStream(random), fileInputStream)); @@ -174,9 +172,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra .isEqualTo(HashGeneratorUtils.generateMD5(random)); // metadata - assertThat( - softwareModuleManagement.get(sm.getId()).get().getArtifacts().get(0).getFilename()) - .as("wrong metadata of the filename").isEqualTo("origFilename"); + assertThat(softwareModuleManagement.get(sm.getId()).get().getArtifacts().get(0).getFilename()) + .as("wrong metadata of the filename").isEqualTo("origFilename"); } @Test @@ -237,8 +234,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra assertThat(artifactManagement.count()).isEqualTo(1); // hashes - assertThat(artifactManagement.getByFilename("customFilename")).as("Local artifact is wrong") - .isPresent(); + assertThat(artifactManagement.getByFilename("customFilename")).as("Local artifact is wrong").isPresent(); } @Test @@ -291,10 +287,10 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra final byte random[] = RandomStringUtils.random(5 * 1024).getBytes(); - final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), - "file1", false); - final Artifact artifact2 = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), - "file2", false); + final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file1", + false); + final Artifact artifact2 = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file2", + false); downloadAndVerify(sm, random, artifact); downloadAndVerify(sm, random, artifact2); @@ -321,8 +317,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); final byte random[] = RandomStringUtils.random(5 * 1024).getBytes(); - final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), - "file1", false); + final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file1", + false); // perform test mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts/{artId}", sm.getId(), artifact.getId()) @@ -347,10 +343,10 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra final byte random[] = RandomStringUtils.random(5 * 1024).getBytes(); - final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), - "file1", false); - final Artifact artifact2 = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), - "file2", false); + final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file1", + false); + final Artifact artifact2 = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file2", + false); mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).accept(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) @@ -678,16 +674,14 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra .isEqualTo("http://localhost/rest/v1/softwaremodules/" + appCreated.getId()); assertThat(softwareModuleManagement.findAll(PAGE)).as("Wrong softwaremodule size").hasSize(2); - assertThat( - softwareModuleManagement.findByType(PAGE, osType.getId()).getContent().get(0).getName()) - .as("Softwaremoudle name is wrong").isEqualTo(os.getName()); - assertThat(softwareModuleManagement.findByType(PAGE, osType.getId()).getContent().get(0) - .getCreatedBy()).as("Softwaremoudle created by is wrong").isEqualTo("uploadTester"); - assertThat(softwareModuleManagement.findByType(PAGE, osType.getId()).getContent().get(0) - .getCreatedAt()).as("Softwaremoudle created at is wrong").isGreaterThanOrEqualTo(current); - assertThat( - softwareModuleManagement.findByType(PAGE, appType.getId()).getContent().get(0).getName()) - .as("Softwaremoudle name is wrong").isEqualTo(ah.getName()); + assertThat(softwareModuleManagement.findByType(PAGE, osType.getId()).getContent().get(0).getName()) + .as("Softwaremoudle name is wrong").isEqualTo(os.getName()); + assertThat(softwareModuleManagement.findByType(PAGE, osType.getId()).getContent().get(0).getCreatedBy()) + .as("Softwaremoudle created by is wrong").isEqualTo("uploadTester"); + assertThat(softwareModuleManagement.findByType(PAGE, osType.getId()).getContent().get(0).getCreatedAt()) + .as("Softwaremoudle created at is wrong").isGreaterThanOrEqualTo(current); + assertThat(softwareModuleManagement.findByType(PAGE, appType.getId()).getContent().get(0).getName()) + .as("Softwaremoudle name is wrong").isEqualTo(ah.getName()); } @Test @@ -706,8 +700,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra mvc.perform(delete("/rest/v1/softwaremodules/{smId}", sm.getId())).andDo(MockMvcResultPrinter.print()) .andExpect(status().isOk()); - assertThat(softwareModuleManagement.findAll(PAGE)) - .as("After delete no softwarmodule should be available").isEmpty(); + assertThat(softwareModuleManagement.findAll(PAGE)).as("After delete no softwarmodule should be available") + .isEmpty(); assertThat(artifactManagement.count()).isEqualTo(0); } @@ -718,8 +712,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra final byte random[] = RandomStringUtils.random(5 * 1024).getBytes(); - artifactManagement.create(new ByteArrayInputStream(random), - ds1.findFirstModuleByType(appType).get().getId(), "file1", false); + artifactManagement.create(new ByteArrayInputStream(random), ds1.findFirstModuleByType(appType).get().getId(), + "file1", false); assertThat(softwareModuleManagement.findAll(PAGE)).hasSize(3); assertThat(artifactManagement.count()).isEqualTo(1); @@ -746,8 +740,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra final byte random[] = RandomStringUtils.random(5 * 1024).getBytes(); // Create 2 artifacts - final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), - "file1", false); + final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file1", + false); artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file2", false); // check repo before delete @@ -761,8 +755,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); // check that only one artifact is still alive and still assigned - assertThat(softwareModuleManagement.findAll(PAGE)).as("After the sm should be marked as deleted") - .hasSize(1); + assertThat(softwareModuleManagement.findAll(PAGE)).as("After the sm should be marked as deleted").hasSize(1); assertThat(artifactManagement.count()).isEqualTo(1); assertThat(softwareModuleManagement.get(sm.getId()).get().getArtifacts()) .as("After delete artifact should available for marked as deleted sm's").hasSize(1); @@ -775,22 +768,23 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra final String knownKey1 = "knownKey1"; final String knownValue1 = "knownValue1"; - final String knownKey2 = "knownKey1"; + final String knownKey2 = "knownKey2"; final String knownValue2 = "knownValue1"; final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); final JSONArray jsonArray = new JSONArray(); jsonArray.put(new JSONObject().put("key", knownKey1).put("value", knownValue1)); - jsonArray.put(new JSONObject().put("key", knownKey2).put("value", knownValue2)); + jsonArray.put(new JSONObject().put("key", knownKey2).put("value", knownValue2).put("targetVisible", true)); mvc.perform(post("/rest/v1/softwaremodules/{swId}/metadata", sm.getId()).accept(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON).content(jsonArray.toString())) .andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()) .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) .andExpect(jsonPath("[0]key", equalTo(knownKey1))).andExpect(jsonPath("[0]value", equalTo(knownValue1))) - .andExpect(jsonPath("[1]key", equalTo(knownKey2))) - .andExpect(jsonPath("[1]value", equalTo(knownValue2))); + .andExpect(jsonPath("[0]targetVisible", equalTo(false))) + .andExpect(jsonPath("[1]key", equalTo(knownKey2))).andExpect(jsonPath("[1]value", equalTo(knownValue2))) + .andExpect(jsonPath("[1]targetVisible", equalTo(true))); final SoftwareModuleMetadata metaKey1 = softwareModuleManagement .getMetaDataBySoftwareModuleId(sm.getId(), knownKey1).get(); @@ -810,10 +804,11 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra final String updateValue = "valueForUpdate"; final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); - softwareModuleManagement.createMetaData(sm.getId(), - entityFactory.generateMetadata(knownKey, knownValue)); + softwareModuleManagement.createMetaData( + entityFactory.softwareModuleMetadata().create(sm.getId()).key(knownKey).value(knownValue)); - final JSONObject jsonObject = new JSONObject().put("key", knownKey).put("value", updateValue); + final JSONObject jsonObject = new JSONObject().put("key", knownKey).put("value", updateValue) + .put("targetVisible", true); mvc.perform(put("/rest/v1/softwaremodules/{swId}/metadata/{key}", sm.getId(), knownKey) .accept(MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_JSON) @@ -824,6 +819,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra final SoftwareModuleMetadata assertDS = softwareModuleManagement .getMetaDataBySoftwareModuleId(sm.getId(), knownKey).get(); assertThat(assertDS.getValue()).as("Metadata is wrong").isEqualTo(updateValue); + assertThat(assertDS.isTargetVisible()).as("target visible is wrong").isTrue(); } @Test @@ -834,8 +830,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra final String knownValue = "knownValue"; final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); - softwareModuleManagement.createMetaData(sm.getId(), - entityFactory.generateMetadata(knownKey, knownValue)); + softwareModuleManagement.createMetaData( + entityFactory.softwareModuleMetadata().create(sm.getId()).key(knownKey).value(knownValue)); mvc.perform(delete("/rest/v1/softwaremodules/{swId}/metadata/{key}", sm.getId(), knownKey)) .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); @@ -851,8 +847,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra final String knownValue = "knownValue"; final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); - softwareModuleManagement.createMetaData(sm.getId(), - entityFactory.generateMetadata(knownKey, knownValue)); + softwareModuleManagement.createMetaData( + entityFactory.softwareModuleMetadata().create(sm.getId()).key(knownKey).value(knownValue)); mvc.perform(delete("/rest/v1/softwaremodules/{swId}/metadata/XXX", sm.getId(), knownKey)) .andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound()); @@ -879,8 +875,8 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); for (int index = 0; index < totalMetadata; index++) { - softwareModuleManagement.createMetaData(sm.getId(), - entityFactory.generateMetadata(knownKeyPrefix + index, knownValuePrefix + index)); + softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata().create(sm.getId()) + .key(knownKeyPrefix + index).value(knownValuePrefix + index)); } final String rsqlSearchValue1 = "value==knownValue1"; 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 863212a25..5bd07e6d5 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 @@ -9,6 +9,7 @@ package org.eclipse.hawkbit.repository; import java.net.URI; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Optional; @@ -25,6 +26,7 @@ import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.model.SoftwareModule; +import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey; @@ -72,7 +74,20 @@ public interface ControllerManagement { * @return {@link SoftwareModule} identified by ID */ @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER) - Optional getSoftwareModule(@NotNull final Long moduleId); + Optional getSoftwareModule(@NotNull Long moduleId); + + /** + * Retrieves {@link SoftwareModuleMetadata} where + * {@link SoftwareModuleMetadata#isTargetVisible()}. + * + * @param moduleId + * of the {@link SoftwareModule} + * @return list of {@link SoftwareModuleMetadata} with maximum size of + * {@link RepositoryConstants#MAX_META_DATA_COUNT} + */ + @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER) + Map> findTargetVisibleMetaDataBySoftwareModuleId( + @NotNull Collection moduleId); /** * Simple addition of a new {@link ActionStatus} entry to the {@link Action} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/EntityFactory.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/EntityFactory.java index d0036c4d2..0de3174bf 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/EntityFactory.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/EntityFactory.java @@ -9,6 +9,7 @@ package org.eclipse.hawkbit.repository; import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; import org.eclipse.hawkbit.repository.builder.ActionStatusBuilder; import org.eclipse.hawkbit.repository.builder.DistributionSetBuilder; @@ -16,13 +17,13 @@ import org.eclipse.hawkbit.repository.builder.DistributionSetTypeBuilder; import org.eclipse.hawkbit.repository.builder.RolloutBuilder; import org.eclipse.hawkbit.repository.builder.RolloutGroupBuilder; import org.eclipse.hawkbit.repository.builder.SoftwareModuleBuilder; +import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataBuilder; import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeBuilder; import org.eclipse.hawkbit.repository.builder.TagBuilder; import org.eclipse.hawkbit.repository.builder.TargetBuilder; import org.eclipse.hawkbit.repository.builder.TargetFilterQueryBuilder; import org.eclipse.hawkbit.repository.model.BaseEntity; import org.eclipse.hawkbit.repository.model.MetaData; -import org.hibernate.validator.constraints.NotEmpty; /** * central {@link BaseEntity} generation service. Objects are created but not @@ -51,7 +52,13 @@ public interface EntityFactory { * * @return {@link MetaData} object */ - MetaData generateMetadata(@NotEmpty String key, @NotNull String value); + MetaData generateMetadata(@Size(min = 1, max = MetaData.KEY_MAX_SIZE) @NotNull String key, + @Size(min = 1, max = MetaData.VALUE_MAX_SIZE) @NotNull String value); + + /** + * @return {@link SoftwareModuleMetadataBuilder} object + */ + SoftwareModuleMetadataBuilder softwareModuleMetadata(); /** * @return {@link TagBuilder} object diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RepositoryConstants.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RepositoryConstants.java index e4d801b8e..9ec08272d 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RepositoryConstants.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RepositoryConstants.java @@ -8,8 +8,10 @@ */ package org.eclipse.hawkbit.repository; +import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.model.DistributionSetType; +import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; /** * Repository constants. @@ -36,6 +38,13 @@ public final class RepositoryConstants { */ public static final int MAX_ACTION_HISTORY_MSG_COUNT = 100; + /** + * Maximum number of metadata entries provided to controllers. + * + * @see SoftwareModuleMetadata#isTargetVisible() + */ + public static final int MAX_META_DATA_COUNT = 50; + private RepositoryConstants() { // Utility class. } 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 dc5076444..3803177fb 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 @@ -16,6 +16,8 @@ import javax.validation.constraints.NotNull; import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; import org.eclipse.hawkbit.repository.builder.SoftwareModuleCreate; +import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataCreate; +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; @@ -23,7 +25,6 @@ import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.repository.model.AssignedSoftwareModule; import org.eclipse.hawkbit.repository.model.DistributionSet; -import org.eclipse.hawkbit.repository.model.MetaData; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; @@ -60,10 +61,8 @@ public interface SoftwareModuleManagement /** * creates a list of software module meta data entries. * - * @param moduleId - * the metadata belongs to * @param metadata - * the meta data entries to create or update + * the meta data entries to create * @return the updated or created software module meta data entries * @throws EntityAlreadyExistsException * in case one of the meta data entry already exists for the @@ -72,15 +71,13 @@ public interface SoftwareModuleManagement * if software module with given ID does not exist */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - List createMetaData(@NotNull Long moduleId, @NotNull Collection metadata); + List createMetaData(@NotNull Collection metadata); /** * creates or updates a single software module meta data entry. * - * @param moduleId - * the metadata belongs to * @param metadata - * the meta data entry to create or update + * the meta data entry to create * @return the updated or created software module meta data entry * @throws EntityAlreadyExistsException * in case the meta data entry already exists for the specific @@ -89,7 +86,7 @@ public interface SoftwareModuleManagement * if software module with given ID does not exist */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - SoftwareModuleMetadata createMetaData(@NotNull Long moduleId, @NotNull MetaData metadata); + SoftwareModuleMetadata createMetaData(@NotNull SoftwareModuleMetadataCreate metadata); /** * deletes a software module meta data entry. @@ -188,6 +185,25 @@ public interface SoftwareModuleManagement @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) Page findMetaDataBySoftwareModuleId(@NotNull Pageable pageable, @NotNull Long moduleId); + /** + * finds all meta data by the given software module id where + * {@link SoftwareModuleMetadata#isTargetVisible()}. + * + * @param pageable + * the page request to page the result + * @param moduleId + * the software module id to retrieve the meta data from + * + * @return a paged result of all meta data entries for a given software + * module id + * + * @throws EntityNotFoundException + * if software module with given ID does not exist + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Page findMetaDataBySoftwareModuleIdAndTargetVisible(@NotNull Pageable pageable, + @NotNull Long moduleId); + /** * finds all meta data by the given software module id. * @@ -259,9 +275,7 @@ public interface SoftwareModuleManagement /** * updates a distribution set meta data value if corresponding entry exists. * - * @param moduleId - * the metadata belongs to - * @param metadata + * @param update * the meta data entry to be updated * * @return the updated meta data entry @@ -271,5 +285,5 @@ public interface SoftwareModuleManagement * updated */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - SoftwareModuleMetadata updateMetaData(@NotNull Long moduleId, @NotNull MetaData metadata); + SoftwareModuleMetadata updateMetaData(@NotNull SoftwareModuleMetadataUpdate update); } diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java index fcad67fd7..6a144096f 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java @@ -57,6 +57,8 @@ public interface SystemManagement { /** * Runs consumer for each teant as * {@link TenantAware#runAsTenant(String, org.eclipse.hawkbit.tenancy.TenantAware.TenantRunner)} + * sliently (i.e. exceptions will be logged but operations will continue for + * further tenants). * * @param consumer * to run as teanant diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataBuilder.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataBuilder.java new file mode 100644 index 000000000..b4a748744 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataBuilder.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2015 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.builder; + +import org.eclipse.hawkbit.repository.model.MetaData; +import org.eclipse.hawkbit.repository.model.SoftwareModule; +import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; + +/** + * Builder for {@link SoftwareModuleMetadata}. + * + */ +public interface SoftwareModuleMetadataBuilder { + + /** + * @param softwareModuleId + * of the {@link SoftwareModule} the {@link MetaData} belongs to + * @param key + * of {@link MetaData#getKey()} + * @return builder instance + */ + SoftwareModuleMetadataUpdate update(long softwareModuleId, String key); + + /** + * @param softwareModuleId + * of the {@link SoftwareModule} the {@link MetaData} belongs to + * @return builder instance + */ + SoftwareModuleMetadataCreate create(long softwareModuleId); + +} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataCreate.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataCreate.java new file mode 100644 index 000000000..6bcf6ce11 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataCreate.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2015 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.builder; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import org.eclipse.hawkbit.repository.model.BaseEntity; +import org.eclipse.hawkbit.repository.model.MetaData; +import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; + +/** + * Builder to create a new {@link SoftwareModuleMetadata} entry. Defines all + * fields that can be set at creation time. Other fields are set by the + * repository automatically, e.g. {@link BaseEntity#getCreatedAt()}. + * + */ +public interface SoftwareModuleMetadataCreate { + + /** + * @param key + * for {@link MetaData#getKey()} + * @return updated builder instance + */ + SoftwareModuleMetadataCreate key(@Size(min = 1, max = MetaData.KEY_MAX_SIZE) @NotNull String key); + + /** + * @param value + * for {@link MetaData#getValue()} + * @return updated builder instance + */ + SoftwareModuleMetadataCreate value(@Size(min = 1, max = MetaData.VALUE_MAX_SIZE) @NotNull String value); + + /** + * @param visible + * for {@link SoftwareModuleMetadata#isTargetVisible()} + * @return updated builder instance + */ + SoftwareModuleMetadataCreate targetVisible(Boolean visible); + + /** + * @return peek on current state of {@link SoftwareModuleMetadata} in the + * builder + */ + SoftwareModuleMetadata build(); + +} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataUpdate.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataUpdate.java new file mode 100644 index 000000000..9a3734f60 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleMetadataUpdate.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2015 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.builder; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import org.eclipse.hawkbit.repository.model.MetaData; +import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; + +/** + * Builder to update an existing {@link SoftwareModuleMetadata} entry. Defines + * all fields that can be updated. + * + */ +public interface SoftwareModuleMetadataUpdate { + /** + * @param value + * for {@link MetaData#getValue()} + * @return updated builder instance + */ + SoftwareModuleMetadataUpdate value(@Size(min = 1, max = MetaData.VALUE_MAX_SIZE) @NotNull String value); + + /** + * @param visible + * for {@link SoftwareModuleMetadata#isTargetVisible()} + * @return updated builder instance + */ + SoftwareModuleMetadataUpdate targetVisible(Boolean visible); + +} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSetMetadata.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSetMetadata.java index 87a62e9ba..6e43d18cf 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSetMetadata.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSetMetadata.java @@ -19,4 +19,9 @@ public interface DistributionSetMetadata extends MetaData { */ DistributionSet getDistributionSet(); + @Override + default Long getEntityId() { + return getDistributionSet().getId(); + } + } diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/MetaData.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/MetaData.java index e3322782f..d8433609b 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/MetaData.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/MetaData.java @@ -15,6 +15,20 @@ import java.io.Serializable; * */ public interface MetaData extends Serializable { + /** + * Maximum length of metadata key. + */ + int KEY_MAX_SIZE = 128; + + /** + * Maximum length of metadata value. + */ + int VALUE_MAX_SIZE = 4000; + + /** + * @return {@link BaseEntity#getId()} the metadata is related to + */ + Long getEntityId(); /** * @return the key diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/SoftwareModuleMetadata.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/SoftwareModuleMetadata.java index cfb5be5d1..23058447b 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/SoftwareModuleMetadata.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/SoftwareModuleMetadata.java @@ -18,4 +18,15 @@ public interface SoftwareModuleMetadata extends MetaData { * @return {@link SoftwareModule} this entry belongs to. */ SoftwareModule getSoftwareModule(); + + @Override + default Long getEntityId() { + return getSoftwareModule().getId(); + } + + /** + * @return true if element is visible for targets as part of + * {@link Action}. + */ + boolean isTargetVisible(); } diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractMetadataUpdateCreate.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractMetadataUpdateCreate.java new file mode 100644 index 000000000..5bddf2edf --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractMetadataUpdateCreate.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2015 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.builder; + +import java.util.Optional; + +/** + * Create and update builder DTO. + * + * @param + * update or create builder interface + */ +public abstract class AbstractMetadataUpdateCreate { + protected String key; + protected String value; + + public T key(final String key) { + this.key = key; + return (T) this; + } + + public String getKey() { + return key; + } + + public T value(final String value) { + this.value = value; + return (T) this; + } + + public Optional getValue() { + return Optional.ofNullable(value); + } + +} diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractSoftwareModuleMetadataUpdateCreate.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractSoftwareModuleMetadataUpdateCreate.java new file mode 100644 index 000000000..5833bd812 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractSoftwareModuleMetadataUpdateCreate.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2015 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.builder; + +import java.util.Optional; + +/** + * Create and update builder DTO. + * + * @param + * update or create builder interface + */ +public abstract class AbstractSoftwareModuleMetadataUpdateCreate extends AbstractMetadataUpdateCreate { + protected Boolean targetVisible; + protected long softwareModuleId; + + public T softwareModuleId(final long softwareModuleId) { + this.softwareModuleId = softwareModuleId; + return (T) this; + } + + public long getSoftwareModuleId() { + return softwareModuleId; + } + + public Optional isTargetVisible() { + return Optional.ofNullable(targetVisible); + } + + public T targetVisible(final Boolean targetVisible) { + this.targetVisible = targetVisible; + return (T) this; + } + +} diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/GenericSoftwareModuleMetadataUpdate.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/GenericSoftwareModuleMetadataUpdate.java new file mode 100644 index 000000000..d05bece24 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/GenericSoftwareModuleMetadataUpdate.java @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2015 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.builder; + +/** + * Update implementation. + */ +public class GenericSoftwareModuleMetadataUpdate + extends AbstractSoftwareModuleMetadataUpdateCreate + implements SoftwareModuleMetadataUpdate { + + public GenericSoftwareModuleMetadataUpdate(final long softwareModuleId, final String key) { + super.softwareModuleId = softwareModuleId; + this.key = key; + } + +} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java index 702824861..f2e499743 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java @@ -9,10 +9,12 @@ package org.eclipse.hawkbit.repository.jpa; import java.net.URI; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.stream.Collectors; import javax.persistence.EntityManager; import javax.persistence.criteria.CriteriaBuilder; @@ -45,6 +47,7 @@ import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.model.SoftwareModule; +import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.security.SystemSecurityContext; @@ -115,6 +118,9 @@ public class JpaControllerManagement implements ControllerManagement { @Autowired private AfterTransactionCommitExecutor afterCommit; + @Autowired + private SoftwareModuleMetadataRepository softwareModuleMetadataRepository; + @Override public String getPollingTime() { return systemSecurityContext.runAsSystem(() -> tenantConfigurationManagement @@ -523,4 +529,15 @@ public class JpaControllerManagement implements ControllerManagement { public Optional getSoftwareModule(final Long id) { return Optional.ofNullable(softwareModuleRepository.findOne(id)); } + + @Override + public Map> findTargetVisibleMetaDataBySoftwareModuleId( + final Collection moduleId) { + + return softwareModuleMetadataRepository + .findBySoftwareModuleIdInAndTargetVisible(new PageRequest(0, RepositoryConstants.MAX_META_DATA_COUNT), + moduleId, true) + .getContent().stream().collect(Collectors.groupingBy(o -> (Long) o[0], + Collectors.mapping(o -> (SoftwareModuleMetadata) o[1], Collectors.toList()))); + } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaEntityFactory.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaEntityFactory.java index 43d67f576..59566da63 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaEntityFactory.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaEntityFactory.java @@ -15,6 +15,7 @@ import org.eclipse.hawkbit.repository.builder.DistributionSetTypeBuilder; import org.eclipse.hawkbit.repository.builder.RolloutBuilder; import org.eclipse.hawkbit.repository.builder.RolloutGroupBuilder; import org.eclipse.hawkbit.repository.builder.SoftwareModuleBuilder; +import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataBuilder; import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeBuilder; import org.eclipse.hawkbit.repository.builder.TagBuilder; import org.eclipse.hawkbit.repository.builder.TargetBuilder; @@ -24,7 +25,7 @@ import org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutGroupBuilder; import org.eclipse.hawkbit.repository.jpa.builder.JpaSoftwareModuleTypeBuilder; import org.eclipse.hawkbit.repository.jpa.builder.JpaTagBuilder; import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetBuilder; -import org.eclipse.hawkbit.repository.jpa.model.JpaMetaData; +import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata; import org.eclipse.hawkbit.repository.model.MetaData; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; @@ -51,9 +52,12 @@ public class JpaEntityFactory implements EntityFactory { @Autowired private TargetFilterQueryBuilder targetFilterQueryBuilder; + @Autowired + private SoftwareModuleMetadataBuilder softwareModuleMetadataBuilder; + @Override public MetaData generateMetadata(final String key, final String value) { - return new JpaMetaData(key, value); + return new JpaDistributionSetMetadata(key, value); } @Override @@ -106,4 +110,9 @@ public class JpaEntityFactory implements EntityFactory { return new JpaRolloutGroupBuilder(); } + @Override + public SoftwareModuleMetadataBuilder softwareModuleMetadata() { + return softwareModuleMetadataBuilder; + } + } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareModuleManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareModuleManagement.java index c06c8f244..9490863cf 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareModuleManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareModuleManagement.java @@ -28,15 +28,20 @@ import javax.persistence.criteria.Root; import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; import org.eclipse.hawkbit.repository.ArtifactManagement; +import org.eclipse.hawkbit.repository.RepositoryConstants; import org.eclipse.hawkbit.repository.SoftwareModuleFields; import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.SoftwareModuleMetadataFields; +import org.eclipse.hawkbit.repository.builder.GenericSoftwareModuleMetadataUpdate; import org.eclipse.hawkbit.repository.builder.GenericSoftwareModuleUpdate; import org.eclipse.hawkbit.repository.builder.SoftwareModuleCreate; +import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataCreate; +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.jpa.builder.JpaSoftwareModuleCreate; +import org.eclipse.hawkbit.repository.jpa.builder.JpaSoftwareModuleMetadataCreate; import org.eclipse.hawkbit.repository.jpa.configuration.Constants; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_; @@ -51,7 +56,6 @@ import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder; import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.AssignedSoftwareModule; import org.eclipse.hawkbit.repository.model.DistributionSet; -import org.eclipse.hawkbit.repository.model.MetaData; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; @@ -61,6 +65,7 @@ import org.springframework.dao.ConcurrencyFailureException; import org.springframework.data.domain.AuditorAware; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.domain.SliceImpl; @@ -443,15 +448,17 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { @Transactional @Retryable(include = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public SoftwareModuleMetadata createMetaData(final Long moduleId, final MetaData md) { + public SoftwareModuleMetadata createMetaData(final SoftwareModuleMetadataCreate c) { + final JpaSoftwareModuleMetadataCreate create = (JpaSoftwareModuleMetadataCreate) c; - checkAndThrowAlreadyIfSoftwareModuleMetadataExists(moduleId, md); + checkAndThrowAlreadyIfSoftwareModuleMetadataExists(create.getSoftwareModuleId(), create); + touch(create.getSoftwareModuleId()); - return softwareModuleMetadataRepository - .save(new JpaSoftwareModuleMetadata(md.getKey(), touch(moduleId), md.getValue())); + return softwareModuleMetadataRepository.save(create.build()); } - private void checkAndThrowAlreadyIfSoftwareModuleMetadataExists(final Long moduleId, final MetaData md) { + private void checkAndThrowAlreadyIfSoftwareModuleMetadataExists(final Long moduleId, + final JpaSoftwareModuleMetadataCreate md) { if (softwareModuleMetadataRepository.exists(new SwMetadataCompositeKey(moduleId, md.getKey()))) { throwMetadataKeyAlreadyExists(md.getKey()); } @@ -461,28 +468,26 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { @Transactional @Retryable(include = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public List createMetaData(final Long moduleId, final Collection md) { - md.forEach(meta -> checkAndThrowAlreadyIfSoftwareModuleMetadataExists(moduleId, meta)); + public List createMetaData(final Collection create) { - final JpaSoftwareModule module = touch(moduleId); - - return Collections.unmodifiableList(md.stream() - .map(meta -> softwareModuleMetadataRepository - .save(new JpaSoftwareModuleMetadata(meta.getKey(), module, meta.getValue()))) - .collect(Collectors.toList())); + return create.stream().map(this::createMetaData).collect(Collectors.toList()); } @Override @Transactional @Retryable(include = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public SoftwareModuleMetadata updateMetaData(final Long moduleId, final MetaData md) { + public SoftwareModuleMetadata updateMetaData(final SoftwareModuleMetadataUpdate u) { + final GenericSoftwareModuleMetadataUpdate update = (GenericSoftwareModuleMetadataUpdate) u; // check if exists otherwise throw entity not found exception - final JpaSoftwareModuleMetadata metadata = (JpaSoftwareModuleMetadata) getMetaDataBySoftwareModuleId(moduleId, - md.getKey()).orElseThrow( - () -> new EntityNotFoundException(SoftwareModuleMetadata.class, moduleId, md.getKey())); - metadata.setValue(md.getValue()); + final JpaSoftwareModuleMetadata metadata = (JpaSoftwareModuleMetadata) getMetaDataBySoftwareModuleId( + update.getSoftwareModuleId(), update.getKey()) + .orElseThrow(() -> new EntityNotFoundException(SoftwareModuleMetadata.class, + update.getSoftwareModuleId(), update.getKey())); + + update.getValue().ifPresent(metadata::setValue); + update.isTargetVisible().ifPresent(metadata::setTargetVisible); touch(metadata.getSoftwareModule()); return softwareModuleMetadataRepository.save(metadata); @@ -593,4 +598,13 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { return softwareModuleRepository.exists(id); } + @Override + public Page findMetaDataBySoftwareModuleIdAndTargetVisible(final Pageable pageable, + final Long moduleId) { + throwExceptionIfSoftwareModuleDoesNotExist(moduleId); + + return convertMdPage(softwareModuleMetadataRepository.findBySoftwareModuleIdAndTargetVisible( + new PageRequest(0, RepositoryConstants.MAX_META_DATA_COUNT), moduleId, true), pageable); + } + } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSystemManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSystemManagement.java index c91d24421..cf4671092 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSystemManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSystemManagement.java @@ -34,6 +34,8 @@ import org.eclipse.hawkbit.repository.report.model.SystemUsageReportWithTenants; import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.tenancy.TenantAware; import org.eclipse.persistence.config.PersistenceUnitProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.interceptor.KeyGenerator; @@ -59,6 +61,8 @@ import org.springframework.validation.annotation.Validated; @Transactional(readOnly = true) @Validated public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, SystemManagement { + private static final Logger LOGGER = LoggerFactory.getLogger(JpaSystemManagement.class); + private static final int MAX_TENANTS_QUERY = 500; @Autowired @@ -328,7 +332,12 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst do { tenants = findTenants(query); tenants.forEach(tenant -> tenantAware.runAsTenant(tenant, () -> { - consumer.accept(tenant); + try { + consumer.accept(tenant); + } catch (final RuntimeException ex) { + LOGGER.error("Exception on forEachTenant execution for tenant {}. Continue with next tenant.", + tenant, ex); + } return null; })); } while (tenants.hasNext() && (query = tenants.nextPageable()) != null); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java index b70a6acbb..5f9f5c0a6 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java @@ -39,6 +39,7 @@ import org.eclipse.hawkbit.repository.builder.DistributionSetBuilder; import org.eclipse.hawkbit.repository.builder.DistributionSetTypeBuilder; import org.eclipse.hawkbit.repository.builder.RolloutBuilder; import org.eclipse.hawkbit.repository.builder.SoftwareModuleBuilder; +import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataBuilder; import org.eclipse.hawkbit.repository.builder.TargetFilterQueryBuilder; import org.eclipse.hawkbit.repository.event.ApplicationEventFilter; import org.eclipse.hawkbit.repository.event.remote.EventEntityManager; @@ -51,6 +52,7 @@ import org.eclipse.hawkbit.repository.jpa.builder.JpaDistributionSetBuilder; import org.eclipse.hawkbit.repository.jpa.builder.JpaDistributionSetTypeBuilder; import org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutBuilder; import org.eclipse.hawkbit.repository.jpa.builder.JpaSoftwareModuleBuilder; +import org.eclipse.hawkbit.repository.jpa.builder.JpaSoftwareModuleMetadataBuilder; import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetFilterQueryBuilder; import org.eclipse.hawkbit.repository.jpa.configuration.MultiTenantJpaTransactionManager; import org.eclipse.hawkbit.repository.jpa.event.JpaEventEntityManager; @@ -167,6 +169,12 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { return new JpaDistributionSetBuilder(distributionSetTypeManagement, softwareManagement); } + @Bean + SoftwareModuleMetadataBuilder softwareModuleMetadataBuilder( + final SoftwareModuleManagement softwareModuleManagement) { + return new JpaSoftwareModuleMetadataBuilder(softwareModuleManagement); + } + /** * @param softwareManagement * for loading diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RolloutGroupRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RolloutGroupRepository.java index 839a21a53..fd8b4cd08 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RolloutGroupRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RolloutGroupRepository.java @@ -38,7 +38,7 @@ public interface RolloutGroupRepository * the rollout the rolloutgroups belong to * @return the rollout groups belonging to a rollout ordered by ID ASC. */ - List findByRolloutOrderByIdAsc(final JpaRollout rollout); + List findByRolloutOrderByIdAsc(JpaRollout rollout); /** * Retrieves all {@link RolloutGroup} referring a specific rollout in a @@ -50,7 +50,7 @@ public interface RolloutGroupRepository * the status of the rollout groups * @return the rollout groups belonging to a rollout in a specific status */ - List findByRolloutAndStatus(final Rollout rollout, final RolloutGroupStatus status); + List findByRolloutAndStatus(Rollout rollout, RolloutGroupStatus status); /** * Counts all {@link RolloutGroup} referring a specific rollout in specific diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleMetadataRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleMetadataRepository.java index d874025a0..2616d8e03 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleMetadataRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleMetadataRepository.java @@ -8,11 +8,17 @@ */ package org.eclipse.hawkbit.repository.jpa; +import java.util.Collection; + import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleMetadata; import org.eclipse.hawkbit.repository.jpa.model.SwMetadataCompositeKey; import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.data.repository.query.Param; import org.springframework.transaction.annotation.Transactional; /** @@ -24,4 +30,11 @@ public interface SoftwareModuleMetadataRepository extends PagingAndSortingRepository, JpaSpecificationExecutor { + Page findBySoftwareModuleIdAndTargetVisible(Pageable page, Long moduleId, + boolean targetVisible); + + @Query("SELECT smd.softwareModule.id, smd FROM JpaSoftwareModuleMetadata smd WHERE smd.softwareModule.id IN :moduleId AND smd.targetVisible = :targetVisible") + Page findBySoftwareModuleIdInAndTargetVisible(Pageable page, @Param("moduleId") Collection moduleId, + @Param("targetVisible") boolean targetVisible); + } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleMetadataBuilder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleMetadataBuilder.java new file mode 100644 index 000000000..ddb9cd50d --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleMetadataBuilder.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2015 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.builder; + +import org.eclipse.hawkbit.repository.SoftwareModuleManagement; +import org.eclipse.hawkbit.repository.builder.GenericSoftwareModuleMetadataUpdate; +import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataBuilder; +import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataCreate; +import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataUpdate; +import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; + +/** + * Builder implementation for {@link SoftwareModuleMetadata}. + * + */ +public class JpaSoftwareModuleMetadataBuilder implements SoftwareModuleMetadataBuilder { + + private final SoftwareModuleManagement softwareModuleManagement; + + public JpaSoftwareModuleMetadataBuilder(final SoftwareModuleManagement softwareModuleManagement) { + this.softwareModuleManagement = softwareModuleManagement; + } + + @Override + public SoftwareModuleMetadataUpdate update(final long softwareModuleId, final String key) { + return new GenericSoftwareModuleMetadataUpdate(softwareModuleId, key); + } + + @Override + public SoftwareModuleMetadataCreate create(final long softwareModuleId) { + return new JpaSoftwareModuleMetadataCreate(softwareModuleId, softwareModuleManagement); + } + +} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleMetadataCreate.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleMetadataCreate.java new file mode 100644 index 000000000..26917d994 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleMetadataCreate.java @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2015 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.builder; + +import org.eclipse.hawkbit.repository.SoftwareModuleManagement; +import org.eclipse.hawkbit.repository.builder.AbstractSoftwareModuleMetadataUpdateCreate; +import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataCreate; +import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; +import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleMetadata; +import org.eclipse.hawkbit.repository.model.SoftwareModule; + +/** + * Create/build implementation. + * + */ +public class JpaSoftwareModuleMetadataCreate + extends AbstractSoftwareModuleMetadataUpdateCreate + implements SoftwareModuleMetadataCreate { + + private final SoftwareModuleManagement softwareModuleManagement; + + JpaSoftwareModuleMetadataCreate(final long softwareModuleId, + final SoftwareModuleManagement softwareModuleManagement) { + this.softwareModuleManagement = softwareModuleManagement; + this.softwareModuleId = softwareModuleId; + } + + @Override + public JpaSoftwareModuleMetadata build() { + final SoftwareModule module = softwareModuleManagement.get(softwareModuleId) + .orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, softwareModuleId)); + + if (key == null) { + new JpaSoftwareModuleMetadata(key, module, value, isTargetVisible().orElse(false)); + } + + return new JpaSoftwareModuleMetadata(key, module, value, isTargetVisible().orElse(false)); + } + +} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaMetaData.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaMetaData.java similarity index 79% rename from hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaMetaData.java rename to hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaMetaData.java index c5b2bfd6b..7dafb7da6 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaMetaData.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaMetaData.java @@ -12,36 +12,36 @@ import javax.persistence.Basic; import javax.persistence.Column; import javax.persistence.Id; import javax.persistence.MappedSuperclass; +import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import org.eclipse.hawkbit.repository.model.MetaData; -import org.hibernate.validator.constraints.NotEmpty; /** * Meta data for entities. * */ @MappedSuperclass -public class JpaMetaData implements MetaData { +public abstract class AbstractJpaMetaData implements MetaData { private static final long serialVersionUID = 1L; @Id - @Column(name = "meta_key", nullable = false, length = 128) - @Size(min = 1, max = 128) - @NotEmpty + @Column(name = "meta_key", nullable = false, length = MetaData.KEY_MAX_SIZE, updatable = false) + @Size(min = 1, max = MetaData.KEY_MAX_SIZE) + @NotNull private String key; - @Column(name = "meta_value", length = 4000) - @Size(max = 4000) + @Column(name = "meta_value", length = MetaData.VALUE_MAX_SIZE) + @Size(max = MetaData.VALUE_MAX_SIZE) @Basic private String value; - public JpaMetaData(final String key, final String value) { + public AbstractJpaMetaData(final String key, final String value) { this.key = key; this.value = value; } - public JpaMetaData() { + public AbstractJpaMetaData() { // Default constructor needed for JPA entities } @@ -83,7 +83,7 @@ public class JpaMetaData implements MetaData { if (!(this.getClass().isInstance(obj))) { return false; } - final JpaMetaData other = (JpaMetaData) obj; + final AbstractJpaMetaData other = (AbstractJpaMetaData) obj; if (key == null) { if (other.key != null) { return false; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSetMetadata.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSetMetadata.java index 366236fcf..675557712 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSetMetadata.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSetMetadata.java @@ -28,7 +28,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSetMetadata; @IdClass(DsMetadataCompositeKey.class) @Entity @Table(name = "sp_ds_metadata") -public class JpaDistributionSetMetadata extends JpaMetaData implements DistributionSetMetadata { +public class JpaDistributionSetMetadata extends AbstractJpaMetaData implements DistributionSetMetadata { private static final long serialVersionUID = 1L; @Id @@ -40,6 +40,10 @@ public class JpaDistributionSetMetadata extends JpaMetaData implements Distribut // default public constructor for JPA } + public JpaDistributionSetMetadata(final String key, final String value) { + super(key, value); + } + public JpaDistributionSetMetadata(final String key, final DistributionSet distributionSet, final String value) { super(key, value); this.distributionSet = (JpaDistributionSet) distributionSet; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModuleMetadata.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModuleMetadata.java index 5f92aa466..4456f031f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModuleMetadata.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModuleMetadata.java @@ -8,6 +8,7 @@ */ package org.eclipse.hawkbit.repository.jpa.model; +import javax.persistence.Column; import javax.persistence.ConstraintMode; import javax.persistence.Entity; import javax.persistence.FetchType; @@ -28,7 +29,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; @IdClass(SwMetadataCompositeKey.class) @Entity @Table(name = "sp_sw_metadata") -public class JpaSoftwareModuleMetadata extends JpaMetaData implements SoftwareModuleMetadata { +public class JpaSoftwareModuleMetadata extends AbstractJpaMetaData implements SoftwareModuleMetadata { private static final long serialVersionUID = 1L; @Id @@ -36,6 +37,9 @@ public class JpaSoftwareModuleMetadata extends JpaMetaData implements SoftwareMo @JoinColumn(name = "sw_id", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_metadata_sw")) private JpaSoftwareModule softwareModule; + @Column(name = "target_visible") + private boolean targetVisible; + public JpaSoftwareModuleMetadata() { // default public constructor for JPA } @@ -45,6 +49,18 @@ public class JpaSoftwareModuleMetadata extends JpaMetaData implements SoftwareMo this.softwareModule = (JpaSoftwareModule) softwareModule; } + public JpaSoftwareModuleMetadata(final String key, final SoftwareModule softwareModule, final String value, + final boolean targetVisible) { + super(key, value); + this.softwareModule = (JpaSoftwareModule) softwareModule; + this.targetVisible = targetVisible; + } + + public JpaSoftwareModuleMetadata(final String key, final String value, final boolean targetVisible) { + super(key, value); + this.targetVisible = targetVisible; + } + public SwMetadataCompositeKey getId() { return new SwMetadataCompositeKey(softwareModule.getId(), getKey()); } @@ -58,6 +74,15 @@ public class JpaSoftwareModuleMetadata extends JpaMetaData implements SoftwareMo this.softwareModule = softwareModule; } + @Override + public boolean isTargetVisible() { + return targetVisible; + } + + public void setTargetVisible(final boolean targetVisible) { + this.targetVisible = targetVisible; + } + @Override public int hashCode() { final int prime = 31; @@ -83,4 +108,5 @@ public class JpaSoftwareModuleMetadata extends JpaMetaData implements SoftwareMo } return true; } + } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_11_3__add_module_md_targetvis__H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_11_3__add_module_md_targetvis__H2.sql new file mode 100644 index 000000000..2d5dfc8c4 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_11_3__add_module_md_targetvis__H2.sql @@ -0,0 +1 @@ +ALTER TABLE sp_sw_metadata ADD COLUMN target_visible boolean; \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_11_3__add_module_md_targetvis__MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_11_3__add_module_md_targetvis__MYSQL.sql new file mode 100644 index 000000000..4165f7ed1 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_11_3__add_module_md_targetvis__MYSQL.sql @@ -0,0 +1 @@ +ALTER TABLE sp_sw_metadata ADD COLUMN target_visible bit; \ No newline at end of file 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 fc2878e03..4bae7e135 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 @@ -17,6 +17,7 @@ import java.io.ByteArrayInputStream; import java.net.URISyntaxException; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import javax.validation.ConstraintViolationException; @@ -40,6 +41,7 @@ import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.SoftwareModule; +import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.test.matcher.Expect; @@ -432,6 +434,23 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest { .as("register target with empty controllerId should fail"); } + @Test + @Description("Verify that targetVisible metadata is returned from repository") + @ExpectEvents({ @Expect(type = DistributionSetCreatedEvent.class, count = 1), + @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), + @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6) }) + public void findTargetVisibleMetaDataBySoftwareModuleId() { + final DistributionSet set = testdataFactory.createDistributionSet(); + testdataFactory.addSoftwareModuleMetadata(set); + + final Map> result = controllerManagement + .findTargetVisibleMetaDataBySoftwareModuleId( + set.getModules().stream().map(SoftwareModule::getId).collect(Collectors.toList())); + + assertThat(result).hasSize(3); + result.entrySet().forEach(entry -> assertThat(entry.getValue()).hasSize(1)); + } + @Test @Description("Verify that controller registration does not result in a TargetPollEvent if feature is disabled") @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), 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 42d3192be..2880674bb 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 @@ -747,19 +747,17 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest { @Description("Queries and loads the metadata related to a given software module.") public void findAllDistributionSetMetadataByDsId() { // create a DS - DistributionSet ds1 = testdataFactory.createDistributionSet("testDs1"); - DistributionSet ds2 = testdataFactory.createDistributionSet("testDs2"); + final DistributionSet ds1 = testdataFactory.createDistributionSet("testDs1"); + final DistributionSet ds2 = testdataFactory.createDistributionSet("testDs2"); for (int index = 0; index < 10; index++) { - - ds1 = createDistributionSetMetadata(ds1.getId(), - new JpaDistributionSetMetadata("key" + index, ds1, "value" + index)).getDistributionSet(); + createDistributionSetMetadata(ds1.getId(), + new JpaDistributionSetMetadata("key" + index, ds1, "value" + index)); } for (int index = 0; index < 20; index++) { - - ds2 = createDistributionSetMetadata(ds2.getId(), - new JpaDistributionSetMetadata("key" + index, ds2, "value" + index)).getDistributionSet(); + createDistributionSetMetadata(ds2.getId(), + new JpaDistributionSetMetadata("key" + index, ds2, "value" + index)); } final Page metadataOfDs1 = distributionSetManagement 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 2ebae177b..d6b0f6703 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 @@ -9,17 +9,18 @@ package org.eclipse.hawkbit.repository.jpa; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.Arrays; -import java.util.Collections; import java.util.Iterator; import java.util.List; 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.jpa.model.JpaDistributionSet; @@ -84,10 +85,14 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { .create(entityFactory.softwareModule().create().name("xxx").type(NOT_EXIST_ID)), "SoftwareModuleType"); - verifyThrownExceptionBy(() -> softwareModuleManagement.createMetaData(NOT_EXIST_IDL, - entityFactory.generateMetadata("xxx", "xxx")), "SoftwareModule"); - verifyThrownExceptionBy(() -> softwareModuleManagement.createMetaData(NOT_EXIST_IDL, - Arrays.asList(entityFactory.generateMetadata("xxx", "xxx"))), "SoftwareModule"); + verifyThrownExceptionBy( + () -> softwareModuleManagement.createMetaData( + entityFactory.softwareModuleMetadata().create(NOT_EXIST_IDL).key("xxx").value("xxx")), + "SoftwareModule"); + verifyThrownExceptionBy( + () -> softwareModuleManagement.createMetaData(Arrays + .asList(entityFactory.softwareModuleMetadata().create(NOT_EXIST_IDL).key("xxx").value("xxx"))), + "SoftwareModule"); verifyThrownExceptionBy(() -> softwareModuleManagement.delete(NOT_EXIST_IDL), "SoftwareModule"); verifyThrownExceptionBy(() -> softwareModuleManagement.delete(Arrays.asList(NOT_EXIST_IDL)), "SoftwareModule"); @@ -95,10 +100,14 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { verifyThrownExceptionBy(() -> softwareModuleManagement.deleteMetaData(module.getId(), NOT_EXIST_ID), "SoftwareModuleMetadata"); - verifyThrownExceptionBy(() -> softwareModuleManagement.updateMetaData(NOT_EXIST_IDL, - entityFactory.generateMetadata("xxx", "xxx")), "SoftwareModule"); - verifyThrownExceptionBy(() -> softwareModuleManagement.updateMetaData(module.getId(), - entityFactory.generateMetadata(NOT_EXIST_ID, "xxx")), "SoftwareModuleMetadata"); + verifyThrownExceptionBy( + () -> softwareModuleManagement.updateMetaData( + entityFactory.softwareModuleMetadata().update(NOT_EXIST_IDL, "xxx").value("xxx")), + "SoftwareModule"); + verifyThrownExceptionBy( + () -> softwareModuleManagement.updateMetaData( + entityFactory.softwareModuleMetadata().update(module.getId(), NOT_EXIST_ID).value("xxx")), + "SoftwareModuleMetadata"); verifyThrownExceptionBy(() -> softwareModuleManagement.findByAssignedTo(PAGE, NOT_EXIST_IDL), "DistributionSet"); @@ -624,12 +633,14 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { assertThat(ah.getOptLockRevision()).isEqualTo(1); - final SoftwareModuleMetadata swMetadata1 = new JpaSoftwareModuleMetadata(knownKey1, ah, knownValue1); + final SoftwareModuleMetadataCreate swMetadata1 = entityFactory.softwareModuleMetadata().create(ah.getId()) + .key(knownKey1).value(knownValue1); - final SoftwareModuleMetadata swMetadata2 = new JpaSoftwareModuleMetadata(knownKey2, ah, knownValue2); + final SoftwareModuleMetadataCreate swMetadata2 = entityFactory.softwareModuleMetadata().create(ah.getId()) + .key(knownKey2).value(knownValue2); - final List softwareModuleMetadata = softwareModuleManagement.createMetaData(ah.getId(), - Arrays.asList(swMetadata1, swMetadata2)); + final List softwareModuleMetadata = softwareModuleManagement + .createMetaData(Arrays.asList(swMetadata1, swMetadata2)); final SoftwareModule changedLockRevisionModule = softwareModuleManagement.get(ah.getId()).get(); assertThat(changedLockRevisionModule.getOptLockRevision()).isEqualTo(2); @@ -638,7 +649,7 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { assertThat(softwareModuleMetadata.get(0)).isNotNull(); assertThat(softwareModuleMetadata.get(0).getValue()).isEqualTo(knownValue1); assertThat(((JpaSoftwareModuleMetadata) softwareModuleMetadata.get(0)).getId().getKey()).isEqualTo(knownKey1); - assertThat(softwareModuleMetadata.get(0).getSoftwareModule().getId()).isEqualTo(ah.getId()); + assertThat(softwareModuleMetadata.get(0).getEntityId()).isEqualTo(ah.getId()); } @Test @@ -651,14 +662,23 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { final SoftwareModule ah = testdataFactory.createSoftwareModuleApp(); - softwareModuleManagement.createMetaData(ah.getId(), entityFactory.generateMetadata(knownKey1, knownValue1)); + softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata().create(ah.getId()).key(knownKey1) + .value(knownValue1).targetVisible(true)); - try { - softwareModuleManagement.createMetaData(ah.getId(), entityFactory.generateMetadata(knownKey1, knownValue2)); - fail("should not have worked as module metadata already exists"); - } catch (final EntityAlreadyExistsException e) { + assertThatExceptionOfType(EntityAlreadyExistsException.class) + .isThrownBy(() -> softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata() + .create(ah.getId()).key(knownKey1).value(knownValue1).targetVisible(true))) + .withMessageContaining("Metadata").withMessageContaining(knownKey1); - } + final String knownKey2 = "myKnownKey2"; + + softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata().create(ah.getId()).key(knownKey2) + .value(knownValue1).targetVisible(false)); + + assertThatExceptionOfType(EntityAlreadyExistsException.class) + .isThrownBy(() -> softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata() + .create(ah.getId()).key(knownKey2).value(knownValue1).targetVisible(true))) + .withMessageContaining("Metadata").withMessageContaining(knownKey2); } @Test @@ -675,9 +695,11 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { assertThat(ah.getOptLockRevision()).isEqualTo(1); // create an software module meta data entry - final List softwareModuleMetadata = softwareModuleManagement.createMetaData(ah.getId(), - Collections.singleton(entityFactory.generateMetadata(knownKey, knownValue))); - assertThat(softwareModuleMetadata).hasSize(1); + final SoftwareModuleMetadata softwareModuleMetadata = softwareModuleManagement.createMetaData( + entityFactory.softwareModuleMetadata().create(ah.getId()).key(knownKey).value(knownValue)); + assertThat(softwareModuleMetadata.isTargetVisible()).isFalse(); + assertThat(softwareModuleMetadata.getValue()).isEqualTo(knownValue); + // base software module should have now the opt lock revision one // because we are modifying the // base software module @@ -686,8 +708,8 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { // update the software module metadata Thread.sleep(100); - final SoftwareModuleMetadata updated = softwareModuleManagement.updateMetaData(ah.getId(), - entityFactory.generateMetadata(knownKey, knownUpdateValue)); + final SoftwareModuleMetadata updated = softwareModuleManagement.updateMetaData(entityFactory + .softwareModuleMetadata().update(ah.getId(), knownKey).value(knownUpdateValue).targetVisible(true)); // we are updating the sw meta data so also modiying the base software // module so opt lock // revision must be two @@ -697,8 +719,9 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { // verify updated meta data contains the updated value assertThat(updated).isNotNull(); assertThat(updated.getValue()).isEqualTo(knownUpdateValue); + assertThat(updated.isTargetVisible()).isTrue(); assertThat(((JpaSoftwareModuleMetadata) updated).getId().getKey()).isEqualTo(knownKey); - assertThat(updated.getSoftwareModule().getId()).isEqualTo(ah.getId()); + assertThat(updated.getEntityId()).isEqualTo(ah.getId()); } @Test @@ -709,8 +732,10 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { SoftwareModule ah = testdataFactory.createSoftwareModuleApp(); - ah = softwareModuleManagement.createMetaData(ah.getId(), entityFactory.generateMetadata(knownKey1, knownValue1)) - .getSoftwareModule(); + softwareModuleManagement.createMetaData( + entityFactory.softwareModuleMetadata().create(ah.getId()).key(knownKey1).value(knownValue1)); + + ah = softwareModuleManagement.get(ah.getId()).get(); assertThat(softwareModuleManagement.findMetaDataBySoftwareModuleId(new PageRequest(0, 10), ah.getId()) .getContent()).as("Contains the created metadata element") @@ -727,10 +752,10 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { final String knownKey1 = "myKnownKey1"; final String knownValue1 = "myKnownValue1"; - SoftwareModule ah = testdataFactory.createSoftwareModuleApp(); + final SoftwareModule ah = testdataFactory.createSoftwareModuleApp(); - ah = softwareModuleManagement.createMetaData(ah.getId(), entityFactory.generateMetadata(knownKey1, knownValue1)) - .getSoftwareModule(); + softwareModuleManagement.createMetaData( + entityFactory.softwareModuleMetadata().create(ah.getId()).key(knownKey1).value(knownValue1)); assertThat(softwareModuleManagement.getMetaDataBySoftwareModuleId(ah.getId(), "doesnotexist")).isNotPresent(); } @@ -739,26 +764,24 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { @Description("Queries and loads the metadata related to a given software module.") public void findAllSoftwareModuleMetadataBySwId() { - SoftwareModule sw1 = testdataFactory.createSoftwareModuleApp(); + final SoftwareModule sw1 = testdataFactory.createSoftwareModuleApp(); - SoftwareModule sw2 = testdataFactory.createSoftwareModuleOs(); + final SoftwareModule sw2 = testdataFactory.createSoftwareModuleOs(); for (int index = 0; index < 10; index++) { - sw1 = softwareModuleManagement - .createMetaData(sw1.getId(), entityFactory.generateMetadata("key" + index, "value" + index)) - .getSoftwareModule(); + softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata().create(sw1.getId()) + .key("key" + index).value("value" + index).targetVisible(true)); } for (int index = 0; index < 20; index++) { - sw2 = softwareModuleManagement - .createMetaData(sw2.getId(), new JpaSoftwareModuleMetadata("key" + index, sw2, "value" + index)) - .getSoftwareModule(); + softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata().create(sw2.getId()) + .key("key" + index).value("value" + index).targetVisible(false)); } - final Page metadataOfSw1 = softwareModuleManagement + Page metadataOfSw1 = softwareModuleManagement .findMetaDataBySoftwareModuleId(new PageRequest(0, 100), sw1.getId()); - final Page metadataOfSw2 = softwareModuleManagement + Page metadataOfSw2 = softwareModuleManagement .findMetaDataBySoftwareModuleId(new PageRequest(0, 100), sw2.getId()); assertThat(metadataOfSw1.getNumberOfElements()).isEqualTo(10); @@ -766,5 +789,17 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { assertThat(metadataOfSw2.getNumberOfElements()).isEqualTo(20); assertThat(metadataOfSw2.getTotalElements()).isEqualTo(20); + + metadataOfSw1 = softwareModuleManagement.findMetaDataBySoftwareModuleIdAndTargetVisible(new PageRequest(0, 100), + sw1.getId()); + + metadataOfSw2 = softwareModuleManagement.findMetaDataBySoftwareModuleIdAndTargetVisible(new PageRequest(0, 100), + sw2.getId()); + + assertThat(metadataOfSw1.getNumberOfElements()).isEqualTo(10); + assertThat(metadataOfSw1.getTotalElements()).isEqualTo(10); + + assertThat(metadataOfSw2.getNumberOfElements()).isEqualTo(0); + assertThat(metadataOfSw2.getTotalElements()).isEqualTo(0); } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleFieldTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleFieldTest.java index 0460ece39..b2afc9882 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleFieldTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleFieldTest.java @@ -11,9 +11,9 @@ package org.eclipse.hawkbit.repository.jpa.rsql; import static org.assertj.core.api.Assertions.assertThat; import org.eclipse.hawkbit.repository.SoftwareModuleFields; +import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataCreate; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; -import org.eclipse.hawkbit.repository.model.MetaData; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.test.util.TestdataFactory; import org.junit.Before; @@ -31,21 +31,23 @@ public class RSQLSoftwareModuleFieldTest extends AbstractJpaIntegrationTest { @Before public void setupBeforeTest() { - final SoftwareModule ah = softwareModuleManagement.create(entityFactory.softwareModule().create() - .type(appType).name("agent-hub").version("1.0.1").description("agent-hub")); - softwareModuleManagement.create(entityFactory.softwareModule().create().type(runtimeType) - .name("oracle-jre").version("1.7.2").description("aa")); + final SoftwareModule ah = softwareModuleManagement.create(entityFactory.softwareModule().create().type(appType) + .name("agent-hub").version("1.0.1").description("agent-hub")); + softwareModuleManagement.create(entityFactory.softwareModule().create().type(runtimeType).name("oracle-jre") + .version("1.7.2").description("aa")); softwareModuleManagement.create( entityFactory.softwareModule().create().type(osType).name("poky").version("3.0.2").description("aa")); - final JpaSoftwareModule ah2 = (JpaSoftwareModule) softwareModuleManagement.create(entityFactory - .softwareModule().create().type(appType).name("agent-hub2").version("1.0.1").description("agent-hub2")); + final JpaSoftwareModule ah2 = (JpaSoftwareModule) softwareModuleManagement.create(entityFactory.softwareModule() + .create().type(appType).name("agent-hub2").version("1.0.1").description("agent-hub2")); - final MetaData softwareModuleMetadata = entityFactory.generateMetadata("metaKey", "metaValue"); - softwareModuleManagement.createMetaData(ah.getId(), softwareModuleMetadata); + final SoftwareModuleMetadataCreate softwareModuleMetadata = entityFactory.softwareModuleMetadata() + .create(ah.getId()).key("metaKey").value("metaValue"); + softwareModuleManagement.createMetaData(softwareModuleMetadata); - final MetaData softwareModuleMetadata2 = entityFactory.generateMetadata("metaKey", "value"); - softwareModuleManagement.createMetaData(ah2.getId(), softwareModuleMetadata2); + final SoftwareModuleMetadataCreate softwareModuleMetadata2 = entityFactory.softwareModuleMetadata() + .create(ah2.getId()).key("metaKey").value("value"); + softwareModuleManagement.createMetaData(softwareModuleMetadata2); } @Test @@ -105,8 +107,7 @@ public class RSQLSoftwareModuleFieldTest extends AbstractJpaIntegrationTest { } private void assertRSQLQuery(final String rsqlParam, final long excpectedEntity) { - final Page find = softwareModuleManagement.findByRsql(new PageRequest(0, 100), - rsqlParam); + final Page find = softwareModuleManagement.findByRsql(new PageRequest(0, 100), rsqlParam); final long countAll = find.getTotalElements(); assertThat(find).isNotNull(); assertThat(countAll).isEqualTo(excpectedEntity); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleMetadataFieldsTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleMetadataFieldsTest.java index 73829d29e..42c467224 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleMetadataFieldsTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLSoftwareModuleMetadataFieldsTest.java @@ -10,12 +10,11 @@ package org.eclipse.hawkbit.repository.jpa.rsql; import static org.assertj.core.api.Assertions.assertThat; -import java.util.ArrayList; import java.util.List; import org.eclipse.hawkbit.repository.SoftwareModuleMetadataFields; +import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataCreate; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; -import org.eclipse.hawkbit.repository.model.MetaData; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; import org.eclipse.hawkbit.repository.test.util.TestdataFactory; @@ -24,6 +23,8 @@ import org.junit.Test; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; +import com.google.common.collect.Lists; + import ru.yandex.qatools.allure.annotations.Description; import ru.yandex.qatools.allure.annotations.Features; import ru.yandex.qatools.allure.annotations.Stories; @@ -40,12 +41,16 @@ public class RSQLSoftwareModuleMetadataFieldsTest extends AbstractJpaIntegration softwareModuleId = softwareModule.getId(); - final List metadata = new ArrayList<>(5); + final List metadata = Lists.newArrayListWithExpectedSize(5); for (int i = 0; i < 5; i++) { - metadata.add(entityFactory.generateMetadata("" + i, "" + i)); + metadata.add( + entityFactory.softwareModuleMetadata().create(softwareModule.getId()).key("" + i).value("" + i)); } - softwareModuleManagement.createMetaData(softwareModule.getId(), metadata); + metadata.add(entityFactory.softwareModuleMetadata().create(softwareModule.getId()).key("targetVisible") + .value("targetVisible").targetVisible(true)); + + softwareModuleManagement.createMetaData(metadata); } @@ -53,18 +58,27 @@ public class RSQLSoftwareModuleMetadataFieldsTest extends AbstractJpaIntegration @Description("Test filter software module metadata by key") public void testFilterByParameterKey() { assertRSQLQuery(SoftwareModuleMetadataFields.KEY.name() + "==1", 1); - assertRSQLQuery(SoftwareModuleMetadataFields.KEY.name() + "!=1", 4); + assertRSQLQuery(SoftwareModuleMetadataFields.KEY.name() + "!=1", 5); assertRSQLQuery(SoftwareModuleMetadataFields.KEY.name() + "=in=(1,2)", 2); - assertRSQLQuery(SoftwareModuleMetadataFields.KEY.name() + "=out=(1,2)", 3); + assertRSQLQuery(SoftwareModuleMetadataFields.KEY.name() + "=out=(1,2)", 4); } @Test - @Description("Test fitler software module metadata status by value") + @Description("Test fitler software module metadata by value") public void testFilterByParameterValue() { assertRSQLQuery(SoftwareModuleMetadataFields.VALUE.name() + "==1", 1); - assertRSQLQuery(SoftwareModuleMetadataFields.VALUE.name() + "!=1", 4); + assertRSQLQuery(SoftwareModuleMetadataFields.VALUE.name() + "!=1", 5); assertRSQLQuery(SoftwareModuleMetadataFields.VALUE.name() + "=in=(1,2)", 2); - assertRSQLQuery(SoftwareModuleMetadataFields.VALUE.name() + "=out=(1,2)", 3); + assertRSQLQuery(SoftwareModuleMetadataFields.VALUE.name() + "=out=(1,2)", 4); + } + + @Test + @Description("Test fitler software module metadata by target visible") + public void testFilterByParameterTargetVisible() { + assertRSQLQuery(SoftwareModuleMetadataFields.TARGETVISIBLE.name() + "==true", 1); + assertRSQLQuery(SoftwareModuleMetadataFields.TARGETVISIBLE.name() + "==false", 5); + assertRSQLQuery(SoftwareModuleMetadataFields.TARGETVISIBLE.name() + "!=false", 1); + assertRSQLQuery(SoftwareModuleMetadataFields.TARGETVISIBLE.name() + "!=true", 5); } private void assertRSQLQuery(final String rsqlParam, final long expectedEntities) { diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java index 375861a1f..a3995acf8 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java @@ -54,6 +54,7 @@ import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessCond import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder; import org.eclipse.hawkbit.repository.model.RolloutGroupConditions; import org.eclipse.hawkbit.repository.model.SoftwareModule; +import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetTag; @@ -71,6 +72,11 @@ import net._01001111.text.LoremIpsum; public class TestdataFactory { private static final LoremIpsum LOREM = new LoremIpsum(); + public static final String VISIBLE_SM_MD_KEY = "visibleMetdataKey"; + public static final String VISIBLE_SM_MD_VALUE = "visibleMetdataValue"; + public static final String INVISIBLE_SM_MD_KEY = "invisibleMetdataKey"; + public static final String INVISIBLE_SM_MD_VALUE = "invisibleMetdataValue"; + /** * default {@link Target#getControllerId()}. */ @@ -266,16 +272,16 @@ public class TestdataFactory { public DistributionSet createDistributionSet(final String prefix, final String version, final boolean isRequiredMigrationStep) { - final SoftwareModule appMod = softwareModuleManagement.create(entityFactory.softwareModule() - .create().type(findOrCreateSoftwareModuleType(SM_TYPE_APP, Integer.MAX_VALUE)) - .name(prefix + SM_TYPE_APP).version(version + "." + new SecureRandom().nextInt(100)) - .description(LOREM.words(20)).vendor(prefix + " vendor Limited, California")); - final SoftwareModule runtimeMod = softwareModuleManagement.create( - entityFactory.softwareModule().create().type(findOrCreateSoftwareModuleType(SM_TYPE_RT)) + final SoftwareModule appMod = softwareModuleManagement.create(entityFactory.softwareModule().create() + .type(findOrCreateSoftwareModuleType(SM_TYPE_APP, Integer.MAX_VALUE)).name(prefix + SM_TYPE_APP) + .version(version + "." + new SecureRandom().nextInt(100)).description(LOREM.words(20)) + .vendor(prefix + " vendor Limited, California")); + final SoftwareModule runtimeMod = softwareModuleManagement + .create(entityFactory.softwareModule().create().type(findOrCreateSoftwareModuleType(SM_TYPE_RT)) .name(prefix + "app runtime").version(version + "." + new SecureRandom().nextInt(100)) .description(LOREM.words(20)).vendor(prefix + " vendor GmbH, Stuttgart, Germany")); - final SoftwareModule osMod = softwareModuleManagement.create( - entityFactory.softwareModule().create().type(findOrCreateSoftwareModuleType(SM_TYPE_OS)) + final SoftwareModule osMod = softwareModuleManagement + .create(entityFactory.softwareModule().create().type(findOrCreateSoftwareModuleType(SM_TYPE_OS)) .name(prefix + " Firmware").version(version + "." + new SecureRandom().nextInt(100)) .description(LOREM.words(20)).vendor(prefix + " vendor Limited Inc, California")); @@ -286,6 +292,30 @@ public class TestdataFactory { .requiredMigrationStep(isRequiredMigrationStep)); } + /** + * Adds {@link SoftwareModuleMetadata} to every module of given + * {@link DistributionSet}. + * + * {@link #VISIBLE_SM_MD_VALUE}, {@link #VISIBLE_SM_MD_KEY} with + * {@link SoftwareModuleMetadata#isTargetVisible()} and + * {@link #INVISIBLE_SM_MD_KEY}, {@link #INVISIBLE_SM_MD_VALUE} without + * {@link SoftwareModuleMetadata#isTargetVisible()} + * + * @param set + * to add metadata to + */ + public void addSoftwareModuleMetadata(final DistributionSet set) { + set.getModules().forEach(this::addTestModuleMetadata); + } + + private void addTestModuleMetadata(final SoftwareModule module) { + softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata().create(module.getId()) + .key(VISIBLE_SM_MD_KEY).value(VISIBLE_SM_MD_VALUE).targetVisible(true)); + softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata().create(module.getId()) + .key(INVISIBLE_SM_MD_KEY).value(INVISIBLE_SM_MD_VALUE).targetVisible(false)); + + } + /** * Creates {@link DistributionSet} in repository. * @@ -370,8 +400,8 @@ public class TestdataFactory { final List sets = Lists.newArrayListWithExpectedSize(number); for (int i = 0; i < number; i++) { - sets.add(distributionSetManagement.create( - entityFactory.distributionSet().create().name("DS" + i).version(DEFAULT_VERSION + "." + i) + sets.add(distributionSetManagement + .create(entityFactory.distributionSet().create().name("DS" + i).version(DEFAULT_VERSION + "." + i) .description(LOREM.words(10)).type(findOrCreateDefaultTestDsType()))); } @@ -417,8 +447,8 @@ public class TestdataFactory { */ public DistributionSet createDistributionSetWithNoSoftwareModules(final String name, final String version) { - return distributionSetManagement.create(entityFactory.distributionSet().create().name(name) - .version(version).description(DEFAULT_DESCRIPTION).type(findOrCreateDefaultTestDsType())); + return distributionSetManagement.create(entityFactory.distributionSet().create().name(name).version(version) + .description(DEFAULT_DESCRIPTION).type(findOrCreateDefaultTestDsType())); } /** @@ -608,9 +638,9 @@ public class TestdataFactory { * @return persisted {@link DistributionSetType} */ public DistributionSetType findOrCreateDistributionSetType(final String dsTypeKey, final String dsTypeName) { - return distributionSetTypeManagement.getByKey(dsTypeKey).orElseGet( - () -> distributionSetTypeManagement.create(entityFactory.distributionSetType() - .create().key(dsTypeKey).name(dsTypeName).description(LOREM.words(10)).colour("black"))); + return distributionSetTypeManagement.getByKey(dsTypeKey) + .orElseGet(() -> distributionSetTypeManagement.create(entityFactory.distributionSetType().create() + .key(dsTypeKey).name(dsTypeName).description(LOREM.words(10)).colour("black"))); } /** @@ -631,9 +661,8 @@ public class TestdataFactory { public DistributionSetType findOrCreateDistributionSetType(final String dsTypeKey, final String dsTypeName, final Collection mandatory, final Collection optional) { return distributionSetTypeManagement.getByKey(dsTypeKey) - .orElseGet(() -> distributionSetTypeManagement.create(entityFactory - .distributionSetType().create().key(dsTypeKey).name(dsTypeName).description(LOREM.words(10)) - .colour("black") + .orElseGet(() -> distributionSetTypeManagement.create(entityFactory.distributionSetType().create() + .key(dsTypeKey).name(dsTypeName).description(LOREM.words(10)).colour("black") .optional(optional.stream().map(SoftwareModuleType::getId).collect(Collectors.toList())) .mandatory(mandatory.stream().map(SoftwareModuleType::getId).collect(Collectors.toList())))); } @@ -664,8 +693,8 @@ public class TestdataFactory { * @return persisted {@link SoftwareModuleType} */ public SoftwareModuleType findOrCreateSoftwareModuleType(final String key, final int maxAssignments) { - return softwareModuleTypeManagement.getByKey(key).orElseGet( - () -> softwareModuleTypeManagement.create(entityFactory.softwareModuleType().create() + return softwareModuleTypeManagement.getByKey(key) + .orElseGet(() -> softwareModuleTypeManagement.create(entityFactory.softwareModuleType().create() .key(key).name(key).description(LOREM.words(10)).maxAssignments(maxAssignments))); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/SpPermissionChecker.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/SpPermissionChecker.java index b1f629b98..b4533447e 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/SpPermissionChecker.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/SpPermissionChecker.java @@ -12,7 +12,6 @@ import java.io.Serializable; import org.eclipse.hawkbit.im.authentication.PermissionService; import org.eclipse.hawkbit.im.authentication.SpPermission; -import org.springframework.beans.factory.annotation.Autowired; /** * Bean which contains all SP permissions. @@ -23,7 +22,6 @@ public class SpPermissionChecker implements Serializable { protected transient PermissionService permissionService; - @Autowired protected SpPermissionChecker(final PermissionService permissionService) { this.permissionService = permissionService; } @@ -52,7 +50,7 @@ public class SpPermissionChecker implements Serializable { * @return TARGET_REPOSITORY_READ boolean value */ public boolean hasTargetAndRepositoryReadPermission() { - return hasTargetReadPermission() && hasReadDistributionPermission(); + return hasTargetReadPermission() && hasReadRepositoryPermission(); } /** @@ -92,39 +90,39 @@ public class SpPermissionChecker implements Serializable { } /** - * Gets the SP READ Distribution Permission. + * Gets the SP READ Repository Permission. * * @return READ_REPOSITORY boolean value */ - public boolean hasReadDistributionPermission() { + public boolean hasReadRepositoryPermission() { return permissionService.hasPermission(SpPermission.READ_REPOSITORY); } /** - * Gets the SP create Distribution Permission. + * Gets the SP create Repository Permission. * * @return CREATE_REPOSITORY boolean value */ - public boolean hasCreateDistributionPermission() { - return hasReadDistributionPermission() && permissionService.hasPermission(SpPermission.CREATE_REPOSITORY); + public boolean hasCreateRepositoryPermission() { + return hasReadRepositoryPermission() && permissionService.hasPermission(SpPermission.CREATE_REPOSITORY); } /** - * Gets the SP update Distribution Permission. + * Gets the SP update Repository Permission. * * @return UPDATE_REPOSITORY boolean value */ - public boolean hasUpdateDistributionPermission() { - return hasReadDistributionPermission() && permissionService.hasPermission(SpPermission.UPDATE_REPOSITORY); + public boolean hasUpdateRepositoryPermission() { + return hasReadRepositoryPermission() && permissionService.hasPermission(SpPermission.UPDATE_REPOSITORY); } /** - * Gets the SP delete Distribution Permission. + * Gets the SP delete Repository Permission. * * @return DELETE_REPOSITORY boolean value */ - public boolean hasDeleteDistributionPermission() { - return hasReadDistributionPermission() && permissionService.hasPermission(SpPermission.DELETE_REPOSITORY); + public boolean hasDeleteRepositoryPermission() { + return hasReadRepositoryPermission() && permissionService.hasPermission(SpPermission.DELETE_REPOSITORY); } /** @@ -133,7 +131,7 @@ public class SpPermissionChecker implements Serializable { * @return permission for rollout update */ public boolean hasRolloutUpdatePermission() { - return hasUpdateTargetPermission() && hasReadDistributionPermission() + return hasUpdateTargetPermission() && hasReadRepositoryPermission() && permissionService.hasPermission(SpPermission.ROLLOUT_MANAGEMENT); } @@ -143,7 +141,7 @@ public class SpPermissionChecker implements Serializable { * @return permission for rollout create */ public boolean hasRolloutCreatePermission() { - return hasUpdateTargetPermission() && hasReadDistributionPermission() + return hasUpdateTargetPermission() && hasReadRepositoryPermission() && permissionService.hasPermission(SpPermission.ROLLOUT_MANAGEMENT); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/UploadArtifactView.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/UploadArtifactView.java index 316127733..6e55bf8cb 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/UploadArtifactView.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/UploadArtifactView.java @@ -157,7 +157,7 @@ public class UploadArtifactView extends VerticalLayout implements View, BrowserW } private void buildLayout() { - if (permChecker.hasReadDistributionPermission() || permChecker.hasCreateDistributionPermission()) { + if (permChecker.hasReadRepositoryPermission() || permChecker.hasCreateRepositoryPermission()) { setSizeFull(); createMainLayout(); addComponents(mainLayout); @@ -170,7 +170,7 @@ public class UploadArtifactView extends VerticalLayout implements View, BrowserW detailAndUploadLayout.addComponent(artifactDetailsLayout); detailAndUploadLayout.setComponentAlignment(artifactDetailsLayout, Alignment.MIDDLE_CENTER); - if (permChecker.hasCreateDistributionPermission()) { + if (permChecker.hasCreateRepositoryPermission()) { dadw = uploadLayout.getDropAreaWrapper(); detailAndUploadLayout.addComponent(dadw); detailAndUploadLayout.setComponentAlignment(dadw, Alignment.MIDDLE_CENTER); @@ -204,7 +204,7 @@ public class UploadArtifactView extends VerticalLayout implements View, BrowserW private void createUploadButtonLayout() { uplaodButtonsLayout = new HorizontalLayout(); - if (permChecker.hasCreateDistributionPermission()) { + if (permChecker.hasCreateRepositoryPermission()) { uplaodButtonsLayout = uploadLayout.getFileUploadLayout(); } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/footer/SMDeleteActionsLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/footer/SMDeleteActionsLayout.java index 31a994946..4d95c2e16 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/footer/SMDeleteActionsLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/footer/SMDeleteActionsLayout.java @@ -92,7 +92,7 @@ public class SMDeleteActionsLayout extends AbstractDeleteActionsLayout { @Override protected boolean hasDeletePermission() { - return permChecker.hasDeleteDistributionPermission(); + return permChecker.hasDeleteRepositoryPermission(); } @Override diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleDetails.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleDetails.java index 98f0f7155..ded36197c 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleDetails.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleDetails.java @@ -8,7 +8,6 @@ */ package org.eclipse.hawkbit.ui.artifacts.smtable; -import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.ui.SpPermissionChecker; @@ -31,8 +30,8 @@ public class SoftwareModuleDetails extends AbstractSoftwareModuleDetails { final SpPermissionChecker permissionChecker, final SoftwareModuleAddUpdateWindow softwareModuleAddUpdateWindow, final ArtifactUploadState artifactUploadState, final SoftwareModuleManagement softwareManagement, - final SwMetadataPopupLayout swMetadataPopupLayout, final EntityFactory entityFactory) { - super(i18n, eventBus, permissionChecker, null, softwareManagement, swMetadataPopupLayout, entityFactory, + final SwMetadataPopupLayout swMetadataPopupLayout) { + super(i18n, eventBus, permissionChecker, null, softwareManagement, swMetadataPopupLayout, softwareModuleAddUpdateWindow); this.artifactUploadState = artifactUploadState; restoreState(); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTableLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTableLayout.java index 1e859fa32..0a1faf757 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTableLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTableLayout.java @@ -49,7 +49,7 @@ public class SoftwareModuleTableLayout extends AbstractTableLayout getMetadataList(); - protected abstract void deleteMetadata(E entity, String key, String value); + protected abstract void deleteMetadata(E entity, String key); protected abstract boolean hasCreatePermission(); protected abstract boolean hasUpdatePermission(); - private void createComponents() { + protected void createComponents() { keyTextField = createKeyTextField(); valueTextArea = createValueTextField(); metaDataGrid = createMetadataGrid(); @@ -211,13 +211,7 @@ public abstract class AbstractMetadataPopupLayout { if (ok) { - handleOkDeleteMetadata(event, key, value); + handleOkDeleteMetadata(event, key); } }); UI.getCurrent().addWindow(confirmDialog.getWindow()); confirmDialog.getWindow().bringToFront(); } - private void handleOkDeleteMetadata(final RendererClickEvent event, final String key, final String value) { - deleteMetadata(getSelectedEntity(), key, value); + private void handleOkDeleteMetadata(final RendererClickEvent event, final String key) { + deleteMetadata(getSelectedEntity(), key); uiNotification.displaySuccess(i18n.getMessage("message.metadata.deleted.successfully", key)); final Object selectedRow = metaDataGrid.getSelectedRow(); metaDataGrid.getContainerDataSource().removeItem(event.getItemId()); @@ -306,17 +310,15 @@ public abstract class AbstractMetadataPopupLayout metadataList = getMetadataList(); for (final M metaData : metadataList) { - addItemToGrid(metaData.getKey(), metaData.getValue()); + addItemToGrid(metaData); } } - private void addItemToGrid(final String key, final String value) { + protected Item addItemToGrid(final M metaData) { final IndexedContainer metadataContainer = (IndexedContainer) metaDataGrid.getContainerDataSource(); - final Item item = metadataContainer.addItem(key); - item.getItemProperty(VALUE).setValue(value); - item.getItemProperty(KEY).setValue(key); + final Item item = metadataContainer.addItem(metaData.getKey()); + item.getItemProperty(VALUE).setValue(metaData.getValue()); + item.getItemProperty(KEY).setValue(metaData.getKey()); + return item; } - private void updateItemInGrid(final String key) { + protected Item updateItemInGrid(final String key) { final IndexedContainer metadataContainer = (IndexedContainer) metaDataGrid.getContainerDataSource(); final Item item = metadataContainer.getItem(key); item.getItemProperty(VALUE).setValue(valueTextArea.getValue()); + return item; } private void onAdd() { metaDataGrid.deselect(metaDataGrid.getSelectedRow()); - valueTextArea.clear(); - keyTextField.clear(); - keyTextField.setEnabled(true); - valueTextArea.setEnabled(true); + clearFields(); + enableEditing(); addIcon.setEnabled(true); } - private void onSave() { + protected void clearFields() { + valueTextArea.clear(); + keyTextField.clear(); + } + + protected void onSave() { final String key = keyTextField.getValue(); final String value = valueTextArea.getValue(); if (mandatoryCheck()) { @@ -391,7 +401,7 @@ public abstract class AbstractMetadataPopupLayout itemsSelected = event.getSelected(); if (!itemsSelected.isEmpty()) { popualateKeyValue(itemsSelected.iterator().next()); addIcon.setEnabled(true); } else { - keyTextField.clear(); - valueTextArea.clear(); + clearFields(); if (hasCreatePermission()) { - keyTextField.setEnabled(true); - valueTextArea.setEnabled(true); + enableEditing(); addIcon.setEnabled(false); } else { keyTextField.setEnabled(false); @@ -476,6 +484,11 @@ public abstract class AbstractMetadataPopupLayout ds = distributionSetManagement - .get(getSelectedBaseEntityId()); + final Optional ds = distributionSetManagement.get(getSelectedBaseEntityId()); if (!ds.isPresent()) { uiNotification.displayWarning(getI18n().getMessage("distributionset.not.exists")); return; diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/AbstractMetadataDetailsLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/AbstractMetadataDetailsLayout.java new file mode 100644 index 000000000..a9949e0c7 --- /dev/null +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/AbstractMetadataDetailsLayout.java @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2015 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.ui.common.detailslayout; + +import org.eclipse.hawkbit.repository.model.MetaData; +import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; +import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder; +import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; + +import com.vaadin.data.Item; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.ui.Button; +import com.vaadin.ui.Table; +import com.vaadin.ui.themes.ValoTheme; + +/** + * Abstract metadata tab for entities. + * + */ +public abstract class AbstractMetadataDetailsLayout extends Table { + + protected static final String METADATA_KEY = "Key"; + + protected static final int MAX_METADATA_QUERY = 500; + + private final VaadinMessageSource i18n; + + protected AbstractMetadataDetailsLayout(final VaadinMessageSource i18n) { + this.i18n = i18n; + createMetadataTable(); + + addCustomGeneratedColumns(); + } + + private VaadinMessageSource getI18n() { + return i18n; + } + + private void createMetadataTable() { + addStyleName(ValoTheme.TABLE_NO_HORIZONTAL_LINES); + addStyleName(ValoTheme.TABLE_NO_STRIPES); + setSelectable(false); + setImmediate(true); + setContainerDataSource(getContainer()); + setColumnHeaderMode(ColumnHeaderMode.EXPLICIT); + addTableHeader(); + setSizeFull(); + // same as height of other tabs in details tabsheet + setHeight(116, Unit.PIXELS); + } + + private IndexedContainer getContainer() { + final IndexedContainer container = new IndexedContainer(); + container.addContainerProperty(METADATA_KEY, String.class, ""); + setColumnExpandRatio(METADATA_KEY, 0.7F); + setColumnAlignment(METADATA_KEY, Align.LEFT); + + return container; + } + + private void addTableHeader() { + setColumnHeader(METADATA_KEY, getI18n().getMessage("header.key")); + } + + protected void setMetadataProperties(final MetaData dsMetadata) { + final Item item = getContainerDataSource().addItem(dsMetadata.getKey()); + item.getItemProperty(METADATA_KEY).setValue(dsMetadata.getKey()); + + } + + private void addCustomGeneratedColumns() { + addGeneratedColumn(METADATA_KEY, (source, itemId, columnId) -> customMetadataDetailButton((String) itemId)); + } + + private Button customMetadataDetailButton(final String metadataKey) { + final Button viewIcon = SPUIComponentProvider.getButton(getDetailLinkId(metadataKey), metadataKey, + "View " + metadataKey + " Metadata details", null, false, null, SPUIButtonStyleSmallNoBorder.class); + viewIcon.setData(metadataKey); + viewIcon.addStyleName(ValoTheme.BUTTON_TINY + " " + ValoTheme.BUTTON_LINK + " " + "on-focus-no-border link" + + " " + "text-style"); + viewIcon.addClickListener(event -> showMetadataDetails(metadataKey)); + return viewIcon; + } + + protected abstract String getDetailLinkId(final String name); + + protected abstract void showMetadataDetails(final String metadataKey); + +} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/AbstractSoftwareModuleDetails.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/AbstractSoftwareModuleDetails.java index dd66cef65..b2de2810d 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/AbstractSoftwareModuleDetails.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/AbstractSoftwareModuleDetails.java @@ -8,15 +8,12 @@ */ package org.eclipse.hawkbit.ui.common.detailslayout; -import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.SoftwareModuleManagement; -import org.eclipse.hawkbit.repository.model.MetaData; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.ui.SpPermissionChecker; import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent; import org.eclipse.hawkbit.ui.artifacts.smtable.SoftwareModuleAddUpdateWindow; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; -import org.eclipse.hawkbit.ui.distributions.event.MetadataEvent; import org.eclipse.hawkbit.ui.distributions.smtable.SwMetadataPopupLayout; import org.eclipse.hawkbit.ui.management.state.ManagementUIState; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; @@ -41,7 +38,7 @@ public abstract class AbstractSoftwareModuleDetails private static final long serialVersionUID = 1L; - private final SoftwareModuleMetadatadetailslayout swmMetadataTable; + private final SoftwareModuleMetadataDetailsLayout swmMetadataTable; private final SoftwareModuleAddUpdateWindow softwareModuleAddUpdateWindow; @@ -52,40 +49,18 @@ public abstract class AbstractSoftwareModuleDetails protected AbstractSoftwareModuleDetails(final VaadinMessageSource i18n, final UIEventBus eventBus, final SpPermissionChecker permissionChecker, final ManagementUIState managementUIState, final SoftwareModuleManagement softwareManagement, final SwMetadataPopupLayout swMetadataPopupLayout, - final EntityFactory entityFactory, final SoftwareModuleAddUpdateWindow softwareModuleAddUpdateWindow) { + final SoftwareModuleAddUpdateWindow softwareModuleAddUpdateWindow) { super(i18n, eventBus, permissionChecker, managementUIState); this.softwareModuleAddUpdateWindow = softwareModuleAddUpdateWindow; this.softwareModuleManagement = softwareManagement; this.swMetadataPopupLayout = swMetadataPopupLayout; - swmMetadataTable = new SoftwareModuleMetadatadetailslayout(); - swmMetadataTable.init(getI18n(), getPermissionChecker(), softwareManagement, swMetadataPopupLayout, - entityFactory); + swmMetadataTable = new SoftwareModuleMetadataDetailsLayout(getI18n(), softwareManagement, + swMetadataPopupLayout); addDetailsTab(); } - /** - * MetadataEvent. - * - * @param event - * as instance of {@link MetadataEvent} - */ - @EventBusListenerMethod(scope = EventScope.UI) - void onEvent(final MetadataEvent event) { - UI.getCurrent().access(() -> { - final MetaData softwareModuleMetadata = event.getMetaData(); - if (softwareModuleMetadata == null || !isSoftwareModuleSelected(event.getModule())) { - return; - } - if (event.getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.CREATE_SOFTWARE_MODULE_METADATA) { - swmMetadataTable.createMetadata(event.getMetaData().getKey()); - } else if (event.getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.DELETE_SOFTWARE_MODULE_METADATA) { - swmMetadataTable.deleteMetadata(event.getMetaData().getKey()); - } - }); - } - @EventBusListenerMethod(scope = EventScope.UI) void onEvent(final SoftwareModuleEvent softwareModuleEvent) { onBaseEntityEvent(softwareModuleEvent); @@ -124,7 +99,7 @@ public abstract class AbstractSoftwareModuleDetails @Override protected boolean hasEditPermission() { - return getPermissionChecker().hasUpdateDistributionPermission(); + return getPermissionChecker().hasUpdateRepositoryPermission(); } @Override diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/DistributionSetMetadataDetailsLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/DistributionSetMetadataDetailsLayout.java new file mode 100644 index 000000000..769d2e0ee --- /dev/null +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/DistributionSetMetadataDetailsLayout.java @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2015 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.ui.common.detailslayout; + +import java.util.List; + +import org.eclipse.hawkbit.repository.DistributionSetManagement; +import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.eclipse.hawkbit.repository.model.DistributionSetMetadata; +import org.eclipse.hawkbit.ui.distributions.dstable.DsMetadataPopupLayout; +import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider; +import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; +import org.springframework.data.domain.PageRequest; + +import com.vaadin.ui.UI; + +/** + * DistributionSet Metadata details layout. + * + */ +public class DistributionSetMetadataDetailsLayout extends AbstractMetadataDetailsLayout { + + private static final long serialVersionUID = 1L; + + private final transient DistributionSetManagement distributionSetManagement; + + private final DsMetadataPopupLayout dsMetadataPopupLayout; + + private Long selectedDistSetId; + + /** + * Initialize the layout. + * + * @param i18n + * the i18n service + * @param distributionSetManagement + * the distribution set management service + * @param dsMetadataPopupLayout + * the distribution set metadata popup layout + */ + public DistributionSetMetadataDetailsLayout(final VaadinMessageSource i18n, + final DistributionSetManagement distributionSetManagement, + final DsMetadataPopupLayout dsMetadataPopupLayout) { + super(i18n); + this.distributionSetManagement = distributionSetManagement; + this.dsMetadataPopupLayout = dsMetadataPopupLayout; + + } + + /** + * Populate software module metadata. + * + * @param distributionSet + */ + public void populateDSMetadata(final DistributionSet distributionSet) { + removeAllItems(); + if (null == distributionSet) { + return; + } + selectedDistSetId = distributionSet.getId(); + final List dsMetadataList = distributionSetManagement + .findMetaDataByDistributionSetId(new PageRequest(0, MAX_METADATA_QUERY), selectedDistSetId) + .getContent(); + if (null != dsMetadataList && !dsMetadataList.isEmpty()) { + dsMetadataList.forEach(this::setMetadataProperties); + } + + } + + @Override + protected void showMetadataDetails(final String metadataKey) { + distributionSetManagement.get(selectedDistSetId) + .ifPresent(distSet -> UI.getCurrent().addWindow(dsMetadataPopupLayout.getWindow(distSet, metadataKey))); + } + + @Override + protected String getDetailLinkId(final String name) { + return new StringBuilder(UIComponentIdProvider.DS_METADATA_DETAIL_LINK).append('.').append(name).toString(); + } + +} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/DistributionSetMetadatadetailsLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/DistributionSetMetadatadetailsLayout.java deleted file mode 100644 index d47231d08..000000000 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/DistributionSetMetadatadetailsLayout.java +++ /dev/null @@ -1,165 +0,0 @@ -/** - * Copyright (c) 2015 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.ui.common.detailslayout; - -import java.util.List; -import java.util.Optional; - -import org.eclipse.hawkbit.repository.DistributionSetManagement; -import org.eclipse.hawkbit.repository.EntityFactory; -import org.eclipse.hawkbit.repository.model.DistributionSet; -import org.eclipse.hawkbit.repository.model.DistributionSetMetadata; -import org.eclipse.hawkbit.ui.SpPermissionChecker; -import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; -import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder; -import org.eclipse.hawkbit.ui.distributions.dstable.DsMetadataPopupLayout; -import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions; -import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider; -import org.eclipse.hawkbit.ui.utils.UINotification; -import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; -import org.springframework.data.domain.PageRequest; - -import com.vaadin.data.Item; -import com.vaadin.data.util.IndexedContainer; -import com.vaadin.ui.Button; -import com.vaadin.ui.Label; -import com.vaadin.ui.Table; -import com.vaadin.ui.UI; -import com.vaadin.ui.themes.ValoTheme; - -/** - * DistributionSet Metadata details layout. - * - */ -public class DistributionSetMetadatadetailsLayout extends Table { - - private static final long serialVersionUID = 2913758299611837718L; - - private static final String METADATA_KEY = "Key"; - - private static final String VIEW = "view"; - - private final transient DistributionSetManagement distributionSetManagement; - - private final DsMetadataPopupLayout dsMetadataPopupLayout; - - private final SpPermissionChecker permissionChecker; - - private final transient EntityFactory entityFactory; - - private final VaadinMessageSource i18n; - - private Long selectedDistSetId; - - private final UINotification notification; - - public DistributionSetMetadatadetailsLayout(final VaadinMessageSource i18n, - final SpPermissionChecker permissionChecker, final DistributionSetManagement distributionSetManagement, - final DsMetadataPopupLayout dsMetadataPopupLayout, final EntityFactory entityFactory, - final UINotification notification) { - this.i18n = i18n; - this.permissionChecker = permissionChecker; - this.distributionSetManagement = distributionSetManagement; - this.dsMetadataPopupLayout = dsMetadataPopupLayout; - this.entityFactory = entityFactory; - this.notification = notification; - createDSMetadataTable(); - addCustomGeneratedColumns(); - } - - /** - * Populate software module metadata. - * - * @param distributionSet - */ - public void populateDSMetadata(final DistributionSet distributionSet) { - removeAllItems(); - if (null == distributionSet) { - return; - } - selectedDistSetId = distributionSet.getId(); - final List dsMetadataList = distributionSetManagement - .findMetaDataByDistributionSetId(new PageRequest(0, 500), selectedDistSetId) - .getContent(); - if (null != dsMetadataList && !dsMetadataList.isEmpty()) { - dsMetadataList.forEach(dsMetadata -> setDSMetadataProperties(dsMetadata)); - } - - } - - private void createDSMetadataTable() { - addStyleName(ValoTheme.TABLE_NO_HORIZONTAL_LINES); - addStyleName(ValoTheme.TABLE_NO_STRIPES); - addStyleName(SPUIStyleDefinitions.SW_MODULE_TABLE); - addStyleName("details-layout"); - setSelectable(false); - setImmediate(true); - setContainerDataSource(getDistSetContainer()); - setColumnHeaderMode(ColumnHeaderMode.EXPLICIT); - addDSMetadataTableHeader(); - setSizeFull(); - // same as height of other tabs in details tabsheet - setHeight(116, Unit.PIXELS); - } - - private IndexedContainer getDistSetContainer() { - final IndexedContainer container = new IndexedContainer(); - container.addContainerProperty(METADATA_KEY, String.class, ""); - setColumnExpandRatio(METADATA_KEY, 0.7F); - setColumnAlignment(METADATA_KEY, Align.LEFT); - - if (permissionChecker.hasUpdateDistributionPermission()) { - container.addContainerProperty(VIEW, Label.class, ""); - setColumnExpandRatio(VIEW, 0.2F); - setColumnAlignment(VIEW, Align.RIGHT); - } - return container; - } - - private void addDSMetadataTableHeader() { - setColumnHeader(METADATA_KEY, i18n.getMessage("header.key")); - } - - private void setDSMetadataProperties(final DistributionSetMetadata dsMetadata) { - final Item item = getContainerDataSource().addItem(dsMetadata.getKey()); - item.getItemProperty(METADATA_KEY).setValue(dsMetadata.getKey()); - - } - - private void addCustomGeneratedColumns() { - addGeneratedColumn(METADATA_KEY, (source, itemId, columnId) -> customMetadataDetailButton((String) itemId)); - } - - private Button customMetadataDetailButton(final String metadataKey) { - final Button viewIcon = SPUIComponentProvider.getButton(getDetailLinkId(metadataKey), metadataKey, - "View " + metadataKey + " Metadata details", null, false, null, SPUIButtonStyleSmallNoBorder.class); - viewIcon.setData(metadataKey); - viewIcon.addStyleName(ValoTheme.BUTTON_TINY + " " + ValoTheme.BUTTON_LINK + " " + "on-focus-no-border link" - + " " + "text-style"); - viewIcon.addClickListener(event -> showMetadataDetails(selectedDistSetId, metadataKey)); - return viewIcon; - } - - private static String getDetailLinkId(final String name) { - return new StringBuilder(UIComponentIdProvider.DS_METADATA_DETAIL_LINK).append('.').append(name).toString(); - } - - private void showMetadataDetails(final Long selectedDistSetId, final String metadataKey) { - final Optional distSet = distributionSetManagement.get(selectedDistSetId); - if (!distSet.isPresent()) { - notification.displayWarning(i18n.getMessage("distributionset.not.exists")); - return; - } - - /* display the window */ - UI.getCurrent().addWindow( - dsMetadataPopupLayout.getWindow(distSet.get(), entityFactory.generateMetadata(metadataKey, ""))); - } - -} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleDetailsTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleDetailsTable.java index db2281f34..ee86dd694 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleDetailsTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleDetailsTable.java @@ -145,7 +145,7 @@ public class SoftwareModuleDetailsTable extends Table { public void populateModule(final DistributionSet distributionSet) { removeAllItems(); if (distributionSet != null) { - if (isUnassignSoftModAllowed && permissionChecker.hasUpdateDistributionPermission()) { + if (isUnassignSoftModAllowed && permissionChecker.hasUpdateRepositoryPermission()) { try { isTargetAssigned = false; } catch (final EntityReadOnlyException exception) { @@ -229,7 +229,7 @@ public class SoftwareModuleDetailsTable extends Table { softwareModule.setId(sw.getName() + "-label"); horizontalLayout.addComponent(softwareModule); horizontalLayout.setExpandRatio(softwareModule, 1F); - if (isUnassignSoftModAllowed && permissionChecker.hasUpdateDistributionPermission() && !isTargetAssigned + if (isUnassignSoftModAllowed && permissionChecker.hasUpdateRepositoryPermission() && !isTargetAssigned && (isSoftModAvaiableForSoftType(alreadyAssignedSwModules, swModType))) { horizontalLayout.addComponent(reassignSoftModule); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleMetadataDetailsLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleMetadataDetailsLayout.java new file mode 100644 index 000000000..f18290ef7 --- /dev/null +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleMetadataDetailsLayout.java @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2015 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.ui.common.detailslayout; + +import java.util.List; + +import org.eclipse.hawkbit.repository.SoftwareModuleManagement; +import org.eclipse.hawkbit.repository.model.SoftwareModule; +import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; +import org.eclipse.hawkbit.ui.distributions.smtable.SwMetadataPopupLayout; +import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider; +import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; +import org.springframework.data.domain.PageRequest; +import org.springframework.util.CollectionUtils; + +import com.vaadin.ui.UI; + +/** + * SoftwareModule Metadata details layout. + * + */ +public class SoftwareModuleMetadataDetailsLayout extends AbstractMetadataDetailsLayout { + + private static final long serialVersionUID = 1L; + + private transient SoftwareModuleManagement softwareModuleManagement; + + private final SwMetadataPopupLayout swMetadataPopupLayout; + + private Long selectedSWModuleId; + + /** + * Initialize the layout. + * + * @param i18n + * the i18n service + * @param softwareManagement + * the software management service + * @param swMetadataPopupLayout + * the software module metadata popup layout + */ + public SoftwareModuleMetadataDetailsLayout(final VaadinMessageSource i18n, + final SoftwareModuleManagement softwareManagement, final SwMetadataPopupLayout swMetadataPopupLayout) { + super(i18n); + this.softwareModuleManagement = softwareManagement; + this.swMetadataPopupLayout = swMetadataPopupLayout; + } + + /** + * Populate software module metadata table. + * + * @param swModule + */ + public void populateSMMetadata(final SoftwareModule swModule) { + removeAllItems(); + if (null == swModule) { + return; + } + selectedSWModuleId = swModule.getId(); + final List swMetadataList = softwareModuleManagement + .findMetaDataBySoftwareModuleId(new PageRequest(0, MAX_METADATA_QUERY), selectedSWModuleId) + .getContent(); + if (!CollectionUtils.isEmpty(swMetadataList)) { + swMetadataList.forEach(this::setMetadataProperties); + } + } + + @Override + protected void showMetadataDetails(final String metadataKey) { + softwareModuleManagement.get(selectedSWModuleId).ifPresent( + swmodule -> UI.getCurrent().addWindow(swMetadataPopupLayout.getWindow(swmodule, metadataKey))); + } + + @Override + protected String getDetailLinkId(final String name) { + return new StringBuilder(UIComponentIdProvider.SW_METADATA_DETAIL_LINK).append('.').append(name).toString(); + } + +} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleMetadatadetailslayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleMetadatadetailslayout.java deleted file mode 100644 index 196e210da..000000000 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleMetadatadetailslayout.java +++ /dev/null @@ -1,185 +0,0 @@ -/** - * Copyright (c) 2015 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.ui.common.detailslayout; - -import java.util.List; - -import org.eclipse.hawkbit.repository.EntityFactory; -import org.eclipse.hawkbit.repository.SoftwareModuleManagement; -import org.eclipse.hawkbit.repository.model.SoftwareModule; -import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; -import org.eclipse.hawkbit.ui.SpPermissionChecker; -import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; -import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder; -import org.eclipse.hawkbit.ui.distributions.smtable.SwMetadataPopupLayout; -import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions; -import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider; -import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; -import org.springframework.data.domain.PageRequest; -import org.springframework.util.CollectionUtils; - -import com.vaadin.data.Item; -import com.vaadin.data.util.IndexedContainer; -import com.vaadin.spring.annotation.SpringComponent; -import com.vaadin.spring.annotation.UIScope; -import com.vaadin.ui.Button; -import com.vaadin.ui.Table; -import com.vaadin.ui.UI; -import com.vaadin.ui.themes.ValoTheme; - -/** - * SoftwareModule Metadata details layout. - * - */ -@SpringComponent -@UIScope -public class SoftwareModuleMetadatadetailslayout extends Table { - - private static final long serialVersionUID = 2913758299611838818L; - - private static final String METADATA_KEY = "Key"; - - private static final int MAX_METADATA_QUERY = 500; - - private SpPermissionChecker permissionChecker; - - private transient SoftwareModuleManagement softwareModuleManagement; - - private SwMetadataPopupLayout swMetadataPopupLayout; - - private VaadinMessageSource i18n; - - private Long selectedSWModuleId; - - private transient EntityFactory entityFactory; - - /** - * Initialize the layout. - * - * @param i18n - * the i18n service - * @param permissionChecker - * the permission checker service - * @param softwareManagement - * the software management service - * @param swMetadataPopupLayout - * the software module metadata popup layout - * @param entityFactory - * the entity factory service - */ - public void init(final VaadinMessageSource i18n, final SpPermissionChecker permissionChecker, - final SoftwareModuleManagement softwareManagement, final SwMetadataPopupLayout swMetadataPopupLayout, - final EntityFactory entityFactory) { - this.i18n = i18n; - this.permissionChecker = permissionChecker; - this.softwareModuleManagement = softwareManagement; - this.swMetadataPopupLayout = swMetadataPopupLayout; - this.entityFactory = entityFactory; - createSWMMetadataTable(); - addCustomGeneratedColumns(); - } - - /** - * Populate software module metadata table. - * - * @param swModule - */ - public void populateSMMetadata(final SoftwareModule swModule) { - removeAllItems(); - if (null == swModule) { - return; - } - selectedSWModuleId = swModule.getId(); - final List swMetadataList = softwareModuleManagement - .findMetaDataBySoftwareModuleId(new PageRequest(0, MAX_METADATA_QUERY), - selectedSWModuleId) - .getContent(); - if (!CollectionUtils.isEmpty(swMetadataList)) { - swMetadataList.forEach(this::setSWMetadataProperties); - } - } - - /** - * Create metadata. - * - * @param metadataKeyName - */ - public void createMetadata(final String metadataKeyName) { - final IndexedContainer metadataContainer = (IndexedContainer) getContainerDataSource(); - final Item item = metadataContainer.addItem(metadataKeyName); - item.getItemProperty(METADATA_KEY).setValue(metadataKeyName); - - } - - /** - * Delete metadata. - * - * @param metadataKeyName - */ - public void deleteMetadata(final String metadataKeyName) { - final IndexedContainer metadataContainer = (IndexedContainer) getContainerDataSource(); - metadataContainer.removeItem(metadataKeyName); - } - - private void createSWMMetadataTable() { - addStyleName(ValoTheme.TABLE_NO_HORIZONTAL_LINES); - addStyleName(ValoTheme.TABLE_NO_STRIPES); - addStyleName(SPUIStyleDefinitions.SW_MODULE_TABLE); - setSelectable(false); - setImmediate(true); - setContainerDataSource(getSwModuleMetadataContainer()); - setColumnHeaderMode(ColumnHeaderMode.EXPLICIT); - addSMMetadataTableHeader(); - setSizeFull(); - // same as height of other tabs in details tabsheet - setHeight(116, Unit.PIXELS); - } - - private IndexedContainer getSwModuleMetadataContainer() { - final IndexedContainer container = new IndexedContainer(); - container.addContainerProperty(METADATA_KEY, String.class, ""); - setColumnAlignment(METADATA_KEY, Align.LEFT); - return container; - } - - private void addSMMetadataTableHeader() { - setColumnHeader(METADATA_KEY, i18n.getMessage("header.key")); - } - - private void setSWMetadataProperties(final SoftwareModuleMetadata swMetadata) { - final Item item = getContainerDataSource().addItem(swMetadata.getKey()); - item.getItemProperty(METADATA_KEY).setValue(swMetadata.getKey()); - } - - private void addCustomGeneratedColumns() { - addGeneratedColumn(METADATA_KEY, (source, itemId, columnId) -> customMetadataDetailButton((String) itemId)); - } - - private Button customMetadataDetailButton(final String metadataKey) { - final Button viewLink = SPUIComponentProvider.getButton(getDetailLinkId(metadataKey), metadataKey, - "View" + metadataKey + " Metadata details", null, false, null, SPUIButtonStyleSmallNoBorder.class); - viewLink.setData(metadataKey); - if (permissionChecker.hasUpdateDistributionPermission()) { - viewLink.addStyleName(ValoTheme.BUTTON_TINY + " " + ValoTheme.BUTTON_LINK + " " + "on-focus-no-border link" - + " " + "text-style"); - viewLink.addClickListener(event -> showMetadataDetails(selectedSWModuleId, metadataKey)); - } - return viewLink; - } - - private static String getDetailLinkId(final String name) { - return new StringBuilder(UIComponentIdProvider.SW_METADATA_DETAIL_LINK).append('.').append(name).toString(); - } - - private void showMetadataDetails(final Long selectedSWModuleId, final String metadataKey) { - softwareModuleManagement.get(selectedSWModuleId).ifPresent(swmodule -> UI.getCurrent() - .addWindow(swMetadataPopupLayout.getWindow(swmodule, entityFactory.generateMetadata(metadataKey, "")))); - } - -} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractDistributionSetTableHeader.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractDistributionSetTableHeader.java index 1294d0811..f89acde75 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractDistributionSetTableHeader.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractDistributionSetTableHeader.java @@ -61,7 +61,7 @@ public abstract class AbstractDistributionSetTableHeader extends AbstractTableHe @Override protected boolean hasCreatePermission() { - return permChecker.hasCreateDistributionPermission(); + return permChecker.hasCreateRepositoryPermission(); } @Override diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractSoftwareModuleTableHeader.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractSoftwareModuleTableHeader.java index 2da67f10b..a9633c7e7 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractSoftwareModuleTableHeader.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractSoftwareModuleTableHeader.java @@ -86,7 +86,7 @@ public abstract class AbstractSoftwareModuleTableHeader extends AbstractTableHea @Override protected boolean hasCreatePermission() { - return permChecker.hasCreateDistributionPermission(); + return permChecker.hasCreateRepositoryPermission(); } @Override diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/DistributionTagToken.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/DistributionTagToken.java index 3fe949d9c..f91aef73c 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/DistributionTagToken.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/DistributionTagToken.java @@ -101,7 +101,7 @@ public class DistributionTagToken extends AbstractTagToken { @Override protected Boolean isToggleTagAssignmentAllowed() { - return checker.hasUpdateDistributionPermission(); + return checker.hasUpdateRepositoryPermission(); } @Override diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/DistributionsView.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/DistributionsView.java index d2f2554d7..225e16100 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/DistributionsView.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/DistributionsView.java @@ -172,8 +172,8 @@ public class DistributionsView extends AbstractNotificationView implements Brows } private boolean hasUserPermission() { - return permChecker.hasUpdateDistributionPermission() || permChecker.hasCreateDistributionPermission() - || permChecker.hasReadDistributionPermission(); + return permChecker.hasUpdateRepositoryPermission() || permChecker.hasCreateRepositoryPermission() + || permChecker.hasReadRepositoryPermission(); } private void createMainLayout() { diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/disttype/DSTypeFilterHeader.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/disttype/DSTypeFilterHeader.java index 87a604112..f39590ae8 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/disttype/DSTypeFilterHeader.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/disttype/DSTypeFilterHeader.java @@ -54,7 +54,7 @@ public class DSTypeFilterHeader extends AbstractFilterHeader { @Override protected boolean hasCreateUpdatePermission() { - return permChecker.hasCreateDistributionPermission() || permChecker.hasUpdateDistributionPermission(); + return permChecker.hasCreateRepositoryPermission() || permChecker.hasUpdateRepositoryPermission(); } @Override diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetDetails.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetDetails.java index 0bc723b59..1b05e812a 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetDetails.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetDetails.java @@ -14,7 +14,6 @@ import java.util.Set; import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetTagManagement; -import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.model.SoftwareModule; @@ -71,13 +70,12 @@ public class DistributionSetDetails extends AbstractDistributionSetDetails { final DistributionAddUpdateWindowLayout distributionAddUpdateWindowLayout, final SoftwareModuleManagement softwareManagement, final DistributionSetManagement distributionSetManagement, final TargetManagement targetManagement, - final EntityFactory entityFactory, final UINotification uiNotification, - final DistributionSetTagManagement distributionSetTagManagement, + final UINotification uiNotification, final DistributionSetTagManagement distributionSetTagManagement, final DsMetadataPopupLayout dsMetadataPopupLayout) { super(i18n, eventBus, permissionChecker, managementUIState, distributionAddUpdateWindowLayout, - distributionSetManagement, dsMetadataPopupLayout, entityFactory, uiNotification, - distributionSetTagManagement, createSoftwareModuleDetailsTable(i18n, permissionChecker, - distributionSetManagement, eventBus, manageDistUIState, uiNotification)); + distributionSetManagement, dsMetadataPopupLayout, uiNotification, distributionSetTagManagement, + createSoftwareModuleDetailsTable(i18n, permissionChecker, distributionSetManagement, eventBus, + manageDistUIState, uiNotification)); this.manageDistUIState = manageDistUIState; this.softwareModuleManagement = softwareManagement; this.targetManagement = targetManagement; @@ -127,8 +125,7 @@ public class DistributionSetDetails extends AbstractDistributionSetDetails { assignedSWModule = new HashMap<>(); } - softwareModuleIdNameList.stream().map(SoftwareModuleIdName::getId) - .map(softwareModuleManagement::get) + softwareModuleIdNameList.stream().map(SoftwareModuleIdName::getId).map(softwareModuleManagement::get) .forEach(found -> found.ifPresent(softwareModule -> { if (assignedSWModule.containsKey(softwareModule.getType().getName())) { @@ -157,7 +154,7 @@ public class DistributionSetDetails extends AbstractDistributionSetDetails { } private Button assignSoftModuleButton(final String softwareModuleName) { - if (getPermissionChecker().hasUpdateDistributionPermission() && manageDistUIState.getLastSelectedDistribution() + if (getPermissionChecker().hasUpdateRepositoryPermission() && manageDistUIState.getLastSelectedDistribution() .map(selected -> targetManagement.countByAssignedDistributionSet(selected) <= 0).orElse(false)) { final Button reassignSoftModule = SPUIComponentProvider.getButton(softwareModuleName, "", "", "", true, @@ -255,11 +252,10 @@ public class DistributionSetDetails extends AbstractDistributionSetDetails { assignedSWModule.clear(); } - getDistributionSetManagement().getWithDetails(getSelectedBaseEntityId()) - .ifPresent(set -> { - setSelectedBaseEntity(set); - UI.getCurrent().access(this::populateModule); - }); + getDistributionSetManagement().getWithDetails(getSelectedBaseEntityId()).ifPresent(set -> { + setSelectedBaseEntity(set); + UI.getCurrent().access(this::populateModule); + }); } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTable.java index 5ff6a766b..bdea43c08 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTable.java @@ -385,7 +385,7 @@ public class DistributionSetTable extends AbstractNamedVersionTable getMetadataList() { return Collections.unmodifiableList(distributionSetManagement - .findMetaDataByDistributionSetId(new PageRequest(0, 500), getSelectedEntity().getId()) - .getContent()); + .findMetaDataByDistributionSetId(new PageRequest(0, 500), getSelectedEntity().getId()).getContent()); } @Override - protected void deleteMetadata(final DistributionSet entity, final String key, final String value) { + protected void deleteMetadata(final DistributionSet entity, final String key) { distributionSetManagement.deleteMetaData(entity.getId(), key); } @Override protected boolean hasCreatePermission() { - return permChecker.hasCreateDistributionPermission(); + return permChecker.hasCreateRepositoryPermission(); } @Override protected boolean hasUpdatePermission() { - return permChecker.hasUpdateDistributionPermission(); + return permChecker.hasUpdateRepositoryPermission(); } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/MetadataEvent.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/MetadataEvent.java deleted file mode 100644 index 492f2d5ce..000000000 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/MetadataEvent.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (c) 2015 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.ui.distributions.event; - -import org.eclipse.hawkbit.repository.model.MetaData; -import org.eclipse.hawkbit.repository.model.SoftwareModule; - -/** - * - * Metadata Events. - * - */ -public class MetadataEvent { - - public enum MetadataUIEvent { - DELETE_SOFTWARE_MODULE_METADATA, CREATE_SOFTWARE_MODULE_METADATA; - } - - private final MetadataUIEvent metadataUIEvent; - - private final MetaData metadata; - - private final SoftwareModule module; - - public MetadataEvent(final MetadataUIEvent metadataUIEvent, final MetaData metadata, final SoftwareModule module) { - this.metadataUIEvent = metadataUIEvent; - this.metadata = metadata; - this.module = module; - } - - public MetadataUIEvent getMetadataUIEvent() { - return metadataUIEvent; - } - - public MetaData getMetaData() { - return metadata; - } - - public SoftwareModule getModule() { - return module; - } - -} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/footer/DSDeleteActionsLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/footer/DSDeleteActionsLayout.java index 225e68fdc..63d22a0f9 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/footer/DSDeleteActionsLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/footer/DSDeleteActionsLayout.java @@ -100,14 +100,14 @@ public class DSDeleteActionsLayout extends AbstractDeleteActionsLayout { @Override protected boolean hasDeletePermission() { - return permChecker.hasDeleteDistributionPermission(); + return permChecker.hasDeleteRepositoryPermission(); } @Override protected boolean hasUpdatePermission() { - return permChecker.hasUpdateDistributionPermission(); + return permChecker.hasUpdateRepositoryPermission(); } @Override diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwMetadataPopupLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwMetadataPopupLayout.java index de806a493..a04045088 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwMetadataPopupLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwMetadataPopupLayout.java @@ -13,28 +13,35 @@ import java.util.List; import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.SoftwareModuleManagement; -import org.eclipse.hawkbit.repository.model.MetaData; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; import org.eclipse.hawkbit.ui.SpPermissionChecker; import org.eclipse.hawkbit.ui.common.AbstractMetadataPopupLayout; -import org.eclipse.hawkbit.ui.distributions.event.MetadataEvent; -import org.eclipse.hawkbit.ui.distributions.event.MetadataEvent.MetadataUIEvent; +import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider; import org.eclipse.hawkbit.ui.utils.UINotification; import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; import org.springframework.data.domain.PageRequest; import org.vaadin.spring.events.EventBus.UIEventBus; +import com.vaadin.data.Item; +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.ui.CheckBox; +import com.vaadin.ui.Grid; +import com.vaadin.ui.VerticalLayout; + /** * Pop up layout to display software module metadata. */ -public class SwMetadataPopupLayout extends AbstractMetadataPopupLayout { +public class SwMetadataPopupLayout extends AbstractMetadataPopupLayout { - private static final long serialVersionUID = -1252090014161012563L; + private static final long serialVersionUID = 1L; + + protected static final String TARGET_VISIBLE = "targetVisible"; private final transient SoftwareModuleManagement softwareModuleManagement; private final transient EntityFactory entityFactory; + private CheckBox targetVisibleField; public SwMetadataPopupLayout(final VaadinMessageSource i18n, final UINotification uiNotification, final UIEventBus eventBus, final SoftwareModuleManagement softwareManagement, @@ -49,52 +56,135 @@ public class SwMetadataPopupLayout extends AbstractMetadataPopupLayout getMetadataList() { + protected List getMetadataList() { return Collections.unmodifiableList(softwareModuleManagement - .findMetaDataBySoftwareModuleId(new PageRequest(0, MAX_METADATA_QUERY), getSelectedEntity().getId()).getContent()); + .findMetaDataBySoftwareModuleId(new PageRequest(0, MAX_METADATA_QUERY), getSelectedEntity().getId()) + .getContent()); } - /** - * delete metadata for SWModule. - */ @Override - protected void deleteMetadata(final SoftwareModule entity, final String key, final String value) { + protected Grid createMetadataGrid() { + final Grid metadataGrid = super.createMetadataGrid(); + metadataGrid.getContainerDataSource().addContainerProperty(TARGET_VISIBLE, Boolean.class, Boolean.FALSE); + metadataGrid.getColumn(TARGET_VISIBLE).setHeaderCaption(i18n.getMessage("metadata.targetvisible")); + metadataGrid.getColumn(TARGET_VISIBLE).setHidden(true); + return metadataGrid; + } + + @Override + protected void deleteMetadata(final SoftwareModule entity, final String key) { softwareModuleManagement.deleteMetaData(entity.getId(), key); - eventBus.publish(this, new MetadataEvent(MetadataUIEvent.DELETE_SOFTWARE_MODULE_METADATA, - entityFactory.generateMetadata(key, value), entity)); } @Override protected boolean hasCreatePermission() { - return permChecker.hasCreateDistributionPermission(); + return permChecker.hasCreateRepositoryPermission(); } @Override protected boolean hasUpdatePermission() { - return permChecker.hasUpdateDistributionPermission(); + return permChecker.hasUpdateRepositoryPermission(); + } + + private CheckBox createTargetVisibleField() { + final CheckBox checkBox = new CheckBox(); + checkBox.setId(UIComponentIdProvider.METADATA_TARGET_VISIBLE_ID); + checkBox.setCaption(i18n.getMessage("metadata.targetvisible")); + checkBox.addValueChangeListener(this::onCheckBoxChange); + + return checkBox; + } + + // Exception for squid:S1172 - parameter defined by Vaadin + @SuppressWarnings("squid:S1172") + private void onCheckBoxChange(final ValueChangeEvent event) { + if (hasCreatePermission() || hasUpdatePermission()) { + if (!getValueTextArea().getValue().isEmpty() && !getKeyTextField().getValue().isEmpty()) { + getMetadataWindow().setSaveButtonEnabled(true); + } else { + getMetadataWindow().setSaveButtonEnabled(false); + } + } + + } + + @Override + protected void createComponents() { + super.createComponents(); + targetVisibleField = createTargetVisibleField(); + } + + @Override + protected VerticalLayout createMetadataFieldsLayout() { + + final VerticalLayout metadataFieldsLayout = super.createMetadataFieldsLayout(); + metadataFieldsLayout.addComponent(targetVisibleField); + return metadataFieldsLayout; + } + + @Override + protected Item popualateKeyValue(final Object metadataCompositeKey) { + final Item item = super.popualateKeyValue(metadataCompositeKey); + + if (item != null) { + targetVisibleField.setValue((Boolean) item.getItemProperty(TARGET_VISIBLE).getValue()); + if (hasUpdatePermission()) { + targetVisibleField.setEnabled(true); + } + } + + return item; + } + + @Override + protected Item updateItemInGrid(final String key) { + final Item item = super.updateItemInGrid(key); + item.getItemProperty(TARGET_VISIBLE).setValue(targetVisibleField.getValue()); + + return item; + } + + @Override + protected Item addItemToGrid(final SoftwareModuleMetadata metaData) { + final Item item = super.addItemToGrid(metaData); + item.getItemProperty(TARGET_VISIBLE).setValue(metaData.isTargetVisible()); + return item; + } + + @Override + protected void enableEditing() { + super.enableEditing(); + targetVisibleField.setEnabled(true); + } + + @Override + protected void clearFields() { + super.clearFields(); + targetVisibleField.clear(); + } + + @Override + protected void disableEditing() { + super.disableEditing(); + targetVisibleField.setEnabled(false); } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleDetails.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleDetails.java index a282e3d96..da4f9a730 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleDetails.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleDetails.java @@ -8,7 +8,6 @@ */ package org.eclipse.hawkbit.ui.distributions.smtable; -import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.ui.SpPermissionChecker; @@ -33,8 +32,8 @@ public class SwModuleDetails extends AbstractSoftwareModuleDetails { final SpPermissionChecker permissionChecker, final SoftwareModuleAddUpdateWindow softwareModuleAddUpdateWindow, final ManageDistUIState manageDistUIState, final SoftwareModuleManagement softwareManagement, - final SwMetadataPopupLayout swMetadataPopupLayout, final EntityFactory entityFactory) { - super(i18n, eventBus, permissionChecker, null, softwareManagement, swMetadataPopupLayout, entityFactory, + final SwMetadataPopupLayout swMetadataPopupLayout) { + super(i18n, eventBus, permissionChecker, null, softwareManagement, swMetadataPopupLayout, softwareModuleAddUpdateWindow); this.manageDistUIState = manageDistUIState; restoreState(); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleTableLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleTableLayout.java index 94c28fd21..969def956 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleTableLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleTableLayout.java @@ -41,8 +41,9 @@ public class SwModuleTableLayout extends AbstractTableLayout { final SwMetadataPopupLayout swMetadataPopupLayout = new SwMetadataPopupLayout(i18n, uiNotification, eventBus, softwareModuleManagement, entityFactory, permChecker); - this.swModuleTable = new SwModuleTable(eventBus, i18n, uiNotification, manageDistUIState, softwareModuleManagement, - distributionsViewClientCriterion, artifactManagement, swMetadataPopupLayout, artifactUploadState); + this.swModuleTable = new SwModuleTable(eventBus, i18n, uiNotification, manageDistUIState, + softwareModuleManagement, distributionsViewClientCriterion, artifactManagement, swMetadataPopupLayout, + artifactUploadState); final SoftwareModuleAddUpdateWindow softwareModuleAddUpdateWindow = new SoftwareModuleAddUpdateWindow(i18n, uiNotification, eventBus, softwareModuleManagement, softwareModuleTypeManagement, entityFactory, @@ -50,7 +51,7 @@ public class SwModuleTableLayout extends AbstractTableLayout { super.init( new SwModuleTableHeader(i18n, permChecker, eventBus, manageDistUIState, softwareModuleAddUpdateWindow), swModuleTable, new SwModuleDetails(i18n, eventBus, permChecker, softwareModuleAddUpdateWindow, - manageDistUIState, softwareModuleManagement, swMetadataPopupLayout, entityFactory)); + manageDistUIState, softwareModuleManagement, swMetadataPopupLayout)); } public SwModuleTable getSwModuleTable() { diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtype/DistSMTypeFilterHeader.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtype/DistSMTypeFilterHeader.java index 408d7cb4f..8a0ba80f0 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtype/DistSMTypeFilterHeader.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtype/DistSMTypeFilterHeader.java @@ -55,7 +55,7 @@ public class DistSMTypeFilterHeader extends AbstractFilterHeader { @Override protected boolean hasCreateUpdatePermission() { - return permChecker.hasCreateDistributionPermission() || permChecker.hasUpdateDistributionPermission(); + return permChecker.hasCreateRepositoryPermission() || permChecker.hasUpdateRepositoryPermission(); } @Override diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/layouts/CreateUpdateTypeLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/layouts/CreateUpdateTypeLayout.java index 64c65d364..bfffd17e1 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/layouts/CreateUpdateTypeLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/layouts/CreateUpdateTypeLayout.java @@ -78,7 +78,7 @@ public abstract class CreateUpdateTypeLayout extends Abst getPreviewButtonColor(ColorPickerConstants.DEFAULT_COLOR); tagColorPreviewBtn.setStyleName(TAG_DYNAMIC_STYLE); - createOptionGroup(permChecker.hasCreateDistributionPermission(), permChecker.hasUpdateDistributionPermission()); + createOptionGroup(permChecker.hasCreateRepositoryPermission(), permChecker.hasUpdateRepositoryPermission()); } @Override @@ -128,8 +128,8 @@ public abstract class CreateUpdateTypeLayout extends Abst super.reset(); typeKey.clear(); restoreComponentStyles(); - setOptionGroupDefaultValue(permChecker.hasCreateDistributionPermission(), - permChecker.hasUpdateDistributionPermission()); + setOptionGroupDefaultValue(permChecker.hasCreateRepositoryPermission(), + permChecker.hasUpdateRepositoryPermission()); } /** diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/DeploymentView.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/DeploymentView.java index e9c23502c..2c2cde881 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/DeploymentView.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/DeploymentView.java @@ -232,7 +232,7 @@ public class DeploymentView extends AbstractNotificationView implements BrowserW private void buildLayout() { // Build only if user has both permissions - if (permChecker.hasTargetReadPermission() || permChecker.hasReadDistributionPermission()) { + if (permChecker.hasTargetReadPermission() || permChecker.hasReadRepositoryPermission()) { setSizeFull(); createMainLayout(); addComponents(mainLayout); @@ -250,9 +250,9 @@ public class DeploymentView extends AbstractNotificationView implements BrowserW private void layoutWidgets() { mainLayout.removeAllComponents(); - if (permChecker.hasReadDistributionPermission() && permChecker.hasTargetReadPermission()) { + if (permChecker.hasReadRepositoryPermission() && permChecker.hasTargetReadPermission()) { displayAllWidgets(); - } else if (permChecker.hasReadDistributionPermission()) { + } else if (permChecker.hasReadRepositoryPermission()) { displayDistributionWidgetsOnly(); } else if (permChecker.hasTargetReadPermission()) { displayTargetWidgetsOnly(); @@ -292,7 +292,7 @@ public class DeploymentView extends AbstractNotificationView implements BrowserW private Boolean showFooterLayout() { if (permChecker.hasTargetReadPermission() - || (permChecker.hasDeleteDistributionPermission() || permChecker.hasDeleteTargetPermission()) + || (permChecker.hasDeleteRepositoryPermission() || permChecker.hasDeleteTargetPermission()) || hasDeploymentPermission()) { return true; } @@ -300,7 +300,7 @@ public class DeploymentView extends AbstractNotificationView implements BrowserW } private boolean hasDeploymentPermission() { - return permChecker.hasReadDistributionPermission() && permChecker.hasUpdateTargetPermission(); + return permChecker.hasReadRepositoryPermission() && permChecker.hasUpdateTargetPermission(); } private void displayTargetWidgetsOnly() { @@ -318,7 +318,7 @@ public class DeploymentView extends AbstractNotificationView implements BrowserW } private void maximizeTargetTable() { - if (permChecker.hasReadDistributionPermission()) { + if (permChecker.hasReadRepositoryPermission()) { mainLayout.removeComponent(distributionTableLayout); mainLayout.removeComponent(distributionTagLayout); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionDetails.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionDetails.java index 21aed433c..050eb94d2 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionDetails.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionDetails.java @@ -10,7 +10,6 @@ package org.eclipse.hawkbit.ui.management.dstable; import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetTagManagement; -import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.ui.SpPermissionChecker; import org.eclipse.hawkbit.ui.common.detailslayout.AbstractDistributionSetDetails; import org.eclipse.hawkbit.ui.common.detailslayout.SoftwareModuleDetailsTable; @@ -30,12 +29,11 @@ public class DistributionDetails extends AbstractDistributionSetDetails { DistributionDetails(final VaadinMessageSource i18n, final UIEventBus eventBus, final SpPermissionChecker permissionChecker, final ManagementUIState managementUIState, final DistributionSetManagement distributionSetManagement, - final DsMetadataPopupLayout dsMetadataPopupLayout, final EntityFactory entityFactory, - final UINotification uiNotification, final DistributionSetTagManagement distributionSetTagManagement, + final DsMetadataPopupLayout dsMetadataPopupLayout, final UINotification uiNotification, + final DistributionSetTagManagement distributionSetTagManagement, final DistributionAddUpdateWindowLayout distributionAddUpdateWindowLayout) { super(i18n, eventBus, permissionChecker, managementUIState, distributionAddUpdateWindowLayout, - distributionSetManagement, dsMetadataPopupLayout, entityFactory, uiNotification, - distributionSetTagManagement, + distributionSetManagement, dsMetadataPopupLayout, uiNotification, distributionSetTagManagement, createSoftwareModuleDetailsTable(i18n, permissionChecker, uiNotification)); restoreState(); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTableLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTableLayout.java index 9eb598234..a5b97bd01 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTableLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTableLayout.java @@ -56,7 +56,7 @@ public class DistributionTableLayout extends AbstractTableLayout