From 82ee1cc4e67cd7ab35ee078bbab21fe81de9486a Mon Sep 17 00:00:00 2001 From: Avgustin Marinov Date: Wed, 15 Apr 2026 16:57:10 +0300 Subject: [PATCH] Fix sonar findings on 21 style (#3020) Signed-off-by: Avgustin Marinov --- .../amqp/AmqpDeadletterProperties.java | 4 +- .../amqp/DmfAmqpDeclarationConfiguration.java | 2 +- .../server/tools/HawkbitMcpToolProvider.java | 281 +++++++++--------- .../org/eclipse/hawkbit/ql/EntityMatcher.java | 162 +++++----- .../hawkbit/ql/jpa/SpecificationBuilder.java | 48 +-- .../repository/jpa/utils/ExceptionMapper.java | 2 +- .../repository/jpa/JpaConfiguration.java | 2 +- .../jpa/model/AbstractJpaBaseEntity.java | 15 +- .../management/JpaControllerManagement.java | 2 +- .../repository/jpa/utils/StatisticsUtils.java | 12 +- .../eclipse/hawkbit/ui/view/TargetView.java | 5 +- .../eclipse/hawkbit/ui/view/util/Filter.java | 22 +- 12 files changed, 284 insertions(+), 273 deletions(-) diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpDeadletterProperties.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpDeadletterProperties.java index fddabcad5..4c362f821 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpDeadletterProperties.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpDeadletterProperties.java @@ -39,7 +39,7 @@ public class AmqpDeadletterProperties { * @return map which holds the properties */ public Map getDeadLetterExchangeArgs(final String exchange) { - final Map args = new HashMap<>(1); + final Map args = HashMap.newHashMap(1); args.put("x-dead-letter-exchange", exchange); return args; } @@ -55,7 +55,7 @@ public class AmqpDeadletterProperties { } private Map getTTLArgs() { - final Map args = new HashMap<>(1); + final Map args = HashMap.newHashMap(1); args.put("x-message-ttl", getTtl()); return args; } diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DmfAmqpDeclarationConfiguration.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DmfAmqpDeclarationConfiguration.java index 26243d1b4..aea1d830a 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DmfAmqpDeclarationConfiguration.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DmfAmqpDeclarationConfiguration.java @@ -142,7 +142,7 @@ public class DmfAmqpDeclarationConfiguration { } private static Map getTTLMaxArgsAuthenticationQueue() { - final Map args = new HashMap<>(2); + final Map args = HashMap.newHashMap(2); args.put("x-message-ttl", Duration.ofSeconds(30).toMillis()); args.put("x-max-length", 1_000); return args; diff --git a/hawkbit-mcp/hawkbit-mcp-starter/src/main/java/org/eclipse/hawkbit/mcp/server/tools/HawkbitMcpToolProvider.java b/hawkbit-mcp/hawkbit-mcp-starter/src/main/java/org/eclipse/hawkbit/mcp/server/tools/HawkbitMcpToolProvider.java index 70261393e..27ccea715 100644 --- a/hawkbit-mcp/hawkbit-mcp-starter/src/main/java/org/eclipse/hawkbit/mcp/server/tools/HawkbitMcpToolProvider.java +++ b/hawkbit-mcp/hawkbit-mcp-starter/src/main/java/org/eclipse/hawkbit/mcp/server/tools/HawkbitMcpToolProvider.java @@ -9,6 +9,9 @@ */ package org.eclipse.hawkbit.mcp.server.tools; +import java.util.Collections; +import java.util.List; + import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.eclipse.hawkbit.mcp.server.config.HawkbitMcpProperties; @@ -24,10 +27,18 @@ import org.eclipse.hawkbit.mcp.server.dto.TargetRequest; import org.eclipse.hawkbit.mgmt.json.model.PagedList; import org.eclipse.hawkbit.mgmt.json.model.action.MgmtAction; import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSet; +import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSetRequestBodyPost; +import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSetRequestBodyPut; import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutResponseBody; +import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutRestRequestBodyPost; +import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutRestRequestBodyPut; import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModule; +import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleRequestBodyPost; +import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleRequestBodyPut; import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTarget; +import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTargetRequestBody; import org.eclipse.hawkbit.mgmt.json.model.targetfilter.MgmtTargetFilterQuery; +import org.eclipse.hawkbit.mgmt.json.model.targetfilter.MgmtTargetFilterQueryRequestBody; import org.eclipse.hawkbit.mgmt.rest.api.MgmtActionRestApi; import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetRestApi; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRolloutRestApi; @@ -39,9 +50,6 @@ import org.eclipse.hawkbit.sdk.Tenant; import org.springaicommunity.mcp.annotation.McpTool; import org.springframework.http.ResponseEntity; -import java.util.Collections; -import java.util.List; - /** * MCP tools for hawkBit using the SDK. *

@@ -94,8 +102,8 @@ public class HawkbitMcpToolProvider { } @McpTool(name = "list_targets", - description = "Retrieves a paged list of targets (devices) with optional RSQL filtering. " + - "Targets represent devices that can receive software updates.") + description = "Retrieves a paged list of targets (devices) with optional RSQL filtering. " + + "Targets represent devices that can receive software updates.") public PagedResponse listTargets(final ListRequest request) { log.debug("Listing targets with rsql={}, offset={}, limit={}", request.rsql(), request.getOffsetOrDefault(), request.getLimitOrDefault()); @@ -111,8 +119,8 @@ public class HawkbitMcpToolProvider { } @McpTool(name = "list_rollouts", - description = "Retrieves a paged list of rollouts with optional RSQL filtering. " + - "Rollouts are used to deploy software to groups of targets.") + description = "Retrieves a paged list of rollouts with optional RSQL filtering. " + + "Rollouts are used to deploy software to groups of targets.") public PagedResponse listRollouts(final ListRequest request) { log.debug("Listing rollouts with rsql={}, offset={}, limit={}", request.rsql(), request.getOffsetOrDefault(), request.getLimitOrDefault()); @@ -129,8 +137,8 @@ public class HawkbitMcpToolProvider { } @McpTool(name = "list_distribution_sets", - description = "Retrieves a paged list of distribution sets with optional RSQL filtering. " + - "Distribution sets are software packages that can be deployed to targets.") + description = "Retrieves a paged list of distribution sets with optional RSQL filtering. " + + "Distribution sets are software packages that can be deployed to targets.") public PagedResponse listDistributionSets(final ListRequest request) { log.debug("Listing distribution sets with rsql={}, offset={}, limit={}", request.rsql(), request.getOffsetOrDefault(), request.getLimitOrDefault()); @@ -146,8 +154,8 @@ public class HawkbitMcpToolProvider { } @McpTool(name = "list_actions", - description = "Retrieves a paged list of actions with optional RSQL filtering. " + - "Actions represent deployment operations assigned to targets.") + description = "Retrieves a paged list of actions with optional RSQL filtering. " + + "Actions represent deployment operations assigned to targets.") public PagedResponse listActions(final ListRequest request) { log.debug("Listing actions with rsql={}, offset={}, limit={}", request.rsql(), request.getOffsetOrDefault(), request.getLimitOrDefault()); @@ -164,8 +172,8 @@ public class HawkbitMcpToolProvider { } @McpTool(name = "list_software_modules", - description = "Retrieves a paged list of software modules with optional RSQL filtering. " + - "Software modules are individual software components within distribution sets.") + description = "Retrieves a paged list of software modules with optional RSQL filtering. " + + "Software modules are individual software components within distribution sets.") public PagedResponse listSoftwareModules(final ListRequest request) { log.debug("Listing software modules with rsql={}, offset={}, limit={}", request.rsql(), request.getOffsetOrDefault(), request.getLimitOrDefault()); @@ -181,8 +189,8 @@ public class HawkbitMcpToolProvider { } @McpTool(name = "list_target_filters", - description = "Retrieves a paged list of target filter queries with optional RSQL filtering. " + - "Target filters define RSQL queries to group targets for rollouts or auto-assignment.") + description = "Retrieves a paged list of target filter queries with optional RSQL filtering. " + + "Target filters define RSQL queries to group targets for rollouts or auto-assignment.") public PagedResponse listTargetFilters(final ListRequest request) { log.debug("Listing target filters with rsql={}, offset={}, limit={}", request.rsql(), request.getOffsetOrDefault(), request.getLimitOrDefault()); @@ -199,305 +207,304 @@ public class HawkbitMcpToolProvider { } @McpTool(name = "manage_target", - description = "Create, update, or delete targets (devices). " + - "Operations: CREATE (new target with controllerId, name, description. When creating a target without a specific target type, set \"targetType\": null), " + - "UPDATE (modify existing target by controllerId), " + - "DELETE (remove target by controllerId). " + - "Use 'type' field to select operation: " + - "{\"type\":\"Create\",\"body\":{\"controllerId\":\"id\",\"name\":\"name\"}}, " + - "{\"type\":\"Update\",\"controllerId\":\"id\",\"body\":{...}}, " + - "{\"type\":\"Delete\",\"controllerId\":\"id\"}") + description = "Create, update, or delete targets (devices). " + + "Operations: CREATE (new target with controllerId, name, description. When creating a target without a specific target type, set \"targetType\": null), " + + "UPDATE (modify existing target by controllerId), " + + "DELETE (remove target by controllerId). " + + "Use 'type' field to select operation: " + + "{\"type\":\"Create\",\"body\":{\"controllerId\":\"id\",\"name\":\"name\"}}, " + + "{\"type\":\"Update\",\"controllerId\":\"id\",\"body\":{...}}, " + + "{\"type\":\"Delete\",\"controllerId\":\"id\"}") @SuppressWarnings("java:S3776") // not too complex public OperationResponse manageTarget(final TargetRequest request) { log.debug("Managing target: request={}", request.getClass().getSimpleName()); final MgmtTargetRestApi api = hawkbitClient.mgmtService(MgmtTargetRestApi.class, dummyTenant); - if (request instanceof TargetRequest.Create r) { + if (request instanceof TargetRequest.Create(MgmtTargetRequestBody body)) { validateOperation(OP_CREATE, TARGETS); - if (r.body() == null) { + if (body == null) { return OperationResponse.failure(OP_CREATE, "Request body is required for CREATE operation"); } - final ResponseEntity> response = api.createTargets(List.of(r.body())); + final ResponseEntity> response = api.createTargets(List.of(body)); final List created = response.getBody(); return OperationResponse.success(OP_CREATE, "Target created successfully", created != null && !created.isEmpty() ? created.get(0) : null); - } else if (request instanceof TargetRequest.Update r) { + } else if (request instanceof TargetRequest.Update(String controllerId, MgmtTargetRequestBody body)) { validateOperation(OP_UPDATE, TARGETS); - if (r.controllerId() == null || r.controllerId().isBlank()) { + if (controllerId == null || controllerId.isBlank()) { return OperationResponse.failure(OP_UPDATE, "controllerId is required for UPDATE operation"); } - if (r.body() == null) { + if (body == null) { return OperationResponse.failure(OP_UPDATE, "Request body is required for UPDATE operation"); } - final ResponseEntity response = api.updateTarget(r.controllerId(), r.body()); + final ResponseEntity response = api.updateTarget(controllerId, body); return OperationResponse.success(OP_UPDATE, "Target updated successfully", response.getBody()); - } else if (request instanceof TargetRequest.Delete r) { + } else if (request instanceof TargetRequest.Delete(String controllerId)) { validateOperation(OP_DELETE, TARGETS); - if (r.controllerId() == null || r.controllerId().isBlank()) { + if (controllerId == null || controllerId.isBlank()) { return OperationResponse.failure(OP_DELETE, "controllerId is required for DELETE operation"); } - api.deleteTarget(r.controllerId()); + api.deleteTarget(controllerId); return OperationResponse.success(OP_DELETE, "Target deleted successfully"); } throw new IllegalArgumentException("Unknown request type: " + request.getClass().getSimpleName()); } @McpTool(name = "manage_rollout", - description = "Create, update, delete, and control rollouts for software deployment. " + - "Use 'type' field to select operation. " + - "Types: Create, Update, Delete, Start, Pause, Stop, Resume, Approve, Deny, Retry, TriggerNextGroup. " + - "For Create: use rollout 'type' values: 'soft', 'forced', 'timeforced', 'downloadonly' (lowercase). " + - "If 'groups' list is provided, omit 'amountGroups' (they are mutually exclusive). " + - "Examples: {\"type\":\"Create\",\"body\":{...}}, " + - "{\"type\":\"Start\",\"rolloutId\":123}, " + - "{\"type\":\"Approve\",\"rolloutId\":123,\"remark\":\"approved\"}") + description = "Create, update, delete, and control rollouts for software deployment. " + + "Use 'type' field to select operation. " + + "Types: Create, Update, Delete, Start, Pause, Stop, Resume, Approve, Deny, Retry, TriggerNextGroup. " + + "For Create: use rollout 'type' values: 'soft', 'forced', 'timeforced', 'downloadonly' (lowercase). " + + "If 'groups' list is provided, omit 'amountGroups' (they are mutually exclusive). " + + "Examples: {\"type\":\"Create\",\"body\":{...}}, " + + "{\"type\":\"Start\",\"rolloutId\":123}, " + + "{\"type\":\"Approve\",\"rolloutId\":123,\"remark\":\"approved\"}") @SuppressWarnings("java:S3776") // not too complex, iterative logic public OperationResponse manageRollout(final RolloutRequest request) { log.debug("Managing rollout: request={}", request.getClass().getSimpleName()); final MgmtRolloutRestApi api = hawkbitClient.mgmtService(MgmtRolloutRestApi.class, dummyTenant); - if (request instanceof RolloutRequest.Create r) { + if (request instanceof RolloutRequest.Create(MgmtRolloutRestRequestBodyPost body)) { validateRolloutOperation(OP_CREATE); - if (r.body() == null) { + if (body == null) { return OperationResponse.failure(OP_CREATE, BODY_IS_REQUIRED_FOR_CREATE_OPERATION); } - final ResponseEntity response = api.create(r.body()); + final ResponseEntity response = api.create(body); return OperationResponse.success(OP_CREATE, "Rollout created successfully", response.getBody()); - } else if (request instanceof RolloutRequest.Update r) { + } else if (request instanceof RolloutRequest.Update(Long rolloutId, MgmtRolloutRestRequestBodyPut body)) { validateRolloutOperation("update"); - if (r.rolloutId() == null) { + if (rolloutId == null) { return OperationResponse.failure(OP_UPDATE, "rolloutId is required for UPDATE operation"); } - if (r.body() == null) { + if (body == null) { return OperationResponse.failure(OP_UPDATE, BODY_IS_REQUIRED_FOR_UPDATE_OPERATION); } - final ResponseEntity response = api.update(r.rolloutId(), r.body()); + final ResponseEntity response = api.update(rolloutId, body); return OperationResponse.success(OP_UPDATE, "Rollout updated successfully", response.getBody()); - } else if (request instanceof RolloutRequest.Delete r) { + } else if (request instanceof RolloutRequest.Delete(Long rolloutId)) { validateRolloutOperation(OP_DELETE); - if (r.rolloutId() == null) { + if (rolloutId == null) { return OperationResponse.failure(OP_DELETE, "rolloutId is required for DELETE operation"); } - api.delete(r.rolloutId()); + api.delete(rolloutId); return OperationResponse.success(OP_DELETE, "Rollout deleted successfully"); - } else if (request instanceof RolloutRequest.Start r) { + } else if (request instanceof RolloutRequest.Start(Long rolloutId)) { validateRolloutOperation("start"); - if (r.rolloutId() == null) { + if (rolloutId == null) { return OperationResponse.failure(OP_START, "rolloutId is required for START operation"); } - api.start(r.rolloutId()); + api.start(rolloutId); return OperationResponse.success(OP_START, "Rollout started successfully"); - } else if (request instanceof RolloutRequest.Pause r) { + } else if (request instanceof RolloutRequest.Pause(Long rolloutId)) { validateRolloutOperation("pause"); - if (r.rolloutId() == null) { + if (rolloutId == null) { return OperationResponse.failure(OP_PAUSE, "rolloutId is required for PAUSE operation"); } - api.pause(r.rolloutId()); + api.pause(rolloutId); return OperationResponse.success(OP_PAUSE, "Rollout paused successfully"); - } else if (request instanceof RolloutRequest.Stop r) { + } else if (request instanceof RolloutRequest.Stop(Long rolloutId)) { validateRolloutOperation("stop"); - if (r.rolloutId() == null) { + if (rolloutId == null) { return OperationResponse.failure(OP_STOP, "rolloutId is required for STOP operation"); } - api.stop(r.rolloutId()); + api.stop(rolloutId); return OperationResponse.success(OP_STOP, "Rollout stopped successfully"); - } else if (request instanceof RolloutRequest.Resume r) { + } else if (request instanceof RolloutRequest.Resume(Long rolloutId)) { validateRolloutOperation("resume"); - if (r.rolloutId() == null) { + if (rolloutId == null) { return OperationResponse.failure(OP_RESUME, "rolloutId is required for RESUME operation"); } - api.resume(r.rolloutId()); + api.resume(rolloutId); return OperationResponse.success(OP_RESUME, "Rollout resumed successfully"); - } else if (request instanceof RolloutRequest.Approve r) { + } else if (request instanceof RolloutRequest.Approve(Long rolloutId, String remark)) { validateRolloutOperation("approve"); - if (r.rolloutId() == null) { + if (rolloutId == null) { return OperationResponse.failure(OP_APPROVE, "rolloutId is required for APPROVE operation"); } - api.approve(r.rolloutId(), r.remark()); + api.approve(rolloutId, remark); return OperationResponse.success(OP_APPROVE, "Rollout approved successfully"); - } else if (request instanceof RolloutRequest.Deny r) { + } else if (request instanceof RolloutRequest.Deny(Long rolloutId, String remark)) { validateRolloutOperation("deny"); - if (r.rolloutId() == null) { + if (rolloutId == null) { return OperationResponse.failure(OP_DENY, "rolloutId is required for DENY operation"); } - api.deny(r.rolloutId(), r.remark()); + api.deny(rolloutId, remark); return OperationResponse.success(OP_DENY, "Rollout denied successfully"); - } else if (request instanceof RolloutRequest.Retry r) { + } else if (request instanceof RolloutRequest.Retry(Long rolloutId)) { validateRolloutOperation("retry"); - if (r.rolloutId() == null) { + if (rolloutId == null) { return OperationResponse.failure(OP_RETRY, "rolloutId is required for RETRY operation"); } - final ResponseEntity response = api.retryRollout(r.rolloutId()); + final ResponseEntity response = api.retryRollout(rolloutId); return OperationResponse.success(OP_RETRY, "Rollout retry created successfully", response.getBody()); - } else if (request instanceof RolloutRequest.TriggerNextGroup r) { + } else if (request instanceof RolloutRequest.TriggerNextGroup(Long rolloutId)) { validateRolloutOperation("trigger-next-group"); - if (r.rolloutId() == null) { + if (rolloutId == null) { return OperationResponse.failure(OP_TRIGGER_NEXT_GROUP, "rolloutId is required for TRIGGER_NEXT_GROUP operation"); } - api.triggerNextGroup(r.rolloutId()); + api.triggerNextGroup(rolloutId); return OperationResponse.success(OP_TRIGGER_NEXT_GROUP, "Next rollout group triggered successfully"); } throw new IllegalArgumentException("Unknown request type: " + request.getClass().getSimpleName()); } @McpTool(name = "manage_distribution_set", - description = "Create, update, or delete distribution sets (software packages). " + - "Use 'type' field to select operation: " + - "{\"type\":\"Create\",\"body\":{\"name\":\"n\",\"version\":\"v\",\"type\":\"t\"}}, " + - "{\"type\":\"Update\",\"distributionSetId\":123,\"body\":{...}}, " + - "{\"type\":\"Delete\",\"distributionSetId\":123}") + description = "Create, update, or delete distribution sets (software packages). " + + "Use 'type' field to select operation: " + + "{\"type\":\"Create\",\"body\":{\"name\":\"n\",\"version\":\"v\",\"type\":\"t\"}}, " + + "{\"type\":\"Update\",\"distributionSetId\":123,\"body\":{...}}, " + + "{\"type\":\"Delete\",\"distributionSetId\":123}") public OperationResponse manageDistributionSet(final DistributionSetRequest request) { log.debug("Managing distribution set: request={}", request.getClass().getSimpleName()); final MgmtDistributionSetRestApi api = hawkbitClient.mgmtService(MgmtDistributionSetRestApi.class, dummyTenant); - if (request instanceof DistributionSetRequest.Create r) { + if (request instanceof DistributionSetRequest.Create(MgmtDistributionSetRequestBodyPost body)) { validateOperation(OP_CREATE, DISTRIBUTION_SETS); - if (r.body() == null) { + if (body == null) { return OperationResponse.failure(OP_CREATE, BODY_IS_REQUIRED_FOR_CREATE_OPERATION); } - final ResponseEntity> response = api.createDistributionSets(List.of(r.body())); + final ResponseEntity> response = api.createDistributionSets(List.of(body)); final List created = response.getBody(); return OperationResponse.success(OP_CREATE, "Distribution set created successfully", created != null && !created.isEmpty() ? created.get(0) : null); - } else if (request instanceof DistributionSetRequest.Update r) { + } else if (request instanceof DistributionSetRequest.Update(Long distributionSetId, MgmtDistributionSetRequestBodyPut body)) { validateOperation(OP_UPDATE, DISTRIBUTION_SETS); - if (r.distributionSetId() == null) { + if (distributionSetId == null) { return OperationResponse.failure(OP_UPDATE, "distributionSetId is required for UPDATE operation"); } - if (r.body() == null) { + if (body == null) { return OperationResponse.failure(OP_UPDATE, BODY_IS_REQUIRED_FOR_UPDATE_OPERATION); } - final ResponseEntity response = api.updateDistributionSet(r.distributionSetId(), r.body()); + final ResponseEntity response = api.updateDistributionSet(distributionSetId, body); return OperationResponse.success(OP_UPDATE, "Distribution set updated successfully", response.getBody()); - } else if (request instanceof DistributionSetRequest.Delete r) { + } else if (request instanceof DistributionSetRequest.Delete(Long distributionSetId)) { validateOperation(OP_DELETE, DISTRIBUTION_SETS); - if (r.distributionSetId() == null) { + if (distributionSetId == null) { return OperationResponse.failure(OP_DELETE, "distributionSetId is required for DELETE operation"); } - api.deleteDistributionSet(r.distributionSetId()); + api.deleteDistributionSet(distributionSetId); return OperationResponse.success(OP_DELETE, "Distribution set deleted successfully"); } throw new IllegalArgumentException("Unknown request type: " + request.getClass().getSimpleName()); } @McpTool(name = "manage_action", - description = "Delete deployment actions. Actions are created indirectly via distribution set assignment. " + - "Use 'type' field to select operation: " + - "{\"type\":\"Delete\",\"actionIds\":[123]}, " + - "{\"type\":\"DeleteBatch\",\"actionIds\":[1,2,3],\"rsql\":\"\"}") + description = "Delete deployment actions. Actions are created indirectly via distribution set assignment. " + + "Use 'type' field to select operation: " + + "{\"type\":\"Delete\",\"actionIds\":[123]}, " + + "{\"type\":\"DeleteBatch\",\"actionIds\":[1,2,3],\"rsql\":\"\"}") public OperationResponse manageAction(final ActionRequest request) { log.debug("Managing action: request={}", request.getClass().getSimpleName()); final MgmtActionRestApi api = hawkbitClient.mgmtService(MgmtActionRestApi.class, dummyTenant); - if (request instanceof ActionRequest.Delete r) { + if (request instanceof ActionRequest.Delete(Long actionId)) { validateActionOperation(OP_DELETE); - if (r.actionId() == null) { + if (actionId == null) { return OperationResponse.failure(OP_DELETE, "actionId is required for DELETE operation"); } - api.deleteAction(r.actionId()); + api.deleteAction(actionId); return OperationResponse.success(OP_DELETE, "Action deleted successfully"); - } else if (request instanceof ActionRequest.DeleteBatch r) { + } else if (request instanceof ActionRequest.DeleteBatch(List actionIds, String rsql)) { validateActionOperation("delete-batch"); - if ((r.actionIds() == null || r.actionIds().isEmpty()) && - (r.rsql() == null || r.rsql().isBlank())) { + if ((actionIds == null || actionIds.isEmpty()) && + (rsql == null || rsql.isBlank())) { return OperationResponse.failure(OP_DELETE_BATCH, "Either actionIds or rsql is required for DELETE_BATCH operation"); } - api.deleteActions(r.rsql(), r.actionIds()); + api.deleteActions(rsql, actionIds); return OperationResponse.success(OP_DELETE_BATCH, "Actions deleted successfully"); } throw new IllegalArgumentException("Unknown request type: " + request.getClass().getSimpleName()); } @McpTool(name = "manage_software_module", - description = "Create, update, or delete software modules. " + - "Use 'type' field to select operation: " + - "{\"type\":\"Create\",\"body\":{\"name\":\"n\",\"version\":\"v\",\"type\":\"t\"}}, " + - "{\"type\":\"Update\",\"softwareModuleId\":123,\"body\":{...}}, " + - "{\"type\":\"Delete\",\"softwareModuleId\":123}") + description = "Create, update, or delete software modules. " + + "Use 'type' field to select operation: " + + "{\"type\":\"Create\",\"body\":{\"name\":\"n\",\"version\":\"v\",\"type\":\"t\"}}, " + + "{\"type\":\"Update\",\"softwareModuleId\":123,\"body\":{...}}, " + + "{\"type\":\"Delete\",\"softwareModuleId\":123}") public OperationResponse manageSoftwareModule(final SoftwareModuleRequest request) { log.debug("Managing software module: request={}", request.getClass().getSimpleName()); final MgmtSoftwareModuleRestApi api = hawkbitClient.mgmtService(MgmtSoftwareModuleRestApi.class, dummyTenant); - if (request instanceof SoftwareModuleRequest.Create r) { + if (request instanceof SoftwareModuleRequest.Create(MgmtSoftwareModuleRequestBodyPost body)) { validateOperation(OP_CREATE, SOFTWARE_MODULES); - if (r.body() == null) { + if (body == null) { return OperationResponse.failure(OP_CREATE, BODY_IS_REQUIRED_FOR_CREATE_OPERATION); } - final ResponseEntity> response = api.createSoftwareModules(List.of(r.body())); + final ResponseEntity> response = api.createSoftwareModules(List.of(body)); final List created = response.getBody(); return OperationResponse.success(OP_CREATE, "Software module created successfully", created != null && !created.isEmpty() ? created.get(0) : null); - } else if (request instanceof SoftwareModuleRequest.Update r) { + } else if (request instanceof SoftwareModuleRequest.Update(Long softwareModuleId, MgmtSoftwareModuleRequestBodyPut body)) { validateOperation(OP_UPDATE, SOFTWARE_MODULES); - if (r.softwareModuleId() == null) { + if (softwareModuleId == null) { return OperationResponse.failure(OP_UPDATE, "softwareModuleId is required for UPDATE operation"); } - if (r.body() == null) { + if (body == null) { return OperationResponse.failure(OP_UPDATE, BODY_IS_REQUIRED_FOR_UPDATE_OPERATION); } - final ResponseEntity response = api.updateSoftwareModule(r.softwareModuleId(), r.body()); + final ResponseEntity response = api.updateSoftwareModule(softwareModuleId, body); return OperationResponse.success(OP_UPDATE, "Software module updated successfully", response.getBody()); - } else if (request instanceof SoftwareModuleRequest.Delete r) { + } else if (request instanceof SoftwareModuleRequest.Delete(Long softwareModuleId)) { validateOperation(OP_DELETE, SOFTWARE_MODULES); - if (r.softwareModuleId() == null) { + if (softwareModuleId == null) { return OperationResponse.failure(OP_DELETE, "softwareModuleId is required for DELETE operation"); } - api.deleteSoftwareModule(r.softwareModuleId()); + api.deleteSoftwareModule(softwareModuleId); return OperationResponse.success(OP_DELETE, "Software module deleted successfully"); } throw new IllegalArgumentException("Unknown request type: " + request.getClass().getSimpleName()); } @McpTool(name = "manage_target_filter", - description = "Create, update, or delete target filter queries. " + - "Use 'type' field to select operation: " + - "{\"type\":\"Create\",\"body\":{\"name\":\"n\",\"query\":\"name==*\"}}, " + - "{\"type\":\"Update\",\"filterId\":123,\"body\":{...}}, " + - "{\"type\":\"Delete\",\"filterId\":123}") + description = "Create, update, or delete target filter queries. " + + "Use 'type' field to select operation: " + + "{\"type\":\"Create\",\"body\":{\"name\":\"n\",\"query\":\"name==*\"}}, " + + "{\"type\":\"Update\",\"filterId\":123,\"body\":{...}}, " + + "{\"type\":\"Delete\",\"filterId\":123}") public OperationResponse manageTargetFilter(final TargetFilterRequest request) { log.debug("Managing target filter: request={}", request.getClass().getSimpleName()); final MgmtTargetFilterQueryRestApi api = hawkbitClient.mgmtService(MgmtTargetFilterQueryRestApi.class, dummyTenant); - if (request instanceof TargetFilterRequest.Create r) { + if (request instanceof TargetFilterRequest.Create(MgmtTargetFilterQueryRequestBody body)) { validateOperation(OP_CREATE, TARGET_FILTERS); - if (r.body() == null) { + if (body == null) { return OperationResponse.failure(OP_CREATE, BODY_IS_REQUIRED_FOR_CREATE_OPERATION); } - final ResponseEntity response = api.createFilter(r.body()); + final ResponseEntity response = api.createFilter(body); return OperationResponse.success(OP_CREATE, "Target filter created successfully", response.getBody()); - } else if (request instanceof TargetFilterRequest.Update r) { + } else if (request instanceof TargetFilterRequest.Update(Long filterId, MgmtTargetFilterQueryRequestBody body)) { validateOperation(OP_UPDATE, TARGET_FILTERS); - if (r.filterId() == null) { + if (filterId == null) { return OperationResponse.failure(OP_UPDATE, "filterId is required for UPDATE operation"); } - if (r.body() == null) { + if (body == null) { return OperationResponse.failure(OP_UPDATE, BODY_IS_REQUIRED_FOR_UPDATE_OPERATION); } - final ResponseEntity response = api.updateFilter(r.filterId(), r.body()); + final ResponseEntity response = api.updateFilter(filterId, body); return OperationResponse.success(OP_UPDATE, "Target filter updated successfully", response.getBody()); - } else if (request instanceof TargetFilterRequest.Delete r) { + } else if (request instanceof TargetFilterRequest.Delete(Long filterId)) { validateOperation(OP_DELETE, TARGET_FILTERS); - if (r.filterId() == null) { + if (filterId == null) { return OperationResponse.failure(OP_DELETE, "filterId is required for DELETE operation"); } - api.deleteFilter(r.filterId()); + api.deleteFilter(filterId); return OperationResponse.success(OP_DELETE, "Target filter deleted successfully"); } throw new IllegalArgumentException("Unknown request type: " + request.getClass().getSimpleName()); } - private void validateOperation(final String operation, final String entity) { if (!isOperationEnabled(operation, entity)) { throw new IllegalArgumentException( "Operation " + operation.toUpperCase() + " is not enabled for " + entity + - ". Check hawkbit.mcp.operations configuration."); + ". Check hawkbit.mcp.operations configuration."); } } @@ -510,7 +517,7 @@ public class HawkbitMcpToolProvider { if (!properties.getOperations().isGlobalOperationEnabled(operation)) { throw new IllegalArgumentException( "Operation " + operation.toUpperCase() + " is not enabled for rollouts. " + - "Check hawkbit.mcp.operations configuration."); + "Check hawkbit.mcp.operations configuration."); } return; } @@ -518,7 +525,7 @@ public class HawkbitMcpToolProvider { if (!entitySetting) { throw new IllegalArgumentException( "Operation " + operation.toUpperCase() + " is not enabled for rollouts. " + - "Check hawkbit.mcp.operations configuration."); + "Check hawkbit.mcp.operations configuration."); } } @@ -530,7 +537,7 @@ public class HawkbitMcpToolProvider { if (operation.equals("delete") && !properties.getOperations().isGlobalOperationEnabled(OP_DELETE)) { throw new IllegalArgumentException( "Operation " + operation.toUpperCase() + " is not enabled for actions. " + - "Check hawkbit.mcp.operations configuration."); + "Check hawkbit.mcp.operations configuration."); } return; } @@ -538,7 +545,7 @@ public class HawkbitMcpToolProvider { if (!entitySetting) { throw new IllegalArgumentException( "Operation " + operation.toUpperCase() + " is not enabled for actions. " + - "Check hawkbit.mcp.operations configuration."); + "Check hawkbit.mcp.operations configuration."); } } diff --git a/hawkbit-ql-jpa/src/main/java/org/eclipse/hawkbit/ql/EntityMatcher.java b/hawkbit-ql-jpa/src/main/java/org/eclipse/hawkbit/ql/EntityMatcher.java index 90b3cb7f3..8a5489700 100644 --- a/hawkbit-ql-jpa/src/main/java/org/eclipse/hawkbit/ql/EntityMatcher.java +++ b/hawkbit-ql-jpa/src/main/java/org/eclipse/hawkbit/ql/EntityMatcher.java @@ -60,85 +60,87 @@ public class EntityMatcher { @SuppressWarnings({ "java:S3776", "java:S3358", "java:S1125", "java:S6541" }) // better readable this way private boolean match(final T t, final Node node) { - if (node instanceof Node.Comparison comparison) { - final String[] split = comparison.getKey().split("\\.", 2); - try { - final Getter fieldGetter = getGetter(t.getClass(), split[0]); - final Object fieldValue = fieldGetter.get(t); - final Operator op = comparison.getOp(); - if (Map.class.isAssignableFrom(getReturnType(fieldGetter))) { - if ((op == NE || op == NOT_IN || op == NOT_LIKE) - && (fieldValue == null || !((Map) fieldValue).containsKey(split[1]))) { - // TODO / recheck - when missing entity shall it be included or not in != or =out=? - now it's not - return false; - } - return compareIgnoreCaseAware( - fieldValue == null ? null : ((Map) fieldValue).get(split[1]), - op, - map( - comparison.getValue(), - (Class) ((ParameterizedType) fieldGetter.type()).getActualTypeArguments()[1])); - } else if (Collection.class.isAssignableFrom(getReturnType(fieldGetter))) { // Set / List - final Object value; - final BiPredicate compare; - if (split.length == 1) { - value = map(comparison.getValue(), getReturnType(fieldGetter)); - compare = (e, operator) -> compareIgnoreCaseAware(e, operator, value); - } else { - final Getter valueGetter = getGetter( - (Class) ((ParameterizedType) fieldGetter.type()).getActualTypeArguments()[0], split[1]); - value = map(comparison.getValue(), getReturnType(valueGetter)); - compare = (e, operator) -> { - try { - return compareIgnoreCaseAware( - map(e == null ? null : valueGetter.get(e), getReturnType(valueGetter)), operator, value); - } catch (final IllegalAccessException | InvocationTargetException ex) { - throw new IllegalArgumentException(ex); - } - }; - } - final Collection set = (Collection) fieldValue; - return switch (op) { - case EQ, GT, GTE, LT, LTE, IN, LIKE -> set == null - ? false - : set.stream().anyMatch(e -> compare.test(e, op)); - case NE, NOT_IN, NOT_LIKE -> set == null - ? true - : set.stream().noneMatch(e -> compare.test(e, op == NE ? EQ : op == NOT_IN ? IN : LIKE)); - }; - } else { - if (split.length == 1) { - return compareIgnoreCaseAware(fieldValue, op, map(comparison.getValue(), getReturnType(fieldGetter))); - } else { - if (split[1].contains(".")) { - // nested field access - final String[] nestedSplit = split[1].split("\\.", 2); - final Getter nestedFieldGetter = getGetter(getReturnType(fieldGetter), nestedSplit[0]); - final Getter valueGetter = getGetter(getReturnType(nestedFieldGetter), nestedSplit[1]); - final Object nestedFieldValue = fieldValue == null ? null : nestedFieldGetter.get(fieldValue); - return compareIgnoreCaseAware( - nestedFieldValue == null ? null : valueGetter.get(nestedFieldValue), - op, - map(comparison.getValue(), getReturnType(valueGetter))); + switch (node) { + case Node.Comparison comparison -> { + final String[] split = comparison.getKey().split("\\.", 2); + try { + final Getter fieldGetter = getGetter(t.getClass(), split[0]); + final Object fieldValue = fieldGetter.get(t); + final Operator op = comparison.getOp(); + if (Map.class.isAssignableFrom(getReturnType(fieldGetter))) { + if ((op == NE || op == NOT_IN || op == NOT_LIKE) + && (fieldValue == null || !((Map) fieldValue).containsKey(split[1]))) { + // TODO / recheck - when missing entity shall it be included or not in != or =out=? - now it's not + return false; + } + return compareIgnoreCaseAware( + fieldValue == null ? null : ((Map) fieldValue).get(split[1]), + op, + map( + comparison.getValue(), + (Class) ((ParameterizedType) fieldGetter.type()).getActualTypeArguments()[1])); + } else if (Collection.class.isAssignableFrom(getReturnType(fieldGetter))) { // Set / List + final Object value; + final BiPredicate compare; + if (split.length == 1) { + value = map(comparison.getValue(), getReturnType(fieldGetter)); + compare = (e, operator) -> compareIgnoreCaseAware(e, operator, value); } else { - final Getter valueGetter = getGetter(getReturnType(fieldGetter), split[1]); - return compareIgnoreCaseAware( - fieldValue == null ? null : valueGetter.get(fieldValue), - op, - map(comparison.getValue(), getReturnType(valueGetter))); + final Getter valueGetter = getGetter( + (Class) ((ParameterizedType) fieldGetter.type()).getActualTypeArguments()[0], split[1]); + value = map(comparison.getValue(), getReturnType(valueGetter)); + compare = (e, operator) -> { + try { + return compareIgnoreCaseAware( + map(e == null ? null : valueGetter.get(e), getReturnType(valueGetter)), operator, value); + } catch (final IllegalAccessException | InvocationTargetException ex) { + throw new IllegalArgumentException(ex); + } + }; + } + final Collection set = (Collection) fieldValue; + return switch (op) { + case EQ, GT, GTE, LT, LTE, IN, LIKE -> set == null + ? false + : set.stream().anyMatch(e -> compare.test(e, op)); + case NE, NOT_IN, NOT_LIKE -> set == null + ? true + : set.stream().noneMatch(e -> compare.test(e, op == NE ? EQ : op == NOT_IN ? IN : LIKE)); + }; + } else { + if (split.length == 1) { + return compareIgnoreCaseAware(fieldValue, op, map(comparison.getValue(), getReturnType(fieldGetter))); + } else { + if (split[1].contains(".")) { + // nested field access + final String[] nestedSplit = split[1].split("\\.", 2); + final Getter nestedFieldGetter = getGetter(getReturnType(fieldGetter), nestedSplit[0]); + final Getter valueGetter = getGetter(getReturnType(nestedFieldGetter), nestedSplit[1]); + final Object nestedFieldValue = fieldValue == null ? null : nestedFieldGetter.get(fieldValue); + return compareIgnoreCaseAware( + nestedFieldValue == null ? null : valueGetter.get(nestedFieldValue), + op, + map(comparison.getValue(), getReturnType(valueGetter))); + } else { + final Getter valueGetter = getGetter(getReturnType(fieldGetter), split[1]); + return compareIgnoreCaseAware( + fieldValue == null ? null : valueGetter.get(fieldValue), + op, + map(comparison.getValue(), getReturnType(valueGetter))); + } } } + } catch (final NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + throw new IllegalArgumentException(e); } - } catch (final NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { - throw new IllegalArgumentException(e); } - } else if (node instanceof Node.Logical logical) { - return switch (logical.getOp()) { - case AND -> logical.getChildren().stream().allMatch(child -> match(t, child)); - case OR -> logical.getChildren().stream().anyMatch(child -> match(t, child)); - }; - } else { - throw new IllegalArgumentException("Unsupported node type: " + node.getClass()); + case Node.Logical logical -> { + return switch (logical.getOp()) { + case AND -> logical.getChildren().stream().allMatch(child -> match(t, child)); + case OR -> logical.getChildren().stream().anyMatch(child -> match(t, child)); + }; + } + default -> throw new IllegalArgumentException("Unsupported node type: " + node.getClass()); } } @@ -151,13 +153,11 @@ public class EntityMatcher { return o; } // if here - ignoreCase in true and we have non-null value - if (o instanceof String str) { - return str.toLowerCase(); - } else if (o instanceof Collection collection) { - return collection.stream().map(this::ignoreCase).toList(); - } else { - return o; - } + return switch (o) { + case String str -> str.toLowerCase(); + case Collection collection -> collection.stream().map(this::ignoreCase).toList(); + default -> o; + }; } // java:S3011 uses reflection to private members anyway diff --git a/hawkbit-ql-jpa/src/main/java/org/eclipse/hawkbit/ql/jpa/SpecificationBuilder.java b/hawkbit-ql-jpa/src/main/java/org/eclipse/hawkbit/ql/jpa/SpecificationBuilder.java index 888807316..ea4cd57af 100644 --- a/hawkbit-ql-jpa/src/main/java/org/eclipse/hawkbit/ql/jpa/SpecificationBuilder.java +++ b/hawkbit-ql-jpa/src/main/java/org/eclipse/hawkbit/ql/jpa/SpecificationBuilder.java @@ -105,29 +105,33 @@ public class SpecificationBuilder { } public Predicate build(final Node node) { - if (node instanceof Comparison comparison) { - return predicate(comparison); - } else if (node instanceof Logical logical) { - final Logical.Operator op = Objects.requireNonNull(logical.getOp()); - if (op == Logical.Operator.AND) { - return cb.and(logical.getChildren().stream() - .map(this::build) - .toList() - .toArray(PREDICATES_ARRAY_0)); - } else if (op == Logical.Operator.OR) { - final Map state = pathResolver.getState(); - return cb.or(logical.getChildren().stream() - .map(child -> { - pathResolver.reset(state); - return build(child); // for or path resolver joins could be reused - }) - .toList() - .toArray(PREDICATES_ARRAY_0)); - } else { - throw new IllegalArgumentException("Unsupported logical operator: " + op); + switch (node) { + case Comparison comparison -> { + return predicate(comparison); } - } else { - throw new IllegalArgumentException("Unsupported node type: " + node.getClass()); + case Logical logical -> { + final Logical.Operator op = Objects.requireNonNull(logical.getOp()); + switch (op) { + case Logical.Operator.AND -> { + return cb.and(logical.getChildren().stream() + .map(this::build) + .toList() + .toArray(PREDICATES_ARRAY_0)); + } + case Logical.Operator.OR -> { + final Map state = pathResolver.getState(); + return cb.or(logical.getChildren().stream() + .map(child -> { + pathResolver.reset(state); + return build(child); // for or path resolver joins could be reused + }) + .toList() + .toArray(PREDICATES_ARRAY_0)); + } + default -> throw new IllegalArgumentException("Unsupported logical operator: " + op); + } + } + default -> throw new IllegalArgumentException("Unsupported node type: " + node.getClass()); } } diff --git a/hawkbit-repository/hawkbit-repository-jpa-api/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/ExceptionMapper.java b/hawkbit-repository/hawkbit-repository-jpa-api/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/ExceptionMapper.java index 3f476fad4..c79f4fdc7 100644 --- a/hawkbit-repository/hawkbit-repository-jpa-api/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/ExceptionMapper.java +++ b/hawkbit-repository/hawkbit-repository-jpa-api/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/ExceptionMapper.java @@ -36,7 +36,7 @@ import org.springframework.transaction.TransactionSystemException; @Slf4j public class ExceptionMapper { - private static final Map EXCEPTION_MAPPING = new HashMap<>(4); + private static final Map EXCEPTION_MAPPING = HashMap.newHashMap(4); // this is required to enable a certain order of exception and to select the most specific mappable exception according to the type // hierarchy of the exception diff --git a/hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaConfiguration.java b/hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaConfiguration.java index d0e48b6c2..eb47e7ddf 100644 --- a/hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaConfiguration.java +++ b/hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaConfiguration.java @@ -81,7 +81,7 @@ public class JpaConfiguration extends JpaBaseConfiguration { @Override protected Map getVendorProperties(final DataSource dataSource) { - final Map properties = new HashMap<>(7); + final Map properties = HashMap.newHashMap(7); // Turn off dynamic weaving to disable LTW lookup in static weaving mode properties.put(PersistenceUnitProperties.WEAVING, "false"); // needed for reports diff --git a/hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java b/hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java index 2b1d155d5..65cb0b454 100644 --- a/hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java +++ b/hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java @@ -34,6 +34,7 @@ import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedBy; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; +import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; /** @@ -154,13 +155,13 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity { return false; } final BaseEntity other = (BaseEntity) obj; - final Long id = getId(); + final Long thisId = getId(); final Long otherId = other.getId(); - if (id == null) { + if (thisId == null) { if (otherId != null) { return false; } - } else if (!id.equals(otherId)) { + } else if (!thisId.equals(otherId)) { return false; } return getOptLockRevision() == other.getOptLockRevision(); @@ -198,9 +199,9 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity { } protected boolean isController() { - return SecurityContextHolder.getContext().getAuthentication() != null && - SecurityContextHolder.getContext().getAuthentication().getDetails() - instanceof TenantAwareAuthenticationDetails tenantAwareDetails && - tenantAwareDetails.controller(); + final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + return authentication != null + && authentication.getDetails() instanceof TenantAwareAuthenticationDetails tenantAwareDetails + && tenantAwareDetails.controller(); } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java index fd50889da..6529b8ad7 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java @@ -678,7 +678,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont log.debug("{} events in flushUpdateQueue.", size); - final Set events = new HashSet<>(queue.size()); + final Set events = HashSet.newHashSet(queue.size()); final int drained = queue.drainTo(events); if (drained <= 0) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/StatisticsUtils.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/StatisticsUtils.java index cc23dbab1..f5487e150 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/StatisticsUtils.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/StatisticsUtils.java @@ -68,12 +68,12 @@ public class StatisticsUtils { final Meter.Id id = m.getId(); if (id.getName().startsWith(Statistics.METER_PREFIX)) { final double value; - if (m instanceof Counter counter) { - value = counter.count(); - } else if (m instanceof FunctionCounter functionCounter) { - value = functionCounter.count(); - } else { - return; + switch (m) { + case Counter counter -> value = counter.count(); + case FunctionCounter functionCounter -> value = functionCounter.count(); + default -> { + return; + } } final StringBuilder key = new StringBuilder(id.getName()); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/view/TargetView.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/view/TargetView.java index 9c7470c36..6a0af2b53 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/view/TargetView.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/view/TargetView.java @@ -255,9 +255,8 @@ public final class TargetView extends TableView } private static List listFilters(HawkbitMgmtClient hawkbitClient) { - return Optional.ofNullable(hawkbitClient.getTargetFilterQueryRestApi() - .getFilters(null, 0, 30, null, null).getBody()) - .map(PagedList::getContent) + return Optional.ofNullable(hawkbitClient.getTargetFilterQueryRestApi().getFilters(null, 0, 30, null, null).getBody()) + .map(PagedList::getContent) .orElseGet(List::of); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/view/util/Filter.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/view/util/Filter.java index f15356bef..88bfdff9f 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/view/util/Filter.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/view/util/Filter.java @@ -149,18 +149,18 @@ public final class Filter extends Div { return null; } - if (value instanceof Collection coll) { - final StringBuilder sb = new StringBuilder(); - coll.stream().forEach(next -> sb.append(key).append("==").append(next).append(',')); - return sb.substring(0, sb.length() - 1); - } else if (value instanceof Optional opt) { - if (opt.isEmpty()) { - return null; - } else { - return key + "==" + opt.get(); + switch (value) { + case Collection coll -> { + final StringBuilder sb = new StringBuilder(); + coll.stream().forEach(next -> sb.append(key).append("==").append(next).append(',')); + return sb.substring(0, sb.length() - 1); + } + case Optional opt -> { + return opt.map(o -> key + "==" + o).orElse(null); + } + default -> { + return key + "==" + value; } - } else { - return key + "==" + value; } }