diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/GenericSpServerException.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/GenericSpServerException.java index 1f64ff7ad..aa84a19d0 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/GenericSpServerException.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/GenericSpServerException.java @@ -11,10 +11,15 @@ package org.eclipse.hawkbit.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; + /** * {@link GenericSpServerException} is thrown when a given entity in's actual and cannot be stored within the current session. Reason could be * that it has been changed within another session. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class GenericSpServerException extends AbstractServerRtException { @Serial diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/utils/ObjectCopyUtil.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/utils/ObjectCopyUtil.java new file mode 100644 index 000000000..16d91e6b3 --- /dev/null +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/utils/ObjectCopyUtil.java @@ -0,0 +1,251 @@ +/** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.utils; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.BiConsumer; +import java.util.function.UnaryOperator; + +import jakarta.validation.constraints.NotNull; + +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = lombok.AccessLevel.PRIVATE) +public class ObjectCopyUtil { + + private static final Map FROM_TO_SETTER = new HashMap<>(); + + // java:S4276 - it is intended to be generic - not specialized + @SuppressWarnings("java:S4276") + public static boolean copy(final Object from, final Object to, boolean setNullValues, final UnaryOperator propertyProcessor) { + final FromTo fromTo = new FromTo(from.getClass(), to.getClass()); + CopyFunction fromToFunction; + synchronized (FROM_TO_SETTER) { + fromToFunction = FROM_TO_SETTER.get(fromTo); + if (fromToFunction == null) { + fromToFunction = fromToFunction(from.getClass(), to.getClass()); + FROM_TO_SETTER.put(fromTo, fromToFunction); + } + } + return fromToFunction.apply(from, to, setNullValues, propertyProcessor); + } + + // java:S4276 - it is intended to be generic - not specialized + // java:S3776 - complexity is due to reflection and dynamic method invocation + // java:S1141 - better readable that way + // java:S3011 - low-level, reflection utility. intentionally changes the accessibility + @SuppressWarnings({ "java:S4276", "java:S3776", "java:S1141", "java:S3011" }) + private static CopyFunction fromToFunction(final Class fromClass, final Class toClass) { + final List propertySetters = new ArrayList<>(); + + for (final Method fromMethod : getMethods(fromClass)) { + if (fromMethod.getParameterCount() == 0 && fromMethod.getReturnType() != void.class) { + final String methodName = fromMethod.getName(); + if (methodName.equals("getClass")) { + continue; // skip + } + final boolean isGet = isGet(methodName); + if (isGet || isIs(fromMethod, methodName)) { + final String fieldName = Character.toLowerCase(methodName.charAt(isGet ? 3 : 2)) + methodName.substring(isGet ? 4 : 3); + fromMethod.setAccessible(true); // if needed + final UnaryOperator toGetter = toGetter(toClass, fromMethod.getName(), fieldName); + final String setterName = "set" + methodName.substring(isGet ? 3 : 2); + final BiConsumer toSetter = toSetter(toClass, setterName, fieldName, fromMethod.getReturnType()); + if (toSetter == null && toGetter == null) { + // we allow toSetter to be null, but in that case the toGetter must not be null and the + // from value shall always match the to value (without setting it) + throw new IllegalStateException("Setter counterpart for " + fromMethod + " is not found in " + toClass.getName()); + } + propertySetters.add((from, to, setNullValues, propertyProcessor) -> { + final Object value; + try { + value = fromMethod.invoke(from); + } catch (final IllegalAccessException e) { + throw new IllegalStateException("Failed to get source value", e); + } catch (final InvocationTargetException e) { + throw new IllegalStateException( + "Failed to get source value", + e.getTargetException() == null ? e : e.getTargetException()); + } + if (value == null && !setNullValues) { // if !setNullValues null means no change + return false; + } + if (toGetter != null) { + final Object currentValue = toGetter.apply(to); + if (Objects.equals(value, currentValue)) { + return false; // no change + } + } + if (toSetter == null) { + throw new IllegalStateException( + "Setter counterpart for " + fromMethod + " is not found in " + toClass.getName() + + " and the 'from' value is not equal to the 'to' value"); + } + toSetter.accept(to, propertyProcessor.apply(value)); + return true; + }); + } + } + } + + return (from, to, setNullValues, entityManager) -> { + boolean updated = false; + for (final CopyFunction fieldSetter : propertySetters) { + updated = fieldSetter.apply(from, to, setNullValues, entityManager) || updated; + } + return updated; + }; + } + + // java:S3011 - low-level, reflection utility. intentionally changes the accessibility + @SuppressWarnings("java:S3011") + private static BiConsumer toSetter( + final Class toClass, final String setterName, final String fieldName, final Class type) { + try { + final Method toSetterMethod = getMethod(toClass, setterName, type); + return (to, value) -> { + try { + toSetterMethod.invoke(to, value); + } catch (final InvocationTargetException e) { + throw new IllegalStateException( + "Error invoking " + toSetterMethod, + e.getTargetException() == null ? e : e.getTargetException()); + } catch (final IllegalAccessException | IllegalArgumentException e) { + throw new IllegalStateException("Error invoking " + toSetterMethod, e); + } + }; + } catch (final NoSuchMethodException nsme) { + final Field field = getField(toClass, fieldName); + if (field == null) { + return null; + } else { + return (to, value) -> { + try { + field.set(to, value); + } catch (final IllegalAccessException | IllegalArgumentException e) { + throw new IllegalStateException("Error setting field " + field, e); + } + }; + } + } + } + + private static UnaryOperator toGetter(final Class toClass, final String getterName, final String fieldName) { + try { + final Method toGetterMethod = getMethod(toClass, getterName); + return to -> { + try { + return toGetterMethod.invoke(to); + } catch (final Exception e) { + throw new IllegalStateException("Error invoking " + toGetterMethod, e); + } + }; + } catch (final NoSuchMethodException e) { + // no method to get current value of the target field, try with field access + final Field field = getField(toClass, fieldName); // is or get + return field == null ? null : to -> { + try { + return field.get(to); + } catch (final Exception e2) { + throw new IllegalStateException("Error getting field " + field, e2); + } + }; + } + } + + private static boolean isIs(final Method fromMethod, final String methodName) { + return methodName.startsWith("is") && methodName.length() > 2 && Character.isUpperCase(methodName.charAt(2)) && + fromMethod.getReturnType() == boolean.class; + } + + private static boolean isGet(final String methodName) { + return methodName.startsWith("get") && methodName.length() > 3 && Character.isUpperCase(methodName.charAt(3)); + } + + @SuppressWarnings("java:S3011") // low-level, reflection utility. intentionally changes the accessibility + private static Field getField(final Class clazz, final String fieldName) { + for (final Field field : clazz.getDeclaredFields()) { + if (fieldName.equals(field.getName())) { + field.setAccessible(true); + return field; + } + } + final Class superClass = clazz.getSuperclass(); + if (superClass == null) { + return null; + } else { + return getField(superClass, fieldName); + } + } + + @NotNull + private static Method getMethod(final Class clazz, final String methodName, final Class... parameterTypes) + throws NoSuchMethodException { + try { + return getMethod(clazz, clazz, methodName, parameterTypes); + } catch (final NoSuchMethodException e) { + if (parameterTypes.length == 1 && parameterTypes[0] == Boolean.class) { + try { + return getMethod(clazz, methodName, boolean.class); + } catch (final NoSuchMethodException e2) { + throw e; + } + } + throw e; + } + } + + @SuppressWarnings("java:S3011") // low-level, reflection utility. intentionally changes the accessibility + private static Method getMethod(final Class target, final Class clazz, final String methodName, final Class... parameterTypes) + throws NoSuchMethodException { + try { + final Method method = clazz.getDeclaredMethod(methodName, parameterTypes); + method.setAccessible(true); + return method; + } catch (final NoSuchMethodException e) { + final Class superClass = clazz.getSuperclass(); + if (superClass == null) { + throw new NoSuchMethodException("Method " + methodName + " not found in " + target.getSimpleName()); + } else { + return getMethod(target, superClass, methodName, parameterTypes); + } + } + } + + private static List getMethods(final Class clazz) { + final List methods = new ArrayList<>(); + for (final Method method : clazz.getDeclaredMethods()) { + if (!method.isSynthetic() && !method.isBridge()) { + methods.add(method); + } + } + final Class superClass = clazz.getSuperclass(); + if (superClass != null) { + methods.addAll(getMethods(superClass)); + } + return methods; + } + + // key for copy of class to class function + private record FromTo(Class from, Class to) {} + + // functional interface to apply the copy operation + private interface CopyFunction { + + boolean apply(Object from, Object to, boolean setNullValues, UnaryOperator propertyProcessor); + } +} \ No newline at end of file diff --git a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/AbstractDDiApiIntegrationTest.java b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/AbstractDDiApiIntegrationTest.java index 0653d8063..7f9d9c034 100644 --- a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/AbstractDDiApiIntegrationTest.java +++ b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/AbstractDDiApiIntegrationTest.java @@ -353,13 +353,13 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat .andExpect(jsonPath(prefix + ".download", equalTo(downloadType))) .andExpect(jsonPath(prefix + ".update", equalTo(updateType))) .andExpect(jsonPath(prefix + ".chunks[?(@.part=='jvm')].name", - contains(ds.findFirstModuleByType(runtimeType).get().getName()))) + contains(findFirstModuleByType(ds, runtimeType).orElseThrow().getName()))) .andExpect(jsonPath(prefix + ".chunks[?(@.part=='jvm')].version", - contains(ds.findFirstModuleByType(runtimeType).get().getVersion()))) + contains(findFirstModuleByType(ds, runtimeType).orElseThrow().getVersion()))) .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].name", - contains(ds.findFirstModuleByType(osType).get().getName()))) + contains(findFirstModuleByType(ds, osType).orElseThrow().getName()))) .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].version", - contains(ds.findFirstModuleByType(osType).get().getVersion()))) + contains(findFirstModuleByType(ds, osType).orElseThrow().getVersion()))) .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0].size", contains(ARTIFACT_SIZE))) .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0].filename", contains(artifact.getFilename()))) @@ -391,9 +391,9 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId + "/softwaremodules/" + osModuleId + "/artifacts/" + artifactSignature.getFilename() + "/download.MD5SUM"))) .andExpect(jsonPath(prefix + ".chunks[?(@.part=='bApp')].version", - contains(ds.findFirstModuleByType(appType).get().getVersion()))) + contains(findFirstModuleByType(ds, appType).orElseThrow().getVersion()))) .andExpect(jsonPath(prefix + ".chunks[?(@.part=='bApp')].metadata").doesNotExist()) .andExpect(jsonPath(prefix + ".chunks[?(@.part=='bApp')].name") - .value(ds.findFirstModuleByType(appType).get().getName())); + .value(findFirstModuleByType(ds, appType).orElseThrow().getName())); } } \ No newline at end of file diff --git a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiArtifactDownloadTest.java b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiArtifactDownloadTest.java index 77a5c9867..043467d4b 100644 --- a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiArtifactDownloadTest.java +++ b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiArtifactDownloadTest.java @@ -83,7 +83,7 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest { final int artifactSize = 5 * 1024; final byte[] random = nextBytes(artifactSize); final Artifact artifact = artifactManagement.create(new ArtifactUpload( - new ByteArrayInputStream(random), ds.findFirstModuleByType(osType).get().getId(), "file1", false, artifactSize)); + new ByteArrayInputStream(random), findFirstModuleByType(ds, osType).orElseThrow().getId(), "file1", false, artifactSize)); assignDistributionSet(ds, targets); @@ -178,7 +178,7 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest { final int artifactSize = (int) quotaManagement.getMaxArtifactSize(); final byte[] random = nextBytes(artifactSize); final Artifact artifact = artifactManagement.create(new ArtifactUpload(new ByteArrayInputStream(random), - ds.findFirstModuleByType(osType).get().getId(), "file1", false, artifactSize)); + findFirstModuleByType(ds, osType).orElseThrow().getId(), "file1", false, artifactSize)); // download fails as artifact is not yet assigned mvc.perform(get("/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}", diff --git a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiCancelActionTest.java b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiCancelActionTest.java index c304a5dc5..f3dfb01a5 100644 --- a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiCancelActionTest.java +++ b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiCancelActionTest.java @@ -123,11 +123,11 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest { .andExpect(jsonPath("$.deployment.download", equalTo("forced"))) .andExpect(jsonPath("$.deployment.update", equalTo("forced"))) .andExpect(jsonPath("$.deployment.chunks[?(@.part=='jvm')].version", - contains(ds.findFirstModuleByType(runtimeType).get().getVersion()))) + contains(findFirstModuleByType(ds, runtimeType).orElseThrow().getVersion()))) .andExpect(jsonPath("$.deployment.chunks[?(@.part=='os')].version", - contains(ds.findFirstModuleByType(osType).get().getVersion()))) + contains(findFirstModuleByType(ds, osType).orElseThrow().getVersion()))) .andExpect(jsonPath("$.deployment.chunks[?(@.part=='bApp')].version", - contains(ds.findFirstModuleByType(appType).get().getVersion()))); + contains(findFirstModuleByType(ds, appType).orElseThrow().getVersion()))); // and finish it mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" diff --git a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiConfirmationBaseTest.java b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiConfirmationBaseTest.java index 720d9b019..d2ce3f180 100644 --- a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiConfirmationBaseTest.java +++ b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiConfirmationBaseTest.java @@ -10,7 +10,7 @@ package org.eclipse.hawkbit.ddi.rest.resource; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.hawkbit.repository.jpa.management.JpaConfirmationManagement.CONFIRMATION_CODE_MSG_PREFIX; +import static org.eclipse.hawkbit.repository.ConfirmationManagement.CONFIRMATION_CODE_MSG_PREFIX; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.hasItem; @@ -124,7 +124,7 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest { getAndVerifyConfirmationBasePayload( DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact, artifactSignature, action.getId(), - findDistributionSetByAction.findFirstModuleByType(osType).get().getId(), "forced", "forced"); + findFirstModuleByType(findDistributionSetByAction, osType).orElseThrow().getId(), "forced", "forced"); // Retrieved is reported final Iterable actionStatus = deploymentManagement diff --git a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java index 062a7cfaf..fb163f9e8 100644 --- a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java +++ b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java @@ -189,7 +189,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { final DistributionSet findDistributionSetByAction = distributionSetManagement.findByAction(action.getId()).get(); getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact, artifactSignature, action.getId(), - findDistributionSetByAction.findFirstModuleByType(osType).get().getId(), "forced", "forced"); + findFirstModuleByType(findDistributionSetByAction, osType).orElseThrow().getId(), "forced", "forced"); // Retrieved is reported final Iterable actionStatusMessages = deploymentManagement @@ -348,10 +348,10 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest { final DistributionSet findDistributionSetByAction = distributionSetManagement.findByAction(action.getId()).get(); getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact, artifactSignature, action.getId(), - findDistributionSetByAction.findFirstModuleByType(osType).get().getId(), "forced", "forced"); + findFirstModuleByType(findDistributionSetByAction, osType).orElseThrow().getId(), "forced", "forced"); getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaTypes.HAL_JSON, ds, artifact, artifactSignature, - action.getId(), findDistributionSetByAction.findFirstModuleByType(osType).get().getId(), "forced", + action.getId(), findFirstModuleByType(findDistributionSetByAction, osType).orElseThrow().getId(), "forced", "forced"); // Retrieved is reported diff --git a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiInstalledBaseTest.java b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiInstalledBaseTest.java index 7fa36ec6e..3344491b7 100644 --- a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiInstalledBaseTest.java +++ b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiInstalledBaseTest.java @@ -160,14 +160,14 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest { startsWith(deploymentBaseLink(CONTROLLER_ID, actionId1.toString())))); getAndVerifyDeploymentBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds1, artifact1, artifactSignature1, - actionId1, ds1.findFirstModuleByType(osType).get().getId(), Action.ActionType.SOFT); + actionId1, findFirstModuleByType(ds1, osType).orElseThrow().getId(), Action.ActionType.SOFT); postDeploymentFeedback(target.getControllerId(), actionId1, getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Closed")), status().isOk()); getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds1, artifact1, artifactSignature1, - actionId1, ds1.findFirstModuleByType(osType).get().getId(), Action.ActionType.SOFT); + actionId1, findFirstModuleByType(ds1, osType).orElseThrow().getId(), Action.ActionType.SOFT); // Run test with 2nd action final Long actionId2 = getFirstAssignedActionId( @@ -180,14 +180,14 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest { startsWith(deploymentBaseLink(CONTROLLER_ID, actionId2.toString())))); getAndVerifyDeploymentBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds2, artifact2, artifactSignature2, - actionId2, ds2.findFirstModuleByType(osType).get().getId(), Action.ActionType.FORCED); + actionId2, findFirstModuleByType(ds2, osType).orElseThrow().getId(), Action.ActionType.FORCED); postDeploymentFeedback(target.getControllerId(), actionId2, getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Closed")), status().isOk()); getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds2, artifact2, artifactSignature2, - actionId2, ds2.findFirstModuleByType(osType).get().getId(), Action.ActionType.FORCED); + actionId2, findFirstModuleByType(ds2, osType).orElseThrow().getId(), Action.ActionType.FORCED); performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), CONTROLLER_ID) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) @@ -197,7 +197,7 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest { // older installed action is still accessible, although not part of controller base getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds1, artifact1, artifactSignature1, - actionId1, ds1.findFirstModuleByType(osType).get().getId(), Action.ActionType.SOFT); + actionId1, findFirstModuleByType(ds1, osType).orElseThrow().getId(), Action.ActionType.SOFT); } /** @@ -245,7 +245,7 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest { .andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist()); getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds1, artifact1, artifactSignature1, - actionId3, ds1.findFirstModuleByType(osType).get().getId(), Action.ActionType.SOFT); + actionId3, findFirstModuleByType(ds1, osType).orElseThrow().getId(), Action.ActionType.SOFT); // cancelled action are not accessible mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), target.getControllerId(), @@ -304,7 +304,7 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest { .andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist()); getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds1, artifact1, artifactSignature1, - actionId1, ds1.findFirstModuleByType(osType).get().getId(), Action.ActionType.SOFT); + actionId1, findFirstModuleByType(ds1, osType).orElseThrow().getId(), Action.ActionType.SOFT); // cancelled action are not accessible mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), target.getControllerId(), @@ -359,7 +359,7 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest { startsWith(deploymentBaseLink(CONTROLLER_ID, actionId3.toString())))); getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds1, artifact1, artifactSignature1, - actionId1, ds1.findFirstModuleByType(osType).get().getId(), Action.ActionType.SOFT); + actionId1, findFirstModuleByType(ds1, osType).orElseThrow().getId(), Action.ActionType.SOFT); // cancelled action are not accessible mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), target.getControllerId(), @@ -463,10 +463,10 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest { tenantAware.getCurrentTenant(), target.getControllerId(), actionId)))); getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact, artifactSignature, - actionId, ds.findFirstModuleByType(osType).get().getId(), actionType); + actionId, findFirstModuleByType(ds, osType).orElseThrow().getId(), actionType); getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaTypes.HAL_JSON, ds, artifact, artifactSignature, actionId, - ds.findFirstModuleByType(osType).get().getId(), actionType); + findFirstModuleByType(ds, osType).orElseThrow().getId(), actionType); // Action is still finished after calling installedBase final Iterable actionStatusMessages = deploymentManagement diff --git a/hawkbit-ddi/hawkbit-ddi-starter/src/main/java/org/eclipse/hawkbit/autoconfigure/ddi/ControllerDownloadSecurityConfiguration.java b/hawkbit-ddi/hawkbit-ddi-starter/src/main/java/org/eclipse/hawkbit/autoconfigure/ddi/ControllerDownloadSecurityConfiguration.java index 5be3e6152..d64b72c5f 100644 --- a/hawkbit-ddi/hawkbit-ddi-starter/src/main/java/org/eclipse/hawkbit/autoconfigure/ddi/ControllerDownloadSecurityConfiguration.java +++ b/hawkbit-ddi/hawkbit-ddi-starter/src/main/java/org/eclipse/hawkbit/autoconfigure/ddi/ControllerDownloadSecurityConfiguration.java @@ -26,7 +26,6 @@ import org.eclipse.hawkbit.security.controller.GatewayTokenAuthenticator; import org.eclipse.hawkbit.security.controller.SecurityHeaderAuthenticator; import org.eclipse.hawkbit.security.controller.SecurityTokenAuthenticator; import org.eclipse.hawkbit.tenancy.TenantAware; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; @@ -57,8 +56,8 @@ class ControllerDownloadSecurityConfiguration { private final HawkbitSecurityProperties securityProperties; private final SystemSecurityContext systemSecurityContext; - @Autowired - ControllerDownloadSecurityConfiguration(final ControllerManagement controllerManagement, + ControllerDownloadSecurityConfiguration( + final ControllerManagement controllerManagement, final TenantConfigurationManagement tenantConfigurationManagement, final TenantAware tenantAware, final DdiSecurityProperties ddiSecurityConfiguration, final HawkbitSecurityProperties securityProperties, final SystemSecurityContext systemSecurityContext) { 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 a944d64e7..f5d2a80c2 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 @@ -97,9 +97,9 @@ public class AmqpMessageDispatcherService extends BaseAmqpService { private final SystemManagement systemManagement; private final TargetManagement targetManagement; private final ServiceMatcher serviceMatcher; - private final DistributionSetManagement distributionSetManagement; + private final SoftwareModuleManagement softwareModuleManagement; + private final DistributionSetManagement distributionSetManagement; private final DeploymentManagement deploymentManagement; - private final SoftwareModuleManagement softwareModuleManagement; private final TenantConfigurationManagement tenantConfigurationManagement; /** @@ -121,8 +121,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 SoftwareModuleManagement softwareModuleManagement, final DeploymentManagement deploymentManagement, + final SoftwareModuleManagement softwareModuleManagement, final DistributionSetManagement distributionSetManagement, + final DeploymentManagement deploymentManagement, final TenantConfigurationManagement tenantConfigurationManagement) { super(rabbitTemplate); this.artifactUrlHandler = artifactUrlHandler; @@ -131,8 +131,8 @@ public class AmqpMessageDispatcherService extends BaseAmqpService { this.systemManagement = systemManagement; this.targetManagement = targetManagement; this.serviceMatcher = serviceMatcher; - this.distributionSetManagement = distributionSetManagement; this.softwareModuleManagement = softwareModuleManagement; + this.distributionSetManagement = distributionSetManagement; this.deploymentManagement = deploymentManagement; this.tenantConfigurationManagement = tenantConfigurationManagement; } diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DmfApiConfiguration.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DmfApiConfiguration.java index 85cd2de3a..7be2bfa78 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DmfApiConfiguration.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DmfApiConfiguration.java @@ -279,8 +279,8 @@ public class DmfApiConfiguration { final SoftwareModuleManagement softwareModuleManagement, final DeploymentManagement deploymentManagement, final TenantConfigurationManagement tenantConfigurationManagement) { return new AmqpMessageDispatcherService(rabbitTemplate, amqpSenderService, artifactUrlHandler, - systemSecurityContext, systemManagement, targetManagement, serviceMatcher, distributionSetManagement, - softwareModuleManagement, deploymentManagement, tenantConfigurationManagement); + systemSecurityContext, systemManagement, targetManagement, serviceMatcher, softwareModuleManagement, distributionSetManagement, + deploymentManagement, tenantConfigurationManagement); } private static Map getTTLMaxArgsAuthenticationQueue() { 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 89da4eb29..5cb1f1329 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 @@ -109,7 +109,7 @@ class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest { amqpMessageDispatcherService = new AmqpMessageDispatcherService(rabbitTemplate, senderService, artifactUrlHandlerMock, systemSecurityContext, systemManagement, targetManagement, serviceMatcher, - distributionSetManagement, softwareModuleManagement, deploymentManagement, tenantConfigurationManagement); + softwareModuleManagement, distributionSetManagement, deploymentManagement, tenantConfigurationManagement); } diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResource.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResource.java index e04fd02d6..1816e820d 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResource.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResource.java @@ -51,7 +51,6 @@ import org.eclipse.hawkbit.repository.DeploymentManagement; import org.eclipse.hawkbit.repository.DistributionSetInvalidationManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; -import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; @@ -82,49 +81,50 @@ import org.springframework.web.bind.annotation.RestController; @RestController public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi { - private final SoftwareModuleManagement softwareModuleManagement; + private final SoftwareModuleManagement softwareModuleManagement; + private final DistributionSetManagement distributionSetManagement; + private final DistributionSetTypeManagement distributionSetTypeManagement; + private final DistributionSetInvalidationManagement distributionSetInvalidationManagement; private final TargetManagement targetManagement; private final TargetFilterQueryManagement targetFilterQueryManagement; private final DeploymentManagement deployManagement; private final SystemManagement systemManagement; - private final EntityFactory entityFactory; - private final DistributionSetManagement distributionSetManagement; - private final DistributionSetTypeManagement distributionSetTypeManagement; + private final MgmtDistributionSetMapper mgmtDistributionSetMapper; private final SystemSecurityContext systemSecurityContext; - private final DistributionSetInvalidationManagement distributionSetInvalidationManagement; private final TenantConfigHelper tenantConfigHelper; @SuppressWarnings("java:S107") MgmtDistributionSetResource( - final SoftwareModuleManagement softwareModuleManagement, - final TargetManagement targetManagement, final TargetFilterQueryManagement targetFilterQueryManagement, - final DeploymentManagement deployManagement, final SystemManagement systemManagement, - final EntityFactory entityFactory, final DistributionSetManagement distributionSetManagement, - final DistributionSetTypeManagement distributionSetTypeManagement, final SystemSecurityContext systemSecurityContext, + final SoftwareModuleManagement softwareModuleManagement, + final DistributionSetManagement distributionSetManagement, + final DistributionSetTypeManagement distributionSetTypeManagement, final DistributionSetInvalidationManagement distributionSetInvalidationManagement, - final TenantConfigurationManagement tenantConfigurationManagement) { + final TargetManagement targetManagement, final TargetFilterQueryManagement targetFilterQueryManagement, + final DeploymentManagement deployManagement, final TenantConfigurationManagement tenantConfigurationManagement, + final MgmtDistributionSetMapper mgmtDistributionSetMapper, + final SystemManagement systemManagement, final SystemSecurityContext systemSecurityContext) { this.softwareModuleManagement = softwareModuleManagement; + this.distributionSetManagement = distributionSetManagement; + this.distributionSetTypeManagement = distributionSetTypeManagement; + this.distributionSetInvalidationManagement = distributionSetInvalidationManagement; this.targetManagement = targetManagement; this.targetFilterQueryManagement = targetFilterQueryManagement; this.deployManagement = deployManagement; - this.systemManagement = systemManagement; - this.entityFactory = entityFactory; - this.distributionSetManagement = distributionSetManagement; - this.distributionSetTypeManagement = distributionSetTypeManagement; - this.systemSecurityContext = systemSecurityContext; - this.distributionSetInvalidationManagement = distributionSetInvalidationManagement; this.tenantConfigHelper = TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement); + this.mgmtDistributionSetMapper = mgmtDistributionSetMapper; + this.systemManagement = systemManagement; + this.systemSecurityContext = systemSecurityContext; } @Override public ResponseEntity> getDistributionSets( final String rsqlParam, final int pagingOffsetParam, final int pagingLimitParam, final String sortParam) { final Pageable pageable = PagingUtility.toPageable(pagingOffsetParam, pagingLimitParam, sanitizeDistributionSetSortParam(sortParam)); - final Slice findDsPage; + final Slice findDsPage; final long countModulesAll; if (rsqlParam != null) { findDsPage = distributionSetManagement.findByRsql(rsqlParam, pageable); - countModulesAll = ((Page) findDsPage).getTotalElements(); + countModulesAll = ((Page) findDsPage).getTotalElements(); } else { findDsPage = distributionSetManagement.findAll(pageable); countModulesAll = distributionSetManagement.count(); @@ -152,8 +152,8 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi { sets.stream().filter(ds -> ds.getType() == null).forEach(ds -> ds.setType(defaultDsKey)); //check if there is already deleted DS Type - for (MgmtDistributionSetRequestBodyPost ds : sets) { - final Optional opt = distributionSetTypeManagement.findByKey(ds.getType()); + for (final MgmtDistributionSetRequestBodyPost ds : sets) { + final Optional opt = distributionSetTypeManagement.findByKey(ds.getType()); opt.ifPresent(dsType -> { if (dsType.isDeleted()) { final String text = "Cannot create Distribution Set from type with key {0}. Distribution Set Type already deleted!"; @@ -163,8 +163,8 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi { }); } - final Collection createdDSets = distributionSetManagement - .create(MgmtDistributionSetMapper.dsFromRequest(sets, entityFactory)); + final Collection createdDSets = distributionSetManagement + .create(mgmtDistributionSetMapper.fromRequest(sets)); log.debug("{} distribution sets created, return status {}", sets.size(), HttpStatus.CREATED); return new ResponseEntity<>(MgmtDistributionSetMapper.toResponseDistributionSets(createdDSets), HttpStatus.CREATED); @@ -182,10 +182,11 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi { public ResponseEntity updateDistributionSet( final Long distributionSetId, final MgmtDistributionSetRequestBodyPut toUpdate) { - final DistributionSet updated = distributionSetManagement.update(entityFactory.distributionSet() - .update(distributionSetId).name(toUpdate.getName()).description(toUpdate.getDescription()) + final DistributionSet updated = distributionSetManagement.update(DistributionSetManagement.Update.builder() + .id(distributionSetId).name(toUpdate.getName()).description(toUpdate.getDescription()) .version(toUpdate.getVersion()).locked(toUpdate.getLocked()) - .requiredMigrationStep(toUpdate.getRequiredMigrationStep())); + .requiredMigrationStep(toUpdate.getRequiredMigrationStep()) + .build()); final MgmtDistributionSet response = MgmtDistributionSetMapper.toResponse(updated); MgmtDistributionSetMapper.addLinks(updated, response); @@ -247,7 +248,7 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi { final List> offlineAssignments = assignments.stream() .map(assignment -> new SimpleEntry<>(assignment.getId(), distributionSetId)) .collect(Collectors.toList()); - return ResponseEntity.ok(MgmtDistributionSetMapper + return ResponseEntity.ok(mgmtDistributionSetMapper .toResponse(deployManagement.offlineAssignedDistributionSets(offlineAssignments))); } @@ -260,7 +261,7 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi { }).toList(); final List assignmentResults = deployManagement.assignDistributionSets(deploymentRequests); - return ResponseEntity.ok(MgmtDistributionSetMapper.toResponse(assignmentResults)); + return ResponseEntity.ok(mgmtDistributionSetMapper.toResponse(assignmentResults)); } @Override @@ -316,9 +317,8 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi { final Long distributionSetId, final int pagingOffsetParam, final int pagingLimitParam, final String sortParam) { final Pageable pageable = PagingUtility.toPageable(pagingOffsetParam, pagingLimitParam, sanitizeDistributionSetSortParam(sortParam)); - final Page softwareModules = softwareModuleManagement.findByAssignedTo(distributionSetId, pageable); - return ResponseEntity.ok(new PagedList<>(MgmtSoftwareModuleMapper.toResponse( - softwareModules.getContent()), softwareModules.getTotalElements())); + final Page softwareModules = softwareModuleManagement.findByAssignedTo(distributionSetId, pageable); + return ResponseEntity.ok(new PagedList<>(MgmtSoftwareModuleMapper.toResponse(softwareModules.getContent()), softwareModules.getTotalElements())); } @Override diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTagResource.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTagResource.java index e08444d55..e92088d5d 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTagResource.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTagResource.java @@ -25,7 +25,6 @@ import org.eclipse.hawkbit.mgmt.rest.resource.mapper.MgmtTagMapper; import org.eclipse.hawkbit.mgmt.rest.resource.util.PagingUtility; import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetTagManagement; -import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetTag; @@ -41,31 +40,29 @@ import org.springframework.web.bind.annotation.RestController; */ @Slf4j @RestController -public class MgmtDistributionSetTagResource implements MgmtDistributionSetTagRestApi { +class MgmtDistributionSetTagResource implements MgmtDistributionSetTagRestApi { - private final DistributionSetTagManagement distributionSetTagManagement; - private final DistributionSetManagement distributionSetManagement; - private final EntityFactory entityFactory; + private final DistributionSetManagement distributionSetManagement; + private final DistributionSetTagManagement distributionSetTagManagement; MgmtDistributionSetTagResource( - final DistributionSetTagManagement distributionSetTagManagement, - final DistributionSetManagement distributionSetManagement, final EntityFactory entityFactory) { + final DistributionSetManagement distributionSetManagement, + final DistributionSetTagManagement distributionSetTagManagement) { this.distributionSetTagManagement = distributionSetTagManagement; this.distributionSetManagement = distributionSetManagement; - this.entityFactory = entityFactory; } @Override public ResponseEntity> getDistributionSetTags( final String rsqlParam, final int pagingOffsetParam, final int pagingLimitParam, final String sortParam) { final Pageable pageable = PagingUtility.toPageable(pagingOffsetParam, pagingLimitParam, sanitizeTagSortParam(sortParam)); - final Slice distributionSetTags; + final Slice distributionSetTags; final long count; if (rsqlParam == null) { distributionSetTags = distributionSetTagManagement.findAll(pageable); count = distributionSetTagManagement.count(); } else { - final Page page = distributionSetTagManagement.findByRsql(rsqlParam, pageable); + final Page page = distributionSetTagManagement.findByRsql(rsqlParam, pageable); distributionSetTags = page; count = page.getTotalElements(); } @@ -88,7 +85,7 @@ public class MgmtDistributionSetTagResource implements MgmtDistributionSetTagRes public ResponseEntity> createDistributionSetTags(final List tags) { log.debug("creating {} ds tags", tags.size()); - final List createdTags = distributionSetTagManagement.create(MgmtTagMapper.mapTagFromRequest(entityFactory, tags)); + final List createdTags = distributionSetTagManagement.create(MgmtDistributionSetMapper.mapTagFromRequest(tags)); return new ResponseEntity<>(MgmtTagMapper.toResponseDistributionSetTag(createdTags), HttpStatus.CREATED); } @@ -97,8 +94,8 @@ public class MgmtDistributionSetTagResource implements MgmtDistributionSetTagRes public ResponseEntity updateDistributionSetTag(final Long distributionSetTagId, final MgmtTagRequestBodyPut restDSTagRest) { final DistributionSetTag distributionSetTag = distributionSetTagManagement - .update(entityFactory.tag().update(distributionSetTagId).name(restDSTagRest.getName()) - .description(restDSTagRest.getDescription()).colour(restDSTagRest.getColour())); + .update(DistributionSetTagManagement.Update.builder().id(distributionSetTagId).name(restDSTagRest.getName()) + .description(restDSTagRest.getDescription()).colour(restDSTagRest.getColour()).build()); final MgmtTag response = MgmtTagMapper.toResponse(distributionSetTag); MgmtTagMapper.addLinks(distributionSetTag, response); @@ -122,7 +119,7 @@ public class MgmtDistributionSetTagResource implements MgmtDistributionSetTagRes final Long distributionSetTagId, final String rsqlParam, final int pagingOffsetParam, final int pagingLimitParam, final String sortParam) { final Pageable pageable = PagingUtility.toPageable(pagingOffsetParam, pagingLimitParam, sanitizeTagSortParam(sortParam)); - final Page distributionSets; + final Page distributionSets; if (rsqlParam == null) { distributionSets = distributionSetManagement.findByTag(distributionSetTagId, pageable); } else { @@ -143,7 +140,7 @@ public class MgmtDistributionSetTagResource implements MgmtDistributionSetTagRes @Override public ResponseEntity assignDistributionSets(final Long distributionSetTagId, final List distributionSetIds) { log.debug("Assign DistributionSet {} for ds tag {}", distributionSetIds.size(), distributionSetTagId); - final List assignedDs = this.distributionSetManagement.assignTag(distributionSetIds, distributionSetTagId); + final List assignedDs = this.distributionSetManagement.assignTag(distributionSetIds, distributionSetTagId); log.debug("Assigned DistributionSet {}", assignedDs.size()); return ResponseEntity.ok().build(); } @@ -160,7 +157,7 @@ public class MgmtDistributionSetTagResource implements MgmtDistributionSetTagRes @AuditLog(entity = "DistributionSetTag", type = AuditLog.Type.UPDATE, description = "Unassign Distribution Sets From Tag") public ResponseEntity unassignDistributionSets(final Long distributionsetTagId, final List distributionsetIds) { log.debug("Unassign DistributionSet {} for ds tag {}", distributionsetIds.size(), distributionsetTagId); - final List assignedDs = this.distributionSetManagement.unassignTag(distributionsetIds, distributionsetTagId); + final List assignedDs = this.distributionSetManagement.unassignTag(distributionsetIds, distributionsetTagId); log.debug("Unassigned DistributionSet {}", assignedDs.size()); return ResponseEntity.ok().build(); } diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTypeResource.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTypeResource.java index 9e0053b8c..d263a243e 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTypeResource.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTypeResource.java @@ -26,7 +26,6 @@ import org.eclipse.hawkbit.mgmt.rest.resource.mapper.MgmtDistributionSetTypeMapp import org.eclipse.hawkbit.mgmt.rest.resource.mapper.MgmtSoftwareModuleTypeMapper; import org.eclipse.hawkbit.mgmt.rest.resource.util.PagingUtility; import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; -import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.SoftwareModuleTypeNotInDistributionSetTypeException; @@ -45,33 +44,34 @@ import org.springframework.web.bind.annotation.RestController; @RestController public class MgmtDistributionSetTypeResource implements MgmtDistributionSetTypeRestApi { - private final SoftwareModuleTypeManagement softwareModuleTypeManagement; - private final DistributionSetTypeManagement distributionSetTypeManagement; - private final EntityFactory entityFactory; + private final SoftwareModuleTypeManagement softwareModuleTypeManagement; + private final DistributionSetTypeManagement distributionSetTypeManagement; + private final MgmtDistributionSetTypeMapper mgmtDistributionSetTypeMapper; MgmtDistributionSetTypeResource( - final SoftwareModuleTypeManagement softwareModuleTypeManagement, - final DistributionSetTypeManagement distributionSetTypeManagement, final EntityFactory entityFactory) { + final SoftwareModuleTypeManagement softwareModuleTypeManagement, + final DistributionSetTypeManagement distributionSetTypeManagement, + final MgmtDistributionSetTypeMapper mgmtDistributionSetTypeMapper) { this.softwareModuleTypeManagement = softwareModuleTypeManagement; this.distributionSetTypeManagement = distributionSetTypeManagement; - this.entityFactory = entityFactory; + this.mgmtDistributionSetTypeMapper = mgmtDistributionSetTypeMapper; } @Override public ResponseEntity> getDistributionSetTypes( final String rsqlParam, final int pagingOffsetParam, final int pagingLimitParam, final String sortParam) { final Pageable pageable = PagingUtility.toPageable(pagingOffsetParam, pagingLimitParam, sanitizeDistributionSetTypeSortParam(sortParam)); - final Slice findModuleTypessAll; + final Slice findModuleTypesAll; long countModulesAll; if (rsqlParam != null) { - findModuleTypessAll = distributionSetTypeManagement.findByRsql(rsqlParam, pageable); - countModulesAll = ((Page) findModuleTypessAll).getTotalElements(); + findModuleTypesAll = distributionSetTypeManagement.findByRsql(rsqlParam, pageable); + countModulesAll = ((Page) findModuleTypesAll).getTotalElements(); } else { - findModuleTypessAll = distributionSetTypeManagement.findAll(pageable); + findModuleTypesAll = distributionSetTypeManagement.findAll(pageable); countModulesAll = distributionSetTypeManagement.count(); } - final List rest = MgmtDistributionSetTypeMapper.toListResponse(findModuleTypessAll.getContent()); + final List rest = MgmtDistributionSetTypeMapper.toListResponse(findModuleTypesAll.getContent()); return ResponseEntity.ok(new PagedList<>(rest, countModulesAll)); } @@ -97,9 +97,10 @@ public class MgmtDistributionSetTypeResource implements MgmtDistributionSetTypeR @AuditLog(entity = "DistributionSetType", type = AuditLog.Type.UPDATE, description = "Update Distribution Set Type") public ResponseEntity updateDistributionSetType( final Long distributionSetTypeId, final MgmtDistributionSetTypeRequestBodyPut restDistributionSetType) { - final DistributionSetType updated = distributionSetTypeManagement.update(entityFactory.distributionSetType() - .update(distributionSetTypeId).description(restDistributionSetType.getDescription()) - .colour(restDistributionSetType.getColour())); + final DistributionSetType updated = distributionSetTypeManagement.update(DistributionSetTypeManagement.Update.builder() + .id(distributionSetTypeId).description(restDistributionSetType.getDescription()) + .colour(restDistributionSetType.getColour()). + build()); final MgmtDistributionSetType response = MgmtDistributionSetTypeMapper.toResponse(updated); MgmtDistributionSetTypeMapper.addLinks(response); @@ -110,11 +111,10 @@ public class MgmtDistributionSetTypeResource implements MgmtDistributionSetTypeR @Override public ResponseEntity> createDistributionSetTypes( final List distributionSetTypes) { - final List createdSoftwareModules = distributionSetTypeManagement - .create(MgmtDistributionSetTypeMapper.smFromRequest(entityFactory, distributionSetTypes)); + final List createdSoftwareModules = distributionSetTypeManagement + .create(mgmtDistributionSetTypeMapper.smFromRequest(distributionSetTypes)); - return ResponseEntity.status(HttpStatus.CREATED) - .body(MgmtDistributionSetTypeMapper.toListResponse(createdSoftwareModules)); + return ResponseEntity.status(HttpStatus.CREATED).body(MgmtDistributionSetTypeMapper.toListResponse(createdSoftwareModules)); } @Override diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadArtifactResource.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadArtifactResource.java index cdaa735b3..f89573f7e 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadArtifactResource.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadArtifactResource.java @@ -36,10 +36,10 @@ import org.springframework.web.context.WebApplicationContext; @Scope(value = WebApplicationContext.SCOPE_REQUEST) public class MgmtDownloadArtifactResource implements MgmtDownloadArtifactRestApi { - private final SoftwareModuleManagement softwareModuleManagement; + private final SoftwareModuleManagement softwareModuleManagement; private final ArtifactManagement artifactManagement; - public MgmtDownloadArtifactResource(final SoftwareModuleManagement softwareModuleManagement, final ArtifactManagement artifactManagement) { + public MgmtDownloadArtifactResource(final SoftwareModuleManagement softwareModuleManagement, final ArtifactManagement artifactManagement) { this.softwareModuleManagement = softwareModuleManagement; this.artifactManagement = artifactManagement; } diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java index 8d0fcd566..c4152e708 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java @@ -62,21 +62,25 @@ import org.springframework.web.multipart.MultipartFile; public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi { private final ArtifactManagement artifactManagement; - private final SoftwareModuleManagement softwareModuleManagement; - private final SoftwareModuleTypeManagement softwareModuleTypeManagement; + private final SoftwareModuleManagement softwareModuleManagement; + private final SoftwareModuleTypeManagement softwareModuleTypeManagement; private final ArtifactUrlHandler artifactUrlHandler; + private final MgmtSoftwareModuleMapper mgmtSoftwareModuleMapper; private final SystemManagement systemManagement; private final EntityFactory entityFactory; MgmtSoftwareModuleResource( - final ArtifactManagement artifactManagement, final SoftwareModuleManagement softwareModuleManagement, - final SoftwareModuleTypeManagement softwareModuleTypeManagement, - final ArtifactUrlHandler artifactUrlHandler, final SystemManagement systemManagement, - final EntityFactory entityFactory) { + final ArtifactManagement artifactManagement, + final SoftwareModuleManagement softwareModuleManagement, + final SoftwareModuleTypeManagement softwareModuleTypeManagement, + final ArtifactUrlHandler artifactUrlHandler, + final MgmtSoftwareModuleMapper mgmtSoftwareModuleMapper, + final SystemManagement systemManagement, final EntityFactory entityFactory) { this.artifactManagement = artifactManagement; this.softwareModuleManagement = softwareModuleManagement; this.softwareModuleTypeManagement = softwareModuleTypeManagement; this.artifactUrlHandler = artifactUrlHandler; + this.mgmtSoftwareModuleMapper = mgmtSoftwareModuleMapper; this.systemManagement = systemManagement; this.entityFactory = entityFactory; } @@ -159,11 +163,11 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi { public ResponseEntity> getSoftwareModules( final String rsqlParam, final int pagingOffsetParam, final int pagingLimitParam, final String sortParam) { final Pageable pageable = PagingUtility.toPageable(pagingOffsetParam, pagingLimitParam, sanitizeSoftwareModuleSortParam(sortParam)); - final Slice findModulesAll; + final Slice findModulesAll; final long countModulesAll; if (rsqlParam != null) { findModulesAll = softwareModuleManagement.findByRsql(rsqlParam, pageable); - countModulesAll = ((Page) findModulesAll).getTotalElements(); + countModulesAll = ((Page) findModulesAll).getTotalElements(); } else { findModulesAll = softwareModuleManagement.findAll(pageable); countModulesAll = softwareModuleManagement.count(); @@ -188,7 +192,7 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi { log.debug("creating {} softwareModules", softwareModules.size()); for (final MgmtSoftwareModuleRequestBodyPost sm : softwareModules) { - final Optional opt = softwareModuleTypeManagement.findByKey(sm.getType()); + final Optional opt = softwareModuleTypeManagement.findByKey(sm.getType()); opt.ifPresent(smType -> { if (smType.isDeleted()) { final String text = "Cannot create Software Module from type with key {0}. Software Module Type already deleted!"; @@ -197,8 +201,8 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi { } }); } - final Collection createdSoftwareModules = softwareModuleManagement - .create(MgmtSoftwareModuleMapper.smFromRequest(entityFactory, softwareModules)); + final Collection createdSoftwareModules = softwareModuleManagement + .create(mgmtSoftwareModuleMapper.smFromRequest(softwareModules)); log.debug("{} softwareModules created, return status {}", softwareModules.size(), HttpStatus.CREATED); return ResponseEntity.status(HttpStatus.CREATED).body(MgmtSoftwareModuleMapper.toResponse(createdSoftwareModules)); @@ -208,10 +212,12 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi { public ResponseEntity updateSoftwareModule( final Long softwareModuleId, final MgmtSoftwareModuleRequestBodyPut restSoftwareModule) { final SoftwareModule module = softwareModuleManagement - .update(entityFactory.softwareModule().update(softwareModuleId) + .update(SoftwareModuleManagement.Update.builder() + .id(softwareModuleId) .description(restSoftwareModule.getDescription()) .vendor(restSoftwareModule.getVendor()) - .locked(restSoftwareModule.getLocked())); + .locked(restSoftwareModule.getLocked()) + .build()); final MgmtSoftwareModule response = MgmtSoftwareModuleMapper.toResponse(module); MgmtSoftwareModuleMapper.addLinks(module, response); diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleTypeResource.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleTypeResource.java index 6e75d926d..2b74079fb 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleTypeResource.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleTypeResource.java @@ -38,23 +38,21 @@ import org.springframework.web.bind.annotation.RestController; @RestController public class MgmtSoftwareModuleTypeResource implements MgmtSoftwareModuleTypeRestApi { - private final SoftwareModuleTypeManagement softwareModuleTypeManagement; - private final EntityFactory entityFactory; + private final SoftwareModuleTypeManagement softwareModuleTypeManagement; - MgmtSoftwareModuleTypeResource(final SoftwareModuleTypeManagement softwareModuleTypeManagement, final EntityFactory entityFactory) { + MgmtSoftwareModuleTypeResource(final SoftwareModuleTypeManagement softwareModuleTypeManagement) { this.softwareModuleTypeManagement = softwareModuleTypeManagement; - this.entityFactory = entityFactory; } @Override public ResponseEntity> getTypes( final String rsqlParam, final int pagingOffsetParam, final int pagingLimitParam, final String sortParam) { final Pageable pageable = PagingUtility.toPageable(pagingOffsetParam, pagingLimitParam, sanitizeSoftwareModuleTypeSortParam(sortParam)); - final Slice findModuleTypessAll; + final Slice findModuleTypessAll; final long countModulesAll; if (rsqlParam != null) { findModuleTypessAll = softwareModuleTypeManagement.findByRsql(rsqlParam, pageable); - countModulesAll = ((Page) findModuleTypessAll).getTotalElements(); + countModulesAll = ((Page) findModuleTypessAll).getTotalElements(); } else { findModuleTypessAll = softwareModuleTypeManagement.findAll(pageable); countModulesAll = softwareModuleTypeManagement.count(); @@ -80,9 +78,11 @@ public class MgmtSoftwareModuleTypeResource implements MgmtSoftwareModuleTypeRes @Override public ResponseEntity updateSoftwareModuleType( final Long softwareModuleTypeId, final MgmtSoftwareModuleTypeRequestBodyPut restSoftwareModuleType) { - final SoftwareModuleType updatedSoftwareModuleType = softwareModuleTypeManagement.update(entityFactory - .softwareModuleType().update(softwareModuleTypeId).description(restSoftwareModuleType.getDescription()) - .colour(restSoftwareModuleType.getColour())); + final SoftwareModuleType updatedSoftwareModuleType = softwareModuleTypeManagement.update( + SoftwareModuleTypeManagement.Update.builder().id(softwareModuleTypeId) + .description(restSoftwareModuleType.getDescription()) + .colour(restSoftwareModuleType.getColour()) + .build()); return ResponseEntity.ok(MgmtSoftwareModuleTypeMapper.toResponse(updatedSoftwareModuleType)); } @@ -90,8 +90,8 @@ public class MgmtSoftwareModuleTypeResource implements MgmtSoftwareModuleTypeRes @Override public ResponseEntity> createSoftwareModuleTypes( final List softwareModuleTypes) { - final List createdSoftwareModules = softwareModuleTypeManagement - .create(MgmtSoftwareModuleTypeMapper.smFromRequest(entityFactory, softwareModuleTypes)); + final List createdSoftwareModules = softwareModuleTypeManagement + .create(MgmtSoftwareModuleTypeMapper.smFromRequest(softwareModuleTypes)); return new ResponseEntity<>(MgmtSoftwareModuleTypeMapper.toTypesResponse(createdSoftwareModules), HttpStatus.CREATED); } diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResource.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResource.java index 68b2654d6..3040f589b 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResource.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResource.java @@ -86,17 +86,21 @@ public class MgmtTargetResource implements MgmtTargetRestApi { private final TargetManagement targetManagement; private final ConfirmationManagement confirmationManagement; private final DeploymentManagement deploymentManagement; + private final MgmtDistributionSetMapper mgmtDistributionSetMapper; private final EntityFactory entityFactory; private final TenantConfigHelper tenantConfigHelper; MgmtTargetResource( final TargetManagement targetManagement, final DeploymentManagement deploymentManagement, - final ConfirmationManagement confirmationManagement, final EntityFactory entityFactory, + final ConfirmationManagement confirmationManagement, + final MgmtDistributionSetMapper mgmtDistributionSetMapper, + final EntityFactory entityFactory, final SystemSecurityContext systemSecurityContext, final TenantConfigurationManagement tenantConfigurationManagement) { this.targetManagement = targetManagement; this.deploymentManagement = deploymentManagement; this.confirmationManagement = confirmationManagement; + this.mgmtDistributionSetMapper = mgmtDistributionSetMapper; this.entityFactory = entityFactory; this.tenantConfigHelper = TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement); } @@ -290,7 +294,7 @@ public class MgmtTargetResource implements MgmtTargetRestApi { log.debug("updateActionConfirmation with data [targetId={}, actionId={}]: {}", targetId, actionId, actionConfirmation); return getValidatedAction(targetId, actionId) - .map(action -> { + .>map(action -> { try { switch (actionConfirmation.getConfirmation()) { case CONFIRMED: @@ -305,18 +309,18 @@ public class MgmtTargetResource implements MgmtTargetRestApi { confirmationManagement.denyAction(actionId, actionConfirmation.getCode(), actionConfirmation.getDetails()); break; } - return new ResponseEntity(HttpStatus.OK); + return new ResponseEntity<>(HttpStatus.OK); } catch (final InvalidConfirmationFeedbackException e) { if (e.getReason() == InvalidConfirmationFeedbackException.Reason.ACTION_CLOSED) { log.warn("Updating action {} with confirmation {} not possible since action not active anymore.", action.getId(), actionConfirmation.getConfirmation(), e); - return new ResponseEntity(HttpStatus.GONE); + return new ResponseEntity<>(HttpStatus.GONE); } else if (e.getReason() == InvalidConfirmationFeedbackException.Reason.NOT_AWAITING_CONFIRMATION) { log.debug("Action is not waiting for confirmation, deny request.", e); - return new ResponseEntity(HttpStatus.NOT_FOUND); + return new ResponseEntity<>(HttpStatus.NOT_FOUND); } else { log.debug("Action confirmation failed with unknown reason.", e); - return new ResponseEntity(HttpStatus.BAD_REQUEST); + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); } } }) @@ -371,7 +375,7 @@ public class MgmtTargetResource implements MgmtTargetRestApi { final List> offlineAssignments = dsAssignments.stream() .map(dsAssignment -> new SimpleEntry<>(targetId, dsAssignment.getId())) .collect(Collectors.toList()); - return ResponseEntity.ok(MgmtDistributionSetMapper + return ResponseEntity.ok(mgmtDistributionSetMapper .toResponse(deploymentManagement.offlineAssignedDistributionSets(offlineAssignments))); } findTargetWithExceptionIfNotFound(targetId); @@ -386,7 +390,7 @@ public class MgmtTargetResource implements MgmtTargetRestApi { final List assignmentResults = deploymentManagement .assignDistributionSets(deploymentRequests); - return ResponseEntity.ok(MgmtDistributionSetMapper.toResponse(assignmentResults)); + return ResponseEntity.ok(mgmtDistributionSetMapper.toResponse(assignmentResults)); } @Override diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTagResource.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTagResource.java index 9ca906433..f36b27fe4 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTagResource.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTagResource.java @@ -92,7 +92,7 @@ public class MgmtTargetTagResource implements MgmtTargetTagRestApi { @Override public ResponseEntity> createTargetTags(final List tags) { log.debug("creating {} target tags", tags.size()); - final List createdTargetTags = this.tagManagement.create(MgmtTagMapper.mapTagFromRequest(entityFactory, tags)); + final List createdTargetTags = tagManagement.create(MgmtTagMapper.mapTagFromRequest(entityFactory, tags)); return new ResponseEntity<>(MgmtTagMapper.toResponse(createdTargetTags), HttpStatus.CREATED); } diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtDistributionSetMapper.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtDistributionSetMapper.java index 1c8cdb1a6..2f9a68877 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtDistributionSetMapper.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtDistributionSetMapper.java @@ -12,45 +12,59 @@ package org.eclipse.hawkbit.mgmt.rest.resource.mapper; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; import org.eclipse.hawkbit.mgmt.json.model.MgmtMetadata; import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtActionId; 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.MgmtTargetAssignmentResponseBody; +import org.eclipse.hawkbit.mgmt.json.model.tag.MgmtTagRequestBodyPut; import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetRestApi; import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetTypeRestApi; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; -import org.eclipse.hawkbit.repository.EntityFactory; -import org.eclipse.hawkbit.repository.builder.DistributionSetCreate; +import org.eclipse.hawkbit.repository.DistributionSetManagement; +import org.eclipse.hawkbit.repository.DistributionSetTagManagement; +import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; +import org.eclipse.hawkbit.repository.SoftwareModuleManagement; +import org.eclipse.hawkbit.repository.SystemManagement; +import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult; +import org.eclipse.hawkbit.repository.model.DistributionSetType; +import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.rest.json.model.ResponseList; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; /** - * A mapper which maps repository model to RESTful model representation and - * back. + * A mapper which maps repository model to RESTful model representation and back. */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public final class MgmtDistributionSetMapper { +@Service +public class MgmtDistributionSetMapper { - /** - * {@link MgmtDistributionSetRequestBodyPost}s to {@link DistributionSet}s. - * - * @param sets to convert - * @return converted list of {@link DistributionSet}s - */ - public static List dsFromRequest( - final Collection sets, final EntityFactory entityFactory) { - return sets.stream().map(dsRest -> fromRequest(dsRest, entityFactory)).toList(); + private final DistributionSetTypeManagement distributionSetTypeManagement; + private final SoftwareModuleManagement softwareModuleManagement; + private final SystemManagement systemManagement; + + MgmtDistributionSetMapper( + final DistributionSetTypeManagement distributionSetTypeManagement, + final SoftwareModuleManagement softwareModuleManagement, + final SystemManagement systemManagement) { + this.distributionSetTypeManagement = distributionSetTypeManagement; + this.softwareModuleManagement = softwareModuleManagement; + this.systemManagement = systemManagement; + } + + public List fromRequest(final Collection sets) { + return sets.stream().map(this::fromRequest).toList(); } public static MgmtDistributionSet toResponse(final DistributionSet distributionSet) { @@ -70,13 +84,11 @@ public final class MgmtDistributionSetMapper { response.setDeleted(distributionSet.isDeleted()); response.setValid(distributionSet.isValid()); - distributionSet.getModules() - .forEach(module -> response.getModules().add(MgmtSoftwareModuleMapper.toResponse(module))); + distributionSet.getModules().forEach(module -> response.getModules().add(MgmtSoftwareModuleMapper.toResponse(module))); response.setRequiredMigrationStep(distributionSet.isRequiredMigrationStep()); - response.add(linkTo(methodOn(MgmtDistributionSetRestApi.class).getDistributionSet(response.getId())) - .withSelfRel().expand()); + response.add(linkTo(methodOn(MgmtDistributionSetRestApi.class).getDistributionSet(response.getId())).withSelfRel().expand()); return response; } @@ -102,7 +114,7 @@ public final class MgmtDistributionSetMapper { return result; } - public static MgmtTargetAssignmentResponseBody toResponse(final List dsAssignmentResults) { + public MgmtTargetAssignmentResponseBody toResponse(final List dsAssignmentResults) { final MgmtTargetAssignmentResponseBody result = new MgmtTargetAssignmentResponseBody(); final int alreadyAssigned = dsAssignmentResults.stream() .mapToInt(DistributionSetAssignmentResult::getAlreadyAssigned).sum(); @@ -115,7 +127,7 @@ public final class MgmtDistributionSetMapper { return result; } - public static List toResponseDistributionSets(final Collection sets) { + public static List toResponseDistributionSets(final Collection sets) { if (sets == null) { return Collections.emptyList(); } @@ -123,6 +135,16 @@ public final class MgmtDistributionSetMapper { return new ResponseList<>(sets.stream().map(MgmtDistributionSetMapper::toResponse).toList()); } + public static List mapTagFromRequest(final Collection tags) { + return tags.stream() + .map(tagRest -> DistributionSetTagManagement.Create.builder() + .name(tagRest.getName()) + .description(tagRest.getDescription()).colour(tagRest.getColour()) + .build()) + .map(DistributionSetTagManagement.Create.class::cast) + .toList(); + } + public static MgmtMetadata toResponseDsMetadata(final String key, String value) { final MgmtMetadata metadataRest = new MgmtMetadata(); metadataRest.setKey(key); @@ -140,7 +162,7 @@ public final class MgmtDistributionSetMapper { return metadata.entrySet().stream().map(e -> toResponseDsMetadata(e.getKey(), e.getValue())).toList(); } - public static List toResponseFromDsList(final List sets) { + public static List toResponseFromDsList(final List sets) { if (sets == null) { return Collections.emptyList(); } @@ -148,14 +170,8 @@ public final class MgmtDistributionSetMapper { return sets.stream().map(MgmtDistributionSetMapper::toResponse).toList(); } - /** - * {@link MgmtDistributionSetRequestBodyPost} to {@link DistributionSet}. - * - * @param dsRest to convert - * @return converted {@link DistributionSet} - */ - private static DistributionSetCreate fromRequest(final MgmtDistributionSetRequestBodyPost dsRest, final EntityFactory entityFactory) { - final List modules = new ArrayList<>(); + private DistributionSetManagement.Create fromRequest(final MgmtDistributionSetRequestBodyPost dsRest) { + final Set modules = new HashSet<>(); if (dsRest.getOs() != null) { modules.add(dsRest.getOs().getId()); } @@ -168,8 +184,32 @@ public final class MgmtDistributionSetMapper { if (dsRest.getModules() != null) { dsRest.getModules().forEach(module -> modules.add(module.getId())); } - return entityFactory.distributionSet().create().name(dsRest.getName()).version(dsRest.getVersion()) - .description(dsRest.getDescription()).type(dsRest.getType()).modules(modules) - .requiredMigrationStep(dsRest.getRequiredMigrationStep()); + return DistributionSetManagement.Create.builder() + .type(Optional.ofNullable(dsRest.getType()) + // if the type is supplied the type MUST exist + .map(typeKey -> distributionSetTypeManagement + .findByKey(typeKey) + .orElseThrow(() -> new EntityNotFoundException(DistributionSetType.class, typeKey))) + .map(DistributionSetType.class::cast) + // if here, the type is not supplied, use the default type + .orElseGet(() -> systemManagement.getTenantMetadata().getDefaultDsType())) + .name(dsRest.getName()).version(dsRest.getVersion()) + .description(dsRest.getDescription()) + .modules(findSoftwareModuleWithExceptionIfNotFound(modules)) + .requiredMigrationStep(dsRest.getRequiredMigrationStep()) + .build(); + } + + private Set findSoftwareModuleWithExceptionIfNotFound(final Set softwareModuleIds) { + if (CollectionUtils.isEmpty(softwareModuleIds)) { + return Collections.emptySet(); + } + + final List modules = softwareModuleManagement.get(softwareModuleIds); + if (modules.size() < softwareModuleIds.size()) { + throw new EntityNotFoundException(SoftwareModule.class, softwareModuleIds); + } + + return new HashSet<>(modules); } } \ No newline at end of file diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtDistributionSetTypeMapper.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtDistributionSetTypeMapper.java index 29979a764..b456b1679 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtDistributionSetTypeMapper.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtDistributionSetTypeMapper.java @@ -14,36 +14,47 @@ import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; import org.eclipse.hawkbit.mgmt.json.model.distributionsettype.MgmtDistributionSetType; import org.eclipse.hawkbit.mgmt.json.model.distributionsettype.MgmtDistributionSetTypeRequestBodyPost; import org.eclipse.hawkbit.mgmt.json.model.softwaremoduletype.MgmtSoftwareModuleTypeAssignment; import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetTypeRestApi; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; -import org.eclipse.hawkbit.repository.EntityFactory; -import org.eclipse.hawkbit.repository.builder.DistributionSetTypeCreate; +import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; +import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; +import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.model.DistributionSetType; +import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.rest.json.model.ResponseList; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; /** * A mapper which maps repository model to RESTful model representation and back. */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) +@Service public final class MgmtDistributionSetTypeMapper { - public static List smFromRequest(final EntityFactory entityFactory, final Collection smTypesRest) { + private final SoftwareModuleTypeManagement softwareModuleTypeManagement; + + MgmtDistributionSetTypeMapper(final SoftwareModuleTypeManagement softwareModuleTypeManagement) { + this.softwareModuleTypeManagement = softwareModuleTypeManagement; + } + + public List smFromRequest(final Collection smTypesRest) { if (smTypesRest == null) { return Collections.emptyList(); } - return smTypesRest.stream().map(smRest -> fromRequest(entityFactory, smRest)).toList(); + return smTypesRest.stream().map(this::fromRequest).toList(); } - public static List toListResponse(final Collection types) { + public static List toListResponse(final Collection types) { if (types == null) { return Collections.emptyList(); } @@ -71,22 +82,32 @@ public final class MgmtDistributionSetTypeMapper { .withRel(MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_OPTIONAL_MODULES).expand()); } - private static DistributionSetTypeCreate fromRequest(final EntityFactory entityFactory, - final MgmtDistributionSetTypeRequestBodyPost smsRest) { - return entityFactory.distributionSetType().create().key(smsRest.getKey()).name(smsRest.getName()) + private DistributionSetTypeManagement.Create fromRequest(final MgmtDistributionSetTypeRequestBodyPost smsRest) { + return DistributionSetTypeManagement.Create.builder() + .key(smsRest.getKey()).name(smsRest.getName()) .description(smsRest.getDescription()).colour(smsRest.getColour()) - .mandatory(getMandatoryModules(smsRest)).optional(getOptionalModules(smsRest)); + .mandatoryModuleTypes(getModules(smsRest.getMandatorymodules())) + .optionalModuleTypes(getModules(smsRest.getOptionalmodules())) + .build(); } - private static Collection getMandatoryModules(final MgmtDistributionSetTypeRequestBodyPost smsRest) { - return Optional.ofNullable(smsRest.getMandatorymodules()) - .map(modules -> modules.stream().map(MgmtSoftwareModuleTypeAssignment::getId).toList()) - .orElse(Collections.emptyList()); + private Set getModules(final List moduleAssignments) { + return Optional.ofNullable(moduleAssignments) + .map(modules -> modules.stream().map(MgmtSoftwareModuleTypeAssignment::getId).collect(Collectors.toSet())) + .map(this::findSoftwareModuleTypeWithExceptionIfNotFound) + .orElse(Collections.emptySet()); } - private static Collection getOptionalModules(final MgmtDistributionSetTypeRequestBodyPost smsRest) { - return Optional.ofNullable(smsRest.getOptionalmodules()) - .map(modules -> modules.stream().map(MgmtSoftwareModuleTypeAssignment::getId).toList()) - .orElse(Collections.emptyList()); + private Set findSoftwareModuleTypeWithExceptionIfNotFound(final Collection softwareModuleTypeId) { + if (CollectionUtils.isEmpty(softwareModuleTypeId)) { + return Collections.emptySet(); + } + + final List module = softwareModuleTypeManagement.get(softwareModuleTypeId); + if (module.size() < softwareModuleTypeId.size()) { + throw new EntityNotFoundException(SoftwareModuleType.class, softwareModuleTypeId); + } + + return new HashSet<>(module); } } \ No newline at end of file diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtSoftwareModuleMapper.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtSoftwareModuleMapper.java index 1973de19f..16e59339a 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtSoftwareModuleMapper.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtSoftwareModuleMapper.java @@ -16,12 +16,8 @@ import java.util.Collection; import java.util.Collections; import java.util.List; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import org.eclipse.hawkbit.repository.artifact.urlhandler.ApiType; -import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrl; -import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrlHandler; -import org.eclipse.hawkbit.repository.artifact.urlhandler.URLPlaceholder; +import jakarta.validation.ValidationException; + 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; @@ -33,22 +29,36 @@ import org.eclipse.hawkbit.mgmt.rest.api.MgmtSoftwareModuleTypeRestApi; import org.eclipse.hawkbit.mgmt.rest.resource.MgmtDownloadArtifactResource; import org.eclipse.hawkbit.mgmt.rest.resource.MgmtSoftwareModuleResource; import org.eclipse.hawkbit.repository.EntityFactory; +import org.eclipse.hawkbit.repository.SoftwareModuleManagement; +import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; import org.eclipse.hawkbit.repository.SystemManagement; -import org.eclipse.hawkbit.repository.builder.SoftwareModuleCreate; +import org.eclipse.hawkbit.repository.artifact.urlhandler.ApiType; +import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrl; +import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrlHandler; +import org.eclipse.hawkbit.repository.artifact.urlhandler.URLPlaceholder; import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataCreate; +import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; 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.SoftwareModuleType; import org.eclipse.hawkbit.rest.json.model.ResponseList; import org.springframework.hateoas.Link; import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; +import org.springframework.stereotype.Service; /** * A mapper which maps repository model to RESTful model representation and back. */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) +@Service public final class MgmtSoftwareModuleMapper { + private final SoftwareModuleTypeManagement softwareModuleTypeManagement; + + MgmtSoftwareModuleMapper(final SoftwareModuleTypeManagement softwareModuleTypeManagement) { + this.softwareModuleTypeManagement = softwareModuleTypeManagement; + } + public static List fromRequestSwMetadata( final EntityFactory entityFactory, final Long softwareModuleId, final Collection metadata) { if (metadata == null) { @@ -62,16 +72,15 @@ public final class MgmtSoftwareModuleMapper { .toList(); } - public static List smFromRequest( - final EntityFactory entityFactory, final Collection smsRest) { + public List smFromRequest(final Collection smsRest) { if (smsRest == null) { return Collections.emptyList(); } - return smsRest.stream().map(smRest -> fromRequest(entityFactory, smRest)).toList(); + return smsRest.stream().map(this::fromRequest).toList(); } - public static List toResponse(final Collection softwareModules) { + public static List toResponse(final Collection softwareModules) { if (softwareModules == null) { return Collections.emptyList(); } @@ -145,7 +154,7 @@ public final class MgmtSoftwareModuleMapper { public static void addLinks(final Artifact artifact, final MgmtArtifact response) { response.add(WebMvcLinkBuilder.linkTo(methodOn(MgmtDownloadArtifactResource.class) - .downloadArtifact(artifact.getSoftwareModule().getId(), artifact.getId())).withRel("download") + .downloadArtifact(artifact.getSoftwareModule().getId(), artifact.getId())).withRel("download") .expand()); } @@ -159,10 +168,21 @@ public final class MgmtSoftwareModuleMapper { urls.forEach(entry -> response.add(Link.of(entry.getRef()).withRel(entry.getRel()).expand())); } - private static SoftwareModuleCreate fromRequest(final EntityFactory entityFactory, + private SoftwareModuleManagement.Create fromRequest( final MgmtSoftwareModuleRequestBodyPost smsRest) { - return entityFactory.softwareModule().create().type(smsRest.getType()).name(smsRest.getName()) - .version(smsRest.getVersion()).description(smsRest.getDescription()).vendor(smsRest.getVendor()) - .encrypted(smsRest.isEncrypted()); + return SoftwareModuleManagement.Create.builder() + .type(getSoftwareModuleTypeFromKeyString(smsRest.getType())) + .name(smsRest.getName()).version(smsRest.getVersion()).description(smsRest.getDescription()).vendor(smsRest.getVendor()) + .encrypted(smsRest.isEncrypted()) + .build(); + } + + private SoftwareModuleType getSoftwareModuleTypeFromKeyString(final String type) { + if (type == null) { + throw new ValidationException("type cannot be null"); + } + + return softwareModuleTypeManagement.findByKey(type.trim()) + .orElseThrow(() -> new EntityNotFoundException(SoftwareModuleType.class, type.trim())); } } \ No newline at end of file diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtSoftwareModuleTypeMapper.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtSoftwareModuleTypeMapper.java index bc9c3faaa..cb6faffa2 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtSoftwareModuleTypeMapper.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtSoftwareModuleTypeMapper.java @@ -21,8 +21,7 @@ import lombok.NoArgsConstructor; import org.eclipse.hawkbit.mgmt.json.model.softwaremoduletype.MgmtSoftwareModuleType; import org.eclipse.hawkbit.mgmt.json.model.softwaremoduletype.MgmtSoftwareModuleTypeRequestBodyPost; import org.eclipse.hawkbit.mgmt.rest.api.MgmtSoftwareModuleTypeRestApi; -import org.eclipse.hawkbit.repository.EntityFactory; -import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeCreate; +import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.rest.json.model.ResponseList; @@ -32,16 +31,16 @@ import org.eclipse.hawkbit.rest.json.model.ResponseList; @NoArgsConstructor(access = AccessLevel.PRIVATE) public final class MgmtSoftwareModuleTypeMapper { - public static List smFromRequest(final EntityFactory entityFactory, + public static List smFromRequest( final Collection smTypesRest) { if (smTypesRest == null) { return Collections.emptyList(); } - return smTypesRest.stream().map(smRest -> fromRequest(entityFactory, smRest)).toList(); + return smTypesRest.stream().map(MgmtSoftwareModuleTypeMapper::fromRequest).toList(); } - public static List toTypesResponse(final Collection types) { + public static List toTypesResponse(final Collection types) { if (types == null) { return Collections.emptyList(); } @@ -62,10 +61,11 @@ public final class MgmtSoftwareModuleTypeMapper { return result; } - private static SoftwareModuleTypeCreate fromRequest(final EntityFactory entityFactory, - final MgmtSoftwareModuleTypeRequestBodyPost smsRest) { - return entityFactory.softwareModuleType().create().key(smsRest.getKey()).name(smsRest.getName()) + private static SoftwareModuleTypeManagement.Create fromRequest(final MgmtSoftwareModuleTypeRequestBodyPost smsRest) { + return SoftwareModuleTypeManagement.Create.builder() + .key(smsRest.getKey()).name(smsRest.getName()) .description(smsRest.getDescription()).colour(smsRest.getColour()) - .maxAssignments(smsRest.getMaxAssignments()); + .maxAssignments(smsRest.getMaxAssignments()) + .build(); } } \ No newline at end of file diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtTagMapper.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtTagMapper.java index 2d2b6a045..5092f9676 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtTagMapper.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/mapper/MgmtTagMapper.java @@ -70,7 +70,7 @@ public final class MgmtTagMapper { .expand()); } - public static List toResponseDistributionSetTag(final List distributionSetTags) { + public static List toResponseDistributionSetTag(final Collection distributionSetTags) { final List tagsRest = new ArrayList<>(); if (distributionSetTags == null) { return tagsRest; @@ -106,7 +106,7 @@ public final class MgmtTagMapper { .withRel("assignedDistributionSets").expand()); } - public static List mapTagFromRequest(final EntityFactory entityFactory, final Collection tags) { + public static List> mapTagFromRequest(final EntityFactory entityFactory, final Collection tags) { return tags.stream() .map(tagRest -> entityFactory.tag().create().name(tagRest.getName()) .description(tagRest.getDescription()).colour(tagRest.getColour())) diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtContentTypeTest.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtContentTypeTest.java index acdf76214..b090cd5cb 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtContentTypeTest.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtContentTypeTest.java @@ -19,7 +19,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import java.util.Collections; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; -import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.rest.util.JsonBuilder; import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter; import org.junit.jupiter.api.BeforeEach; @@ -35,22 +35,21 @@ import org.springframework.test.web.servlet.MvcResult; /** * With Spring Boot 2.2.x the default charset encoding became deprecated. In hawkBit we want to keep the old behavior for now and still * return the charset in the response, which is achieved through enabling {@link Encoding} via properties. - */ -@SpringBootTest(properties = { "server.servlet.encoding.charset=UTF-8", "server.servlet.encoding.force=true" }) -@Import(HttpEncodingAutoConfiguration.class) -/** + *

* Feature: Component Tests - Management API
* Story: Response Content-Type */ +@SpringBootTest(properties = { "server.servlet.encoding.charset=UTF-8", "server.servlet.encoding.force=true" }) +@Import(HttpEncodingAutoConfiguration.class) @SuppressWarnings("java:S1874") // TODO for compatibility, to be checked if we really want to do that public class MgmtContentTypeTest extends AbstractManagementApiIntegrationTest { - private final String dsName = "DS-ö"; - private DistributionSet ds; + private static final String DS_NAME = "DS-ö"; + private DistributionSetManagement.Create dsCreate; @BeforeEach public void setupBeforeTest() { - ds = testdataFactory.generateDistributionSet(dsName); + dsCreate = DistributionSetManagement.Create.builder().type(defaultDsType()).name(DS_NAME).version("1.0").build(); } /** @@ -60,11 +59,11 @@ public class MgmtContentTypeTest extends AbstractManagementApiIntegrationTest { void postDistributionSet_ContentTypeJsonUtf8_woAccept() throws Exception { final MvcResult result = mvc.perform( post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING).content(JsonBuilder.distributionSets( - Collections.singletonList(ds))) + Collections.singletonList(dsCreate))) .contentType(MediaType.APPLICATION_JSON_UTF8)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isCreated()) - .andExpect(jsonPath("[0]name", equalTo(dsName))) + .andExpect(jsonPath("[0]name", equalTo(DS_NAME))) .andReturn(); assertEquals(MediaTypes.HAL_JSON_VALUE + ";charset=UTF-8", getResponseHeaderContentType(result)); @@ -77,11 +76,11 @@ public class MgmtContentTypeTest extends AbstractManagementApiIntegrationTest { void postDistributionSet_ContentTypeJsonUtf8_wAcceptJson() throws Exception { final MvcResult result = mvc.perform( post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING).content(JsonBuilder.distributionSets( - Collections.singletonList(ds))) + Collections.singletonList(dsCreate))) .contentType(MediaType.APPLICATION_JSON_UTF8).accept(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isCreated()) - .andExpect(jsonPath("[0]name", equalTo(dsName))) + .andExpect(jsonPath("[0]name", equalTo(DS_NAME))) .andReturn(); assertEquals(MediaType.APPLICATION_JSON_UTF8_VALUE, getResponseHeaderContentType(result)); @@ -94,11 +93,11 @@ public class MgmtContentTypeTest extends AbstractManagementApiIntegrationTest { void postDistributionSet_ContentTypeJsonUtf8_wAcceptJsonUtf8() throws Exception { final MvcResult result = mvc.perform( post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING).content(JsonBuilder.distributionSets( - Collections.singletonList(ds))) + Collections.singletonList(dsCreate))) .contentType(MediaType.APPLICATION_JSON_UTF8).accept(MediaType.APPLICATION_JSON_UTF8)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isCreated()) - .andExpect(jsonPath("[0]name", equalTo(dsName))) + .andExpect(jsonPath("[0]name", equalTo(DS_NAME))) .andReturn(); assertEquals(MediaType.APPLICATION_JSON_UTF8_VALUE, getResponseHeaderContentType(result)); @@ -111,11 +110,11 @@ public class MgmtContentTypeTest extends AbstractManagementApiIntegrationTest { void postDistributionSet_ContentTypeJsonUtf8_wAcceptHalJson() throws Exception { final MvcResult result = mvc.perform( post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING).content(JsonBuilder.distributionSets( - Collections.singletonList(ds))) + Collections.singletonList(dsCreate))) .contentType(MediaType.APPLICATION_JSON_UTF8).accept(MediaTypes.HAL_JSON)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isCreated()) - .andExpect(jsonPath("[0]name", equalTo(dsName))) + .andExpect(jsonPath("[0]name", equalTo(DS_NAME))) .andReturn(); assertEquals(MediaTypes.HAL_JSON_VALUE + ";charset=UTF-8", getResponseHeaderContentType(result)); @@ -128,11 +127,11 @@ public class MgmtContentTypeTest extends AbstractManagementApiIntegrationTest { void postDistributionSet_ContentTypeJson_woAccept() throws Exception { final MvcResult result = mvc.perform( post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING).content(JsonBuilder.distributionSets( - Collections.singletonList(ds))) + Collections.singletonList(dsCreate))) .contentType(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isCreated()) - .andExpect(jsonPath("[0]name", equalTo(dsName))) + .andExpect(jsonPath("[0]name", equalTo(DS_NAME))) .andReturn(); assertEquals(MediaTypes.HAL_JSON_VALUE + ";charset=UTF-8", getResponseHeaderContentType(result)); @@ -145,11 +144,11 @@ public class MgmtContentTypeTest extends AbstractManagementApiIntegrationTest { void postDistributionSet_ContentTypeJson_wAcceptJson() throws Exception { final MvcResult result = mvc.perform( post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING).content(JsonBuilder.distributionSets( - Collections.singletonList(ds))) + Collections.singletonList(dsCreate))) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isCreated()) - .andExpect(jsonPath("[0]name", equalTo(dsName))) + .andExpect(jsonPath("[0]name", equalTo(DS_NAME))) .andReturn(); assertEquals(MediaType.APPLICATION_JSON_UTF8_VALUE, getResponseHeaderContentType(result)); @@ -161,11 +160,11 @@ public class MgmtContentTypeTest extends AbstractManagementApiIntegrationTest { @Test void postDistributionSet_ContentTypeJson_wAcceptJsonUtf8() throws Exception { final MvcResult result = mvc.perform(post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING) - .content(JsonBuilder.distributionSets(Collections.singletonList(ds))).contentType(MediaType.APPLICATION_JSON) + .content(JsonBuilder.distributionSets(Collections.singletonList(dsCreate))).contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON_UTF8)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isCreated()) - .andExpect(jsonPath("[0]name", equalTo(dsName))) + .andExpect(jsonPath("[0]name", equalTo(DS_NAME))) .andReturn(); assertEquals(MediaType.APPLICATION_JSON_UTF8_VALUE, getResponseHeaderContentType(result)); @@ -177,11 +176,11 @@ public class MgmtContentTypeTest extends AbstractManagementApiIntegrationTest { @Test void postDistributionSet_ContentTypeJson_wAcceptHalJson() throws Exception { final MvcResult result = mvc.perform(post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING) - .content(JsonBuilder.distributionSets(Collections.singletonList(ds))).contentType(MediaType.APPLICATION_JSON) + .content(JsonBuilder.distributionSets(Collections.singletonList(dsCreate))).contentType(MediaType.APPLICATION_JSON) .accept(MediaTypes.HAL_JSON)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isCreated()) - .andExpect(jsonPath("[0]name", equalTo(dsName))) + .andExpect(jsonPath("[0]name", equalTo(DS_NAME))) .andReturn(); assertEquals(MediaTypes.HAL_JSON_VALUE + ";charset=UTF-8", getResponseHeaderContentType(result)); diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResourceTest.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResourceTest.java index 17453d7ea..2afa473f4 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResourceTest.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResourceTest.java @@ -41,6 +41,7 @@ import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtActionType; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; import org.eclipse.hawkbit.mgmt.rest.resource.util.ResourceUtility; +import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository; @@ -359,8 +360,7 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe void createDsFromAlreadyMarkedAsDeletedType() throws Exception { final SoftwareModule softwareModule = testdataFactory.createSoftwareModule("exampleKey"); final DistributionSetType type = testdataFactory.findOrCreateDistributionSetType( - "testKey", "testType", Collections.singletonList(softwareModule.getType()), - Collections.singletonList(softwareModule.getType())); + "testKey", "testType", List.of(softwareModule.getType()), List.of()); final DistributionSet ds = testdataFactory.createDistributionSet("dsName", "dsVersion", type, Collections.singletonList(softwareModule)); final Target target = testdataFactory.createTarget("exampleControllerId"); @@ -371,7 +371,7 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe distributionSetTypeManagement.delete(type.getId()); // check if the ds type is marked as deleted - final Optional opt = distributionSetTypeManagement.findByKey(type.getKey()); + final Optional opt = distributionSetTypeManagement.findByKey(type.getKey()); if (opt.isEmpty()) { throw new AssertionError("The Optional object of distribution set type should not be empty!"); } @@ -379,7 +379,7 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe Assert.isTrue(reloaded.isDeleted(), "Distribution Set Type not marked as deleted!"); //request for ds creation of type which is already marked as deleted - should return bad request - final DistributionSet generated = testdataFactory.generateDistributionSet( + final DistributionSetManagement.Create generated = testdataFactory.generateDistributionSet( "stanTest", "2", reloaded, Collections.singletonList(softwareModule)); final MvcResult mvcResult = mvc .perform(post("/rest/v1/distributionsets") @@ -854,8 +854,8 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe assertThat(distributionSetManagement.findByCompleted(true, PAGE)).isEmpty(); DistributionSet set = testdataFactory.createDistributionSet("one"); - set = distributionSetManagement.update(entityFactory.distributionSet().update(set.getId()) - .version("anotherVersion").requiredMigrationStep(true)); + set = distributionSetManagement.update(DistributionSetManagement.Update.builder().id(set.getId()) + .version("anotherVersion").requiredMigrationStep(true).build()); // load also lazy stuff set = distributionSetManagement.getWithDetails(set.getId()).get(); @@ -881,9 +881,9 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe .andExpect(jsonPath("$.content.[0].lastModifiedAt", equalTo(set.getLastModifiedAt()))) .andExpect(jsonPath("$.content.[0].version", equalTo(set.getVersion()))) .andExpect(jsonPath("$.content.[0].modules.[?(@.type=='" + runtimeType.getKey() + "')].id", - contains(set.findFirstModuleByType(runtimeType).get().getId().intValue()))) + contains(findFirstModuleByType(set, runtimeType).get().getId().intValue()))) .andExpect(jsonPath("$.content.[0].modules.[?(@.type=='" + appType.getKey() + "')].id", - contains(set.findFirstModuleByType(appType).get().getId().intValue()))) + contains(findFirstModuleByType(set, appType).get().getId().intValue()))) .andExpect(jsonPath("$.content.[0].modules.[?(@.type=='" + osType.getKey() + "')].id", contains(getOsModule(set).intValue()))); } @@ -916,9 +916,9 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe .andExpect(jsonPath("$.lastModifiedAt", equalTo(set.getLastModifiedAt()))) .andExpect(jsonPath("$.version", equalTo(set.getVersion()))) .andExpect(jsonPath("$.modules.[?(@.type=='" + runtimeType.getKey() + "')].id", - contains(set.findFirstModuleByType(runtimeType).get().getId().intValue()))) + contains(findFirstModuleByType(set, runtimeType).get().getId().intValue()))) .andExpect(jsonPath("$.modules.[?(@.type=='" + appType.getKey() + "')].id", - contains(set.findFirstModuleByType(appType).get().getId().intValue()))) + contains(findFirstModuleByType(set, appType).get().getId().intValue()))) .andExpect(jsonPath("$.modules.[?(@.type=='" + osType.getKey() + "')].id", contains(getOsModule(set).intValue()))); @@ -935,26 +935,19 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe final SoftwareModule jvm = testdataFactory.createSoftwareModule(TestdataFactory.SM_TYPE_RT); final SoftwareModule os = testdataFactory.createSoftwareModule(TestdataFactory.SM_TYPE_OS); - DistributionSet one = testdataFactory.generateDistributionSet("one", "one", standardDsType, - Arrays.asList(os, jvm, ah)); - DistributionSet two = testdataFactory.generateDistributionSet("two", "two", standardDsType, - Arrays.asList(os, jvm, ah)); - DistributionSet three = testdataFactory.generateDistributionSet("three", "three", standardDsType, - Arrays.asList(os, jvm, ah), true); - final long current = System.currentTimeMillis(); - final MvcResult mvcResult = executeMgmtTargetPost(one, two, three); + final MvcResult mvcResult = executeMgmtTargetPost( + testdataFactory.generateDistributionSet("one", "one", standardDsType, Arrays.asList(os, jvm, ah)), + testdataFactory.generateDistributionSet("two", "two", standardDsType, Arrays.asList(os, jvm, ah)), + testdataFactory.generateDistributionSet("three", "three", standardDsType, Arrays.asList(os, jvm, ah), true)); - one = distributionSetManagement - .getWithDetails(distributionSetManagement.findByRsql("name==one", PAGE).getContent().get(0).getId()) - .get(); - two = distributionSetManagement - .getWithDetails(distributionSetManagement.findByRsql("name==two", PAGE).getContent().get(0).getId()) - .get(); - three = distributionSetManagement - .getWithDetails(distributionSetManagement.findByRsql("name==three", PAGE).getContent().get(0).getId()) - .get(); + final DistributionSet one = distributionSetManagement + .getWithDetails(distributionSetManagement.findByRsql("name==one", PAGE).getContent().get(0).getId()).orElseThrow(); + final DistributionSet two = distributionSetManagement + .getWithDetails(distributionSetManagement.findByRsql("name==two", PAGE).getContent().get(0).getId()).orElseThrow(); + final DistributionSet three = distributionSetManagement + .getWithDetails(distributionSetManagement.findByRsql("name==three", PAGE).getContent().get(0).getId()).orElseThrow(); assertThat((Object) JsonPath.compile("[0]_links.self.href").read(mvcResult.getResponse().getContentAsString())) .hasToString("http://localhost/rest/v1/distributionsets/" + one.getId()); @@ -1058,8 +1051,11 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe final DistributionSet set = testdataFactory.createDistributionSet("one"); assertThat(distributionSetManagement.count()).isEqualTo(1); - final String body = new JSONObject().put("version", "anotherVersion").put("requiredMigrationStep", true) - .put("deleted", true).toString(); + final String body = new JSONObject() + .put("version", "anotherVersion") + .put("requiredMigrationStep", true) + .put("deleted", true) + .toString(); mvc.perform(put("/rest/v1/distributionsets/{dsId}", set.getId()).content(body) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) @@ -1112,8 +1108,12 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe void invalidRequestsOnDistributionSetsResource() throws Exception { final DistributionSet set = testdataFactory.createDistributionSet("one"); - final List sets = new ArrayList<>(); - sets.add(set); + final List sets = new ArrayList<>(); + sets.add(DistributionSetManagement.Create.builder() + .type(set.getType()) + .name(set.getName()) + .version(set.getVersion()) + .build()); // SM does not exist mvc.perform(get("/rest/v1/distributionsets/12345678")) @@ -1135,13 +1135,14 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe .andDo(MockMvcResultPrinter.print()) .andExpect(status().isBadRequest()); - final DistributionSet missingName = entityFactory.distributionSet().create().build(); + final DistributionSetManagement.Create missingName = DistributionSetManagement.Create.builder().build(); mvc.perform(post("/rest/v1/distributionsets").content(JsonBuilder.distributionSets(Collections.singletonList(missingName))) .contentType(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isBadRequest()); - final DistributionSet toLongName = testdataFactory.generateDistributionSet(randomString(NamedEntity.NAME_MAX_SIZE + 1)); + final DistributionSetManagement.Create toLongName = + testdataFactory.generateDistributionSet(randomString(NamedEntity.NAME_MAX_SIZE + 1)); mvc.perform(post("/rest/v1/distributionsets").content(JsonBuilder.distributionSets(Collections.singletonList(toLongName))) .contentType(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print()) @@ -1165,7 +1166,6 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe mvc.perform(delete("/rest/v1/distributionsets")) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isMethodNotAllowed()); - } /** @@ -1349,7 +1349,10 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe final int amount = 10; testdataFactory.createDistributionSets(amount); distributionSetManagement - .create(entityFactory.distributionSet().create().name("incomplete").version("2").type("os")); + .create(DistributionSetManagement.Create.builder() + .type(distributionSetTypeManagement.findByKey("os").orElseThrow()) + .name("incomplete").version("2") + .build()); final String rsqlFindLikeDs1OrDs2 = "complete==" + Boolean.TRUE; @@ -1820,8 +1823,10 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe .create(entityFactory.targetFilterQuery().create().name(filterNamePrefix + "c").query("name==y")); } - private MvcResult executeMgmtTargetPost(final DistributionSet one, final DistributionSet two, - final DistributionSet three) throws Exception { + private MvcResult executeMgmtTargetPost( + final DistributionSetManagement.Create one, + final DistributionSetManagement.Create two, + final DistributionSetManagement.Create three) throws Exception { return mvc .perform(post("/rest/v1/distributionsets") .content(JsonBuilder.distributionSets(Arrays.asList(one, two, three))) @@ -1835,13 +1840,13 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe .andExpect(jsonPath("[0]createdBy", equalTo("uploadTester"))) .andExpect(jsonPath("[0]version", equalTo(one.getVersion()))) .andExpect(jsonPath("[0]complete", equalTo(Boolean.TRUE))) - .andExpect(jsonPath("[0]requiredMigrationStep", equalTo(one.isRequiredMigrationStep()))) + .andExpect(jsonPath("[0]requiredMigrationStep", equalTo(one.getRequiredMigrationStep()))) .andExpect(jsonPath("[0].modules.[?(@.type=='" + runtimeType.getKey() + "')].id", - contains(one.findFirstModuleByType(runtimeType).get().getId().intValue()))) + contains(findFirstModuleByType(one, runtimeType).get().getId().intValue()))) .andExpect(jsonPath("[0].modules.[?(@.type=='" + appType.getKey() + "')].id", - contains(one.findFirstModuleByType(appType).get().getId().intValue()))) + contains(findFirstModuleByType(one, appType).get().getId().intValue()))) .andExpect(jsonPath("[0].modules.[?(@.type=='" + osType.getKey() + "')].id", - contains(one.findFirstModuleByType(osType).get().getId().intValue()))) + contains(findFirstModuleByType(one, osType).get().getId().intValue()))) .andExpect(jsonPath("[1]name", equalTo(two.getName()))) .andExpect(jsonPath("[1]description", equalTo(two.getDescription()))) .andExpect(jsonPath("[1]complete", equalTo(Boolean.TRUE))) @@ -1849,12 +1854,12 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe .andExpect(jsonPath("[1]createdBy", equalTo("uploadTester"))) .andExpect(jsonPath("[1]version", equalTo(two.getVersion()))) .andExpect(jsonPath("[1].modules.[?(@.type=='" + runtimeType.getKey() + "')].id", - contains(two.findFirstModuleByType(runtimeType).get().getId().intValue()))) + contains(findFirstModuleByType(two, runtimeType).get().getId().intValue()))) .andExpect(jsonPath("[1].modules.[?(@.type=='" + appType.getKey() + "')].id", - contains(two.findFirstModuleByType(appType).get().getId().intValue()))) + contains(findFirstModuleByType(two, appType).get().getId().intValue()))) .andExpect(jsonPath("[1].modules.[?(@.type=='" + osType.getKey() + "')].id", - contains(two.findFirstModuleByType(osType).get().getId().intValue()))) - .andExpect(jsonPath("[1]requiredMigrationStep", equalTo(two.isRequiredMigrationStep()))) + contains(findFirstModuleByType(two, osType).get().getId().intValue()))) + .andExpect(jsonPath("[1]requiredMigrationStep", equalTo(two.getRequiredMigrationStep()))) .andExpect(jsonPath("[2]name", equalTo(three.getName()))) .andExpect(jsonPath("[2]description", equalTo(three.getDescription()))) .andExpect(jsonPath("[2]complete", equalTo(Boolean.TRUE))) @@ -1862,12 +1867,12 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe .andExpect(jsonPath("[2]createdBy", equalTo("uploadTester"))) .andExpect(jsonPath("[2]version", equalTo(three.getVersion()))) .andExpect(jsonPath("[2].modules.[?(@.type=='" + runtimeType.getKey() + "')].id", - contains(three.findFirstModuleByType(runtimeType).get().getId().intValue()))) + contains(findFirstModuleByType(three, runtimeType).get().getId().intValue()))) .andExpect(jsonPath("[2].modules.[?(@.type=='" + appType.getKey() + "')].id", - contains(three.findFirstModuleByType(appType).get().getId().intValue()))) + contains(findFirstModuleByType(three, appType).get().getId().intValue()))) .andExpect(jsonPath("[2].modules.[?(@.type=='" + osType.getKey() + "')].id", - contains(three.findFirstModuleByType(osType).get().getId().intValue()))) - .andExpect(jsonPath("[2]requiredMigrationStep", equalTo(three.isRequiredMigrationStep()))) + contains(findFirstModuleByType(three, osType).get().getId().intValue()))) + .andExpect(jsonPath("[2]requiredMigrationStep", equalTo(three.getRequiredMigrationStep()))) .andReturn(); } diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTagResourceTest.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTagResourceTest.java index 1ee2bce72..4b99bd5ab 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTagResourceTest.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTagResourceTest.java @@ -353,7 +353,7 @@ class MgmtDistributionSetTagResourceTest extends AbstractManagementApiIntegratio .andDo(MockMvcResultPrinter.print()) .andExpect(status().isOk()); - final List updated = distributionSetManagement.findByTag(tag.getId(), PAGE).getContent(); + final List updated = distributionSetManagement.findByTag(tag.getId(), PAGE).getContent(); assertThat(updated.stream().map(DistributionSet::getId).toList()).containsOnly(set.getId()); } @@ -375,7 +375,7 @@ class MgmtDistributionSetTagResourceTest extends AbstractManagementApiIntegratio .andDo(MockMvcResultPrinter.print()) .andExpect(status().isOk()); - final List updated = distributionSetManagement.findByTag(tag.getId(), PAGE).getContent(); + final List updated = distributionSetManagement.findByTag(tag.getId(), PAGE).getContent(); assertThat(updated.stream().map(DistributionSet::getId).toList()) .containsAll(sets.stream().map(DistributionSet::getId).toList()); } @@ -402,7 +402,7 @@ class MgmtDistributionSetTagResourceTest extends AbstractManagementApiIntegratio .andDo(MockMvcResultPrinter.print()) .andExpect(status().isOk()); - final List updated = distributionSetManagement.findByTag(tag.getId(), PAGE).getContent(); + final List updated = distributionSetManagement.findByTag(tag.getId(), PAGE).getContent(); assertThat(updated.stream().map(DistributionSet::getId).toList()) .containsOnly(assigned.getId()); } @@ -430,7 +430,7 @@ class MgmtDistributionSetTagResourceTest extends AbstractManagementApiIntegratio .andDo(MockMvcResultPrinter.print()) .andExpect(status().isOk()); - final List updated = distributionSetManagement.findByTag(tag.getId(), PAGE).getContent(); + final List updated = distributionSetManagement.findByTag(tag.getId(), PAGE).getContent(); assertThat(updated.stream().map(DistributionSet::getId).toList()) .containsOnly(assigned.getId()); } diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTypeResourceTest.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTypeResourceTest.java index e4690db03..d8d21e066 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTypeResourceTest.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTypeResourceTest.java @@ -27,11 +27,14 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Set; import com.jayway.jsonpath.JsonPath; import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; -import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeCreate; +import org.eclipse.hawkbit.repository.DistributionSetManagement; +import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; +import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.NamedEntity; @@ -59,12 +62,14 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati @WithUser(principal = "uploadTester", allSpPermissions = true) void getDistributionSetTypes() throws Exception { DistributionSetType testType = distributionSetTypeManagement.create( - entityFactory.distributionSetType().create() + DistributionSetTypeManagement.Create.builder() .key("test123") .name("TestName123") .description("Desc123") - .colour("col12")); - testType = distributionSetTypeManagement.update(entityFactory.distributionSetType().update(testType.getId()).description("Desc1234")); + .colour("col12") + .build()); + testType = distributionSetTypeManagement.update( + DistributionSetTypeManagement.Update.builder().id(testType.getId()).description("Desc1234").build()); // 4 types overall (2 hawkbit tenant default, 1 test default and 1 // generated in this test) @@ -99,12 +104,14 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati @WithUser(principal = "uploadTester", allSpPermissions = true) void getDistributionSetTypesSortedByKey() throws Exception { DistributionSetType testType = distributionSetTypeManagement.create( - entityFactory.distributionSetType().create() + DistributionSetTypeManagement.Create.builder() .key("zzzzz") .name("TestName123") .description("Desc123") - .colour("col12")); - testType = distributionSetTypeManagement.update(entityFactory.distributionSetType().update(testType.getId()).description("Desc1234")); + .colour("col12") + .build()); + testType = distributionSetTypeManagement.update( + DistributionSetTypeManagement.Update.builder().id(testType.getId()).description("Desc1234").build()); // descending mvc.perform(get("/rest/v1/distributionsettypes") @@ -160,11 +167,12 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati @WithUser(principal = "uploadTester", allSpPermissions = true) void addMandatoryModuleToDistributionSetType() throws Exception { DistributionSetType testType = distributionSetTypeManagement.create( - entityFactory.distributionSetType().create() + DistributionSetTypeManagement.Create.builder() .key("test123") .name("TestName123") .description("Desc123") - .colour("col12")); + .colour("col12") + .build()); mvc.perform(post("/rest/v1/distributionsettypes/{dstID}/mandatorymoduletypes", testType.getId()) .contentType(MediaType.APPLICATION_JSON) @@ -185,11 +193,12 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati @WithUser(principal = "uploadTester", allSpPermissions = true) void addOptionalModuleToDistributionSetType() throws Exception { DistributionSetType testType = distributionSetTypeManagement.create( - entityFactory.distributionSetType().create() + DistributionSetTypeManagement.Create.builder() .key("test123") .name("TestName123") .description("Desc123") - .colour("col12")); + .colour("col12") + .build()); mvc.perform(post("/rest/v1/distributionsettypes/{dstID}/optionalmoduletypes", testType.getId()) .contentType(MediaType.APPLICATION_JSON) @@ -213,15 +222,16 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati final int maxSoftwareModuleTypes = quotaManagement.getMaxSoftwareModuleTypesPerDistributionSetType(); final List moduleTypeIds = new ArrayList<>(); for (int i = 0; i < maxSoftwareModuleTypes + 1; ++i) { - final SoftwareModuleTypeCreate smCreate = entityFactory.softwareModuleType().create().name("smType_" + i) - .description("smType_" + i).maxAssignments(1).colour("blue").key("smType_" + i); + final SoftwareModuleTypeManagement.Create smCreate = SoftwareModuleTypeManagement.Create.builder().name("smType_" + i) + .description("smType_" + i).maxAssignments(1).colour("blue").key("smType_" + i).build(); moduleTypeIds.add(softwareModuleTypeManagement.create(smCreate).getId()); } // verify quota enforcement for optional module types - final DistributionSetType testType = distributionSetTypeManagement.create(entityFactory.distributionSetType() - .create().key("testType").name("testType").description("testType").colour("col12")); + final DistributionSetType testType = distributionSetTypeManagement.create( + DistributionSetTypeManagement.Create.builder() + .key("testType").name("testType").description("testType").colour("col12").build()); assertThat(testType.getOptLockRevision()).isEqualTo(1); for (int i = 0; i < moduleTypeIds.size() - 1; ++i) { @@ -241,8 +251,9 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati // verify quota enforcement for mandatory module types - final DistributionSetType testType2 = distributionSetTypeManagement.create(entityFactory.distributionSetType() - .create().key("testType2").name("testType2").description("testType2").colour("col12")); + final DistributionSetType testType2 = distributionSetTypeManagement.create( + DistributionSetTypeManagement.Create.builder() + .key("testType2").name("testType2").description("testType2").colour("col12").build()); assertThat(testType2.getOptLockRevision()).isEqualTo(1); for (int i = 0; i < moduleTypeIds.size() - 1; ++i) { @@ -385,10 +396,10 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati @Test @WithUser(principal = "uploadTester", allSpPermissions = true) void getDistributionSetType() throws Exception { - DistributionSetType testType = distributionSetTypeManagement.create(entityFactory.distributionSetType().create() - .key("test123").name("TestName123").description("Desc123")); + DistributionSetType testType = distributionSetTypeManagement.create(DistributionSetTypeManagement.Create.builder() + .key("test123").name("TestName123").description("Desc123").build()); testType = distributionSetTypeManagement - .update(entityFactory.distributionSetType().update(testType.getId()).description("Desc1234")); + .update(DistributionSetTypeManagement.Update.builder().id(testType.getId()).description("Desc1234").build()); mvc.perform(get("/rest/v1/distributionsettypes/{dstId}", testType.getId()).accept(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print()) @@ -420,8 +431,9 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati @Test @WithUser(principal = "uploadTester", allSpPermissions = true) void deleteDistributionSetTypeUnused() throws Exception { - final DistributionSetType testType = distributionSetTypeManagement.create(entityFactory.distributionSetType() - .create().key("test123").name("TestName123").description("Desc123").colour("col12")); + final DistributionSetType testType = distributionSetTypeManagement.create( + DistributionSetTypeManagement.Create.builder() + .key("test123").name("TestName123").description("Desc123").colour("col12").build()); assertThat(distributionSetTypeManagement.count()).isEqualTo(DEFAULT_DS_TYPES + 1); @@ -448,11 +460,14 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati @Test @WithUser(principal = "uploadTester", allSpPermissions = true) void deleteDistributionSetTypeUsed() throws Exception { - final DistributionSetType testType = distributionSetTypeManagement.create(entityFactory.distributionSetType() - .create().key("test123").name("TestName123").description("Desc123").colour("col12")); + final DistributionSetType testType = distributionSetTypeManagement.create( + DistributionSetTypeManagement.Create.builder() + .key("test123").name("TestName123").description("Desc123").colour("col12").build()); - distributionSetManagement.create(entityFactory.distributionSet().create().name("sdfsd").description("dsfsdf") - .version("1").type(testType)); + distributionSetManagement.create(DistributionSetManagement.Create.builder() + .type(distributionSetTypeManagement.findByKey(testType.getKey()).orElseThrow()) + .name("sdfsd").version("1").description("dsfsdf") + .build()); assertThat(distributionSetTypeManagement.count()).isEqualTo(DEFAULT_DS_TYPES + 1); assertThat(distributionSetManagement.count()).isEqualTo(1); @@ -480,8 +495,9 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati */ @Test void updateDistributionSetTypeColourDescriptionAndNameUntouched() throws Exception { - final DistributionSetType testType = distributionSetTypeManagement.create(entityFactory.distributionSetType() - .create().key("test123").name("TestName123").description("Desc123").colour("col")); + final DistributionSetType testType = distributionSetTypeManagement.create( + DistributionSetTypeManagement.Create.builder() + .key("test123").name("TestName123").description("Desc123").colour("col").build()); final String body = new JSONObject().put("id", testType.getId()).put("description", "foobardesc") .put("colour", "updatedColour") @@ -503,8 +519,9 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati */ @Test void updateDistributionSetTypeDescriptionAndColor() throws Exception { - final DistributionSetType testType = distributionSetTypeManagement.update(entityFactory.distributionSetType() - .update(testdataFactory.createDistributionSet().getType().getId()).description("Desc1234")); + final DistributionSetType testType = distributionSetTypeManagement.update( + DistributionSetTypeManagement.Update.builder() + .id(testdataFactory.createDistributionSet().getType().getId()).description("Desc1234").build()); final String body = new JSONObject() .put("description", "an updated description") .put("colour", "rgb(106,178,83)").toString(); @@ -522,7 +539,7 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati @Test void updateDistributionSetTypeDeletedFlag() throws Exception { final DistributionSetType testType = distributionSetTypeManagement - .create(entityFactory.distributionSetType().create().key("test123").name("TestName123").colour("col")); + .create(DistributionSetTypeManagement.Create.builder().key("test123").name("TestName123").colour("col").build()); final String body = new JSONObject().put("id", testType.getId()).put("deleted", true).toString(); @@ -591,7 +608,7 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati @Test void invalidRequestsOnDistributionSetTypesResource() throws Exception { final SoftwareModuleType testSmType = softwareModuleTypeManagement - .create(entityFactory.softwareModuleType().create().key("test123").name("TestName123")); + .create(SoftwareModuleTypeManagement.Create.builder().key("test123").name("TestName123").build()); // DST does not exist mvc.perform(get("/rest/v1/distributionsettypes/12345678")) @@ -645,12 +662,15 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati // Modules types at creation time invalid - final DistributionSetType testNewType = entityFactory.distributionSetType().create().key("test123") - .name("TestName123").description("Desc123").colour("col").mandatory(Collections.singletonList(osType.getId())) - .optional(Collections.emptyList()).build(); + final DistributionSetTypeManagement.Create testNewType = DistributionSetTypeManagement.Create.builder() + .key("test123") + .name("TestName123").description("Desc123").colour("col") + .mandatoryModuleTypes(Set.of(osType)) + .optionalModuleTypes(Collections.emptySet()) + .build(); mvc.perform(post("/rest/v1/distributionsettypes") - .content(JsonBuilder.distributionSetTypes(Collections.singletonList(testNewType))) + .content(JsonBuilder.distributionSetTypes(List.of(testNewType))) .contentType(MediaType.APPLICATION_OCTET_STREAM)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isUnsupportedMediaType()); @@ -672,12 +692,12 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati .andDo(MockMvcResultPrinter.print()) .andExpect(status().isBadRequest()); - final DistributionSetType toLongName = entityFactory.distributionSetType().create() + final DistributionSetTypeManagement.Create toLongName = DistributionSetTypeManagement.Create.builder() .key("test123") .name(randomString(NamedEntity.NAME_MAX_SIZE + 1)) .build(); mvc.perform(post("/rest/v1/distributionsettypes") - .content(JsonBuilder.distributionSetTypes(Collections.singletonList(toLongName))) + .content(JsonBuilder.distributionSetTypes(List.of(toLongName))) .contentType(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isBadRequest()); @@ -706,9 +726,9 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati @Test void searchDistributionSetTypeRsql() throws Exception { distributionSetTypeManagement - .create(entityFactory.distributionSetType().create().key("test123").name("TestName123")); + .create(DistributionSetTypeManagement.Create.builder().key("test123").name("TestName123").build()); distributionSetTypeManagement - .create(entityFactory.distributionSetType().create().key("test1234").name("TestName1234")); + .create(DistributionSetTypeManagement.Create.builder().key("test1234").name("TestName1234").build()); final String rsqlFindLikeDs1OrDs2 = "name==TestName123,name==TestName1234"; @@ -731,17 +751,17 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati assertThat(created2.getOptionalModuleTypes()).containsOnly(osType, runtimeType, appType); assertThat(created3.getMandatoryModuleTypes()).containsOnly(osType, runtimeType); - assertThat((Object)JsonPath.compile("[0]_links.self.href").read(mvcResult.getResponse().getContentAsString())) + assertThat((Object) JsonPath.compile("[0]_links.self.href").read(mvcResult.getResponse().getContentAsString())) .hasToString("http://localhost/rest/v1/distributionsettypes/" + created1.getId()); - assertThat((Object)JsonPath.compile("[1]_links.self.href").read(mvcResult.getResponse().getContentAsString())) + assertThat((Object) JsonPath.compile("[1]_links.self.href").read(mvcResult.getResponse().getContentAsString())) .hasToString("http://localhost/rest/v1/distributionsettypes/" + created2.getId()); - assertThat((Object)JsonPath.compile("[2]_links.self.href").read(mvcResult.getResponse().getContentAsString())) + assertThat((Object) JsonPath.compile("[2]_links.self.href").read(mvcResult.getResponse().getContentAsString())) .hasToString("http://localhost/rest/v1/distributionsettypes/" + created3.getId()); assertThat(distributionSetTypeManagement.count()).isEqualTo(7); } - private MvcResult runPostDistributionSetType(final List types) throws Exception { + private MvcResult runPostDistributionSetType(final List types) throws Exception { return mvc .perform(post("/rest/v1/distributionsettypes").content(JsonBuilder.distributionSetTypes(types)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) @@ -765,24 +785,32 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati .andReturn(); } - private List createTestDistributionSetTestTypes() { + private List createTestDistributionSetTestTypes() { assertThat(distributionSetTypeManagement.count()).isEqualTo(DEFAULT_DS_TYPES); return Arrays.asList( - entityFactory.distributionSetType().create().key("testKey1").name("TestName1").description("Desc1") - .colour("col").mandatory(Collections.singletonList(osType.getId())) - .optional(Collections.singletonList(runtimeType.getId())).build(), - entityFactory.distributionSetType().create().key("testKey2").name("TestName2").description("Desc2") - .colour("col").optional(Arrays.asList(runtimeType.getId(), osType.getId(), appType.getId())) - .build(), - entityFactory.distributionSetType().create().key("testKey3").name("TestName3").description("Desc3") - .colour("col").mandatory(Arrays.asList(runtimeType.getId(), osType.getId())).build()); + DistributionSetTypeManagement.Create.builder() + .key("testKey1").name("TestName1").description("Desc1").colour("col") + .mandatoryModuleTypes(Set.of(osType)) + .optionalModuleTypes(Set.of(runtimeType)) + .build(), + DistributionSetTypeManagement.Create.builder() + .key("testKey2").name("TestName2").description("Desc2").colour("col") + .optionalModuleTypes(Set.of(runtimeType, osType, appType)) + .build(), + DistributionSetTypeManagement.Create.builder() + .key("testKey3").name("TestName3").description("Desc3").colour("col") + .mandatoryModuleTypes(Set.of(runtimeType, osType)) + .build()); } private DistributionSetType generateTestType() { - final DistributionSetType testType = distributionSetTypeManagement.create(entityFactory.distributionSetType() - .create().key("test123").name("TestName123").description("Desc123").colour("col") - .mandatory(Collections.singletonList(osType.getId())).optional(Collections.singletonList(appType.getId()))); + final DistributionSetType testType = distributionSetTypeManagement.create( + DistributionSetTypeManagement.Create.builder() + .key("test123").name("TestName123").description("Desc123").colour("col") + .mandatoryModuleTypes(Set.of(osType)) + .optionalModuleTypes(Set.of(appType)) + .build()); assertThat(testType.getOptLockRevision()).isEqualTo(1); assertThat(testType.getOptionalModuleTypes()).containsExactly(appType); assertThat(testType.getMandatoryModuleTypes()).containsExactly(osType); diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java index 5580490b1..55118edb7 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java @@ -45,6 +45,7 @@ import org.eclipse.hawkbit.mgmt.rest.api.MgmtRepresentationMode; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; import org.eclipse.hawkbit.mgmt.rest.resource.util.ResourceUtility; import org.eclipse.hawkbit.repository.Constants; +import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.FileSizeQuotaExceededException; @@ -98,12 +99,10 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes * Trying to create a SM from already marked as deleted type - should get as response 400 Bad Request */ @Test - void createSMFromAlreadyMarkedAsDeletedType() throws Exception { + void createSMFromAlreadyMarkedAsDeletedType() throws Exception { final String SM_TYPE = "someSmType"; final SoftwareModule sm = testdataFactory.createSoftwareModule(SM_TYPE); - testdataFactory.findOrCreateDistributionSetType( - "testKey", "testType", Collections.singletonList(sm.getType()), - Collections.singletonList(sm.getType())); + testdataFactory.findOrCreateDistributionSetType("testKey", "testType", List.of(sm.getType()), List.of()); final DistributionSetType type = testdataFactory.findOrCreateDistributionSetType("testKey", "testType"); final DistributionSet ds = testdataFactory.createDistributionSet("name", "version", type, Collections.singletonList(sm)); final Target target = testdataFactory.createTarget("test"); @@ -113,7 +112,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes softwareModuleTypeManagement.delete(sm.getType().getId()); //check if it is marked as deleted - final Optional opt = softwareModuleTypeManagement.findByKey(SM_TYPE); + final Optional opt = softwareModuleTypeManagement.findByKey(SM_TYPE); if (opt.isEmpty()) { throw new AssertionError("The Optional object of software module type should not be empty!"); } @@ -137,7 +136,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes * Handles the GET request of retrieving all meta data of artifacts assigned to a software module (in full representation mode including a download URL by the artifact provider). */ @Test - void getArtifactsWithParameters() throws Exception { + void getArtifactsWithParameters() throws Exception { final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); final byte[] random = randomBytes(5); @@ -153,14 +152,14 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes } /** - * Get a paged list of meta data for a software module. + * Get a paged list of meta data for a software module. */ @Test - void getMetadata() throws Exception { + void getMetadata() throws Exception { final int totalMetadata = 4; final String knownKeyPrefix = "knownKey"; final String knownValuePrefix = "knownValue"; - final SoftwareModule module = testdataFactory.createDistributionSet("one").findFirstModuleByType(osType).get(); + final SoftwareModule module = findFirstModuleByType(testdataFactory.createDistributionSet("one"), osType).get(); for (int index = 0; index < totalMetadata; index++) { softwareModuleManagement.updateMetadata(entityFactory.softwareModuleMetadata().create(module.getId()) @@ -175,14 +174,14 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes } /** - * Get a paged list of meta data for a software module with defined page size and sorting by name descending and key starting with 'known'. + * Get a paged list of meta data for a software module with defined page size and sorting by name descending and key starting with 'known'. */ @Test - void getMetadataWithParameters() throws Exception { + void getMetadataWithParameters() throws Exception { final int totalMetadata = 4; final String knownKeyPrefix = "knownKey"; final String knownValuePrefix = "knownValue"; - final SoftwareModule module = testdataFactory.createDistributionSet("one").findFirstModuleByType(osType).get(); + final SoftwareModule module = findFirstModuleByType(testdataFactory.createDistributionSet("one"), osType).orElseThrow(); for (int index = 0; index < totalMetadata; index++) { softwareModuleManagement.updateMetadata(entityFactory.softwareModuleMetadata().create(module.getId()) @@ -201,23 +200,23 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes * Get a single meta data value for a meta data key. */ @Test - void getMetadataValue() throws Exception { + void getMetadataValue() throws Exception { // prepare and create metadata final String knownKey = "knownKey"; final String knownValue = "knownValue"; - final SoftwareModule module = testdataFactory.createDistributionSet("one").findFirstModuleByType(osType).get(); + final SoftwareModule module = findFirstModuleByType(testdataFactory.createDistributionSet("one"), osType).orElseThrow(); softwareModuleManagement.updateMetadata( entityFactory.softwareModuleMetadata().create(module.getId()).key(knownKey).value(knownValue)); mvc.perform(get(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/metadata/{metadataKey}", - module.getId(), knownKey)) + module.getId(), knownKey)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isOk()); } /** - * Tests the update of software module metadata. It is verfied that only the selected fields for the update are really updated and the modification values are filled (i.e. updated by and at). + * Tests the update of software module metadata. It is verified that only the selected fields for the update are really updated and the modification values are filled (i.e. updated by and at). */ @Test @WithUser(principal = "smUpdateTester", allSpPermissions = true) @@ -230,13 +229,13 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes final String updateVendor = "newVendor1"; final String updateDescription = "newDescription1"; - final SoftwareModule sm = softwareModuleManagement.create(entityFactory.softwareModule() - .create() + final SoftwareModule sm = softwareModuleManagement.create(SoftwareModuleManagement.Create.builder() .type(osType) .name(knownSWName) .version(knownSWVersion) .description(knownSWDescription) - .vendor(knownSWVendor)); + .vendor(knownSWVendor) + .build()); assertThat(sm.getName()).as("Wrong name of the software module").isEqualTo(knownSWName); @@ -279,7 +278,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes final String knownSWVersion = "version1"; final SoftwareModule sm = softwareModuleManagement.create( - entityFactory.softwareModule().create().type(osType).name(knownSWName).version(knownSWVersion)); + SoftwareModuleManagement.Create.builder().type(osType).name(knownSWName).version(knownSWVersion).build()); assertThat(sm.isDeleted()).as("Created software module should not be deleted").isFalse(); @@ -311,7 +310,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes @WithUser(principal = "smUpdateTester", allSpPermissions = true) void lockSoftwareModule() throws Exception { final SoftwareModule sm = softwareModuleManagement.create( - entityFactory.softwareModule().create().type(osType).name("name1").version("version1")); + SoftwareModuleManagement.Create.builder().type(osType).name("name1").version("version1").build()); assertThat(sm.isLocked()).as("Created software module should not be locked").isFalse(); // ensures that we are not to fast so that last modified is not set correctly await().until(() -> sm.getLastModifiedAt() > 0L && sm.getLastModifiedBy() != null); @@ -342,7 +341,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes @WithUser(principal = "smUpdateTester", allSpPermissions = true) void unlockSoftwareModule() throws Exception { final SoftwareModule sm = softwareModuleManagement.create( - entityFactory.softwareModule().create().type(osType).name("name1").version("version1")); + SoftwareModuleManagement.Create.builder().type(osType).name("name1").version("version1").build()); softwareModuleManagement.lock(sm.getId()); assertThat(softwareModuleManagement.get(sm.getId()) .orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, sm.getId())).isLocked()) @@ -402,10 +401,10 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes mvcResult.getResponse().getContentAsString()); final Long artId = softwareModuleManagement.get(sm.getId()).get().getArtifacts().get(0).getId(); assertThat(artResult.getId()).as("Wrong artifact id").isEqualTo(artId); - assertThat((Object)JsonPath.compile("$._links.self.href").read(mvcResult.getResponse().getContentAsString())) + assertThat((Object) JsonPath.compile("$._links.self.href").read(mvcResult.getResponse().getContentAsString())) .as("Link contains no self url") .hasToString("http://localhost/rest/v1/softwaremodules/" + sm.getId() + "/artifacts/" + artId); - assertThat((Object)JsonPath.compile("$._links.download.href").read(mvcResult.getResponse().getContentAsString())) + assertThat((Object) JsonPath.compile("$._links.download.href").read(mvcResult.getResponse().getContentAsString())) .as("response contains no download url ") .hasToString("http://localhost/rest/v1/softwaremodules/" + sm.getId() + "/artifacts/" + artId + "/download"); @@ -772,11 +771,9 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes .andExpect(jsonPath("$.providedFilename", equalTo("file1"))) .andExpect(jsonPath("$._links.download.href", useArtifactUrlHandler ? equalTo("http://download-cdn.com/artifacts/%s/download".formatted(artifact.getFilename())) - : equalTo("http://localhost/rest/v1/softwaremodules/%s/artifacts/%s/download" - .formatted(sm.getId(), artifact.getId())))) + : equalTo("http://localhost/rest/v1/softwaremodules/%s/artifacts/%s/download".formatted(sm.getId(), artifact.getId())))) .andExpect(jsonPath("$._links.self.href", equalTo( - "http://localhost/rest/v1/softwaremodules/%s/artifacts/%s".formatted(sm.getId(), - artifact.getId())))); + "http://localhost/rest/v1/softwaremodules/%s/artifacts/%s".formatted(sm.getId(), artifact.getId())))); } /** @@ -785,14 +782,16 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes @Test void getArtifactSoftDeleted() throws Exception { // prepare data for test - final SoftwareModule sm = testdataFactory.createSoftwareModuleOs("softDeleted"); + SoftwareModule sm = testdataFactory.createSoftwareModuleOs("softDeleted"); final Artifact artifact = testdataFactory.createArtifacts(sm.getId()).get(0); - testdataFactory.createDistributionSet(Collections.singletonList(sm)); + // the sm is changed by artifact creation, necessary to get the latest version for Hibernate + sm = softwareModuleManagement.get(sm.getId()).orElseThrow(); + testdataFactory.createDistributionSet(List.of(sm)); softwareModuleManagement.delete(sm.getId()); // perform test - mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts/{artId}", sm.getId(), artifact.getId()).accept( - MediaType.APPLICATION_JSON)) + mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts/{artId}", sm.getId(), artifact.getId()) + .accept(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) @@ -900,18 +899,18 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes */ @Test void invalidRequestsOnArtifactResource() throws Exception { - final int artifactSize = 5 * 1024; final byte[] random = randomBytes(artifactSize); final MockMultipartFile file = new MockMultipartFile("file", "orig", null, random); - final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); - - final SoftwareModule smSoftDeleted = testdataFactory.createSoftwareModuleOs("softDeleted"); + SoftwareModule smSoftDeleted = testdataFactory.createSoftwareModuleOs("softDeleted"); final Artifact artifactSoftDeleted = testdataFactory.createArtifacts(smSoftDeleted.getId()).get(0); + // the smSoftDeleted is changed by artifact creation, necessary to get the latest version for Hibernate + smSoftDeleted = softwareModuleManagement.get(smSoftDeleted.getId()).orElseThrow(); testdataFactory.createDistributionSet(List.of(smSoftDeleted)); softwareModuleManagement.delete(smSoftDeleted.getId()); + final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); // no artifact available mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts/1234567/download", sm.getId())) .andDo(MockMvcResultPrinter.print()) @@ -996,8 +995,6 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes void invalidRequestsOnSoftwareModulesResource() throws Exception { final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); - final List modules = Collections.singletonList(sm); - // SM does not exist mvc.perform(get("/rest/v1/softwaremodules/12345678")) .andDo(MockMvcResultPrinter.print()) @@ -1024,7 +1021,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes .andDo(MockMvcResultPrinter.print()) .andExpect(status().isBadRequest()); - final SoftwareModule toLongName = entityFactory.softwareModule().create().type(osType) + final SoftwareModuleManagement.Create toLongName = SoftwareModuleManagement.Create.builder().type(osType) .name(randomString(80)).build(); mvc.perform(post("/rest/v1/softwaremodules").content(JsonBuilder.softwareModules(Collections.singletonList(toLongName))) .contentType(MediaType.APPLICATION_JSON)) @@ -1032,16 +1029,22 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes .andExpect(status().isBadRequest()); // unsupported media type - mvc.perform(post("/rest/v1/softwaremodules").content(JsonBuilder.softwareModules(modules)) + mvc.perform(post("/rest/v1/softwaremodules") + .content(JsonBuilder.softwareModules(List.of(SoftwareModuleManagement.Create.builder() + .type(sm.getType()) + .name(sm.getName()) + .version(sm.getVersion()) + .build()))) .contentType(MediaType.APPLICATION_OCTET_STREAM)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isUnsupportedMediaType()); - final SoftwareModule swm = entityFactory.softwareModule().create().name("encryptedModule").type(osType) + final SoftwareModuleManagement.Create swm = SoftwareModuleManagement.Create.builder() + .name("encryptedModule").type(osType) .version("version").vendor("vendor").description("description").encrypted(true).build(); // artifact decryption is not supported mvc.perform( - post("/rest/v1/softwaremodules").content(JsonBuilder.softwareModules(Collections.singletonList(swm))) + post("/rest/v1/softwaremodules").content(JsonBuilder.softwareModules(List.of(swm))) .contentType(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isBadRequest()); @@ -1270,16 +1273,14 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes @Test @WithUser(principal = "uploadTester", allSpPermissions = true) void createSoftwareModules() throws Exception { - final SoftwareModule os = entityFactory.softwareModule() - .create() + final SoftwareModuleManagement.Create os = SoftwareModuleManagement.Create.builder() .name("name1") .type(osType) .version("version1") .vendor("vendor1") .description("description1") .build(); - final SoftwareModule ah = entityFactory.softwareModule() - .create() + final SoftwareModuleManagement.Create ah = SoftwareModuleManagement.Create.builder() .name("name3") .type(appType) .version("version3") @@ -1287,7 +1288,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes .description("description3") .build(); - final List modules = Arrays.asList(os, ah); + final List modules = Arrays.asList(os, ah); final long current = System.currentTimeMillis(); @@ -1375,7 +1376,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes final int artifactSize = 5 * 1024; final byte[] random = randomBytes(artifactSize); - final Long appTypeSmId = ds1.findFirstModuleByType(appType).get().getId(); + final Long appTypeSmId = findFirstModuleByType(ds1, appType).get().getId(); artifactManagement.create( new ArtifactUpload(new ByteArrayInputStream(random), appTypeSmId, "file1", false, artifactSize)); @@ -1535,7 +1536,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes // binary try (final InputStream fileInputStream = artifactManagement - .loadArtifactBinary(softwareModuleManagement.get(sm.getId()).get().getArtifacts().get(0).getSha1Hash(), + .loadArtifactBinary(softwareModuleManagement.get(sm.getId()).orElseThrow().getArtifacts().get(0).getSha1Hash(), sm.getId(), sm.isEncrypted()) .get().getFileInputStream()) { assertTrue(IOUtils.contentEquals(new ByteArrayInputStream(random), fileInputStream), @@ -1543,17 +1544,17 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes } // hashes - assertThat(artifactManagement.getByFilename("origFilename").get().getSha1Hash()).as("Wrong sha1 hash") + assertThat(artifactManagement.getByFilename("origFilename").orElseThrow().getSha1Hash()).as("Wrong sha1 hash") .isEqualTo(HashGeneratorUtils.generateSHA1(random)); - assertThat(artifactManagement.getByFilename("origFilename").get().getMd5Hash()).as("Wrong md5 hash") + assertThat(artifactManagement.getByFilename("origFilename").orElseThrow().getMd5Hash()).as("Wrong md5 hash") .isEqualTo(HashGeneratorUtils.generateMD5(random)); - assertThat(artifactManagement.getByFilename("origFilename").get().getSha256Hash()).as("Wrong sha256 hash") + assertThat(artifactManagement.getByFilename("origFilename").orElseThrow().getSha256Hash()).as("Wrong sha256 hash") .isEqualTo(HashGeneratorUtils.generateSHA256(random)); // metadata - assertThat(softwareModuleManagement.get(sm.getId()).get().getArtifacts().get(0).getFilename()) + assertThat(softwareModuleManagement.get(sm.getId()).orElseThrow().getArtifacts().get(0).getFilename()) .as("wrong metadata of the filename").isEqualTo("origFilename"); } @@ -1574,8 +1575,8 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes char character = 'a'; for (int index = 0; index < amount; index++) { final String str = String.valueOf(character); - softwareModuleManagement.create(entityFactory.softwareModule().create().type(osType).name(str) - .description(str).vendor(str).version(str)); + softwareModuleManagement.create( + SoftwareModuleManagement.Create.builder().type(osType).name(str).description(str).vendor(str).version(str).build()); character++; } } diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleTypeResourceTest.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleTypeResourceTest.java index b50d16fcc..3e4a4e4e2 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleTypeResourceTest.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleTypeResourceTest.java @@ -29,6 +29,8 @@ import java.util.List; import com.jayway.jsonpath.JsonPath; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; +import org.eclipse.hawkbit.repository.SoftwareModuleManagement; +import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; import org.eclipse.hawkbit.repository.model.NamedEntity; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.test.util.WithUser; @@ -101,7 +103,8 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractManagementApiInt public void getSoftwareModuleTypesWithParameters() throws Exception { final SoftwareModuleType testType = testdataFactory.findOrCreateSoftwareModuleType("test123"); softwareModuleTypeManagement - .update(entityFactory.softwareModuleType().update(testType.getId()).description("Desc1234").colour("rgb(106,178,83)")); + .update(SoftwareModuleTypeManagement.Update.builder().id(testType.getId()).description("Desc1234").colour("rgb(106,178,83)") + .build()); mvc.perform(get(MgmtRestConstants.SOFTWAREMODULETYPE_V1_REQUEST_MAPPING + "?limit=10&sort=name:ASC&offset=0&q=name==a") .accept(MediaType.APPLICATION_JSON)) @@ -160,19 +163,18 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractManagementApiInt @WithUser(principal = "uploadTester", allSpPermissions = true) public void createSoftwareModuleTypesInvalidAssignmentBadRequest() throws Exception { - final List types = new ArrayList<>(); - types.add(entityFactory.softwareModuleType().create().key("test-1").name("TestName-1").maxAssignments(-1) - .build()); + final List types = new ArrayList<>(); + types.add(SoftwareModuleTypeManagement.Create.builder().key("test-1").name("TestName-1").maxAssignments(-1).build()); - mvc.perform(post("/rest/v1/softwaremoduletypes").content(JsonBuilder.softwareModuleTypes(types)) + mvc.perform(post("/rest/v1/softwaremoduletypes").content(JsonBuilder.softwareModuleTypeCreates(types)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isBadRequest()); types.clear(); - types.add(entityFactory.softwareModuleType().create().key("test0").name("TestName0").maxAssignments(0).build()); + types.add(SoftwareModuleTypeManagement.Create.builder().key("test0").name("TestName0").maxAssignments(0).build()); - mvc.perform(post("/rest/v1/softwaremoduletypes").content(JsonBuilder.softwareModuleTypes(types)) + mvc.perform(post("/rest/v1/softwaremoduletypes").content(JsonBuilder.softwareModuleTypeCreates(types)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isBadRequest()); @@ -185,16 +187,16 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractManagementApiInt @WithUser(principal = "uploadTester", allSpPermissions = true) public void createSoftwareModuleTypes() throws Exception { - final List types = Arrays.asList( - entityFactory.softwareModuleType().create().key("test1").name("TestName1").description("Desc1") + final List types = Arrays.asList( + SoftwareModuleTypeManagement.Create.builder().key("test1").name("TestName1").description("Desc1") .colour("col1‚").maxAssignments(1).build(), - entityFactory.softwareModuleType().create().key("test2").name("TestName2").description("Desc2") + SoftwareModuleTypeManagement.Create.builder().key("test2").name("TestName2").description("Desc2") .colour("col2‚").maxAssignments(2).build(), - entityFactory.softwareModuleType().create().key("test3").name("TestName3").description("Desc3") + SoftwareModuleTypeManagement.Create.builder().key("test3").name("TestName3").description("Desc3") .colour("col3‚").maxAssignments(3).build()); final MvcResult mvcResult = mvc - .perform(post("/rest/v1/softwaremoduletypes").content(JsonBuilder.softwareModuleTypes(types)) + .perform(post("/rest/v1/softwaremoduletypes").content(JsonBuilder.softwareModuleTypeCreates(types)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isCreated()) @@ -223,9 +225,9 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractManagementApiInt assertThat((Object) JsonPath.compile("[0]_links.self.href").read(mvcResult.getResponse().getContentAsString())) .hasToString("http://localhost/rest/v1/softwaremoduletypes/" + created1.getId()); - assertThat((Object)JsonPath.compile("[1]_links.self.href").read(mvcResult.getResponse().getContentAsString())) + assertThat((Object) JsonPath.compile("[1]_links.self.href").read(mvcResult.getResponse().getContentAsString())) .hasToString("http://localhost/rest/v1/softwaremoduletypes/" + created2.getId()); - assertThat((Object)JsonPath.compile("[2]_links.self.href").read(mvcResult.getResponse().getContentAsString())) + assertThat((Object) JsonPath.compile("[2]_links.self.href").read(mvcResult.getResponse().getContentAsString())) .hasToString("http://localhost/rest/v1/softwaremoduletypes/" + created3.getId()); assertThat(softwareModuleTypeManagement.count()).isEqualTo(6); @@ -275,7 +277,7 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractManagementApiInt * Ensures that module type deletion request to API on an entity that does not exist results in NOT_FOUND. */ @Test - void deleteSoftwareModuleTypeThatDoesNotExistLeadsToNotFound() throws Exception { + void deleteSoftwareModuleTypeThatDoesNotExistLeadsToNotFound() throws Exception { mvc.perform(delete("/rest/v1/softwaremoduletypes/1234")) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isNotFound()); @@ -289,7 +291,7 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractManagementApiInt public void deleteSoftwareModuleTypeUsed() throws Exception { final SoftwareModuleType testType = createTestType(); softwareModuleManagement - .create(entityFactory.softwareModule().create().type(testType).name("name").version("version")); + .create(SoftwareModuleManagement.Create.builder().type(testType).name("name").version("version").build()); assertThat(softwareModuleTypeManagement.count()).isEqualTo(4); @@ -314,7 +316,7 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractManagementApiInt * Checks the correct behaviour of /rest/v1/softwaremoduletypes/{ID} PUT requests. */ @Test - void updateSoftwareModuleTypeColourDescriptionAndNameUntouched() throws Exception { + void updateSoftwareModuleTypeColourDescriptionAndNameUntouched() throws Exception { final SoftwareModuleType testType = createTestType(); final String body = new JSONObject().put("id", testType.getId()).put("description", "foobardesc") @@ -336,7 +338,7 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractManagementApiInt * Tests the update of the deletion flag. It is verfied that the software module type can't be marked as deleted through update operation. */ @Test - void updateSoftwareModuleTypeDeletedFlag() throws Exception { + void updateSoftwareModuleTypeDeletedFlag() throws Exception { SoftwareModuleType testType = createTestType(); final String body = new JSONObject().put("id", testType.getId()).put("deleted", true).toString(); @@ -358,7 +360,7 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractManagementApiInt * Checks the correct behaviour of /rest/v1/softwaremoduletypes GET requests with paging. */ @Test - void getSoftwareModuleTypesWithoutAddtionalRequestParameters() throws Exception { + void getSoftwareModuleTypesWithoutAddtionalRequestParameters() throws Exception { final int types = 3; mvc.perform(get(MgmtRestConstants.SOFTWAREMODULETYPE_V1_REQUEST_MAPPING)) .andDo(MockMvcResultPrinter.print()) @@ -372,7 +374,7 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractManagementApiInt * Checks the correct behaviour of /rest/v1/softwaremoduletypes GET requests with paging. */ @Test - void getSoftwareModuleTypesWithPagingLimitRequestParameter() throws Exception { + void getSoftwareModuleTypesWithPagingLimitRequestParameter() throws Exception { final int types = 3; final int limitSize = 1; mvc.perform(get(MgmtRestConstants.SOFTWAREMODULETYPE_V1_REQUEST_MAPPING) @@ -388,7 +390,7 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractManagementApiInt * Checks the correct behaviour of /rest/v1/softwaremoduletypes GET requests with paging. */ @Test - void getSoftwareModuleTypesWithPagingLimitAndOffsetRequestParameter() throws Exception { + void getSoftwareModuleTypesWithPagingLimitAndOffsetRequestParameter() throws Exception { final int types = 3; final int offsetParam = 2; final int expectedSize = types - offsetParam; @@ -406,10 +408,13 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractManagementApiInt * Ensures that the server is behaving as expected on invalid requests (wrong media type, wrong ID etc.). */ @Test - void invalidRequestsOnSoftwaremoduleTypesResource() throws Exception { + void invalidRequestsOnSoftwareModuleTypesResource() throws Exception { final SoftwareModuleType testType = createTestType(); - final List types = Collections.singletonList(testType); + final List types = List.of(SoftwareModuleTypeManagement.Create.builder() + .key(testType.getKey()) + .name(testType.getName()) + .build()); // SM does not exist mvc.perform(get("/rest/v1/softwaremoduletypes/12345678")) @@ -437,18 +442,18 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractManagementApiInt .andDo(MockMvcResultPrinter.print()) .andExpect(status().isBadRequest()); - final SoftwareModuleType toLongName = entityFactory.softwareModuleType().create() + final SoftwareModuleTypeManagement.Create toLongName = SoftwareModuleTypeManagement.Create.builder() .key("test123") .name(randomString(NamedEntity.NAME_MAX_SIZE + 1)) .build(); mvc.perform( - post("/rest/v1/softwaremoduletypes").content(JsonBuilder.softwareModuleTypes(Collections.singletonList(toLongName))) + post("/rest/v1/softwaremoduletypes").content(JsonBuilder.softwareModuleTypeCreates(Collections.singletonList(toLongName))) .contentType(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isBadRequest()); // unsupported media type - mvc.perform(post("/rest/v1/softwaremoduletypes").content(JsonBuilder.softwareModuleTypes(types)) + mvc.perform(post("/rest/v1/softwaremoduletypes").content(JsonBuilder.softwareModuleTypeCreates(types)) .contentType(MediaType.APPLICATION_OCTET_STREAM)) .andDo(MockMvcResultPrinter.print()) .andExpect(status().isUnsupportedMediaType()); @@ -468,11 +473,11 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractManagementApiInt * Search erquest of software module types. */ @Test - void searchSoftwareModuleTypeRsql() throws Exception { - softwareModuleTypeManagement.create(entityFactory.softwareModuleType().create().key("test123") - .name("TestName123").description("Desc123").maxAssignments(5)); - softwareModuleTypeManagement.create(entityFactory.softwareModuleType().create().key("test1234") - .name("TestName1234").description("Desc1234").maxAssignments(5)); + void searchSoftwareModuleTypeRsql() throws Exception { + softwareModuleTypeManagement.create(SoftwareModuleTypeManagement.Create.builder().key("test123") + .name("TestName123").description("Desc123").maxAssignments(5).build()); + softwareModuleTypeManagement.create(SoftwareModuleTypeManagement.Create.builder().key("test1234") + .name("TestName1234").description("Desc1234").maxAssignments(5).build()); final String rsqlFindLikeDs1OrDs2 = "name==TestName123,name==TestName1234"; @@ -487,10 +492,9 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractManagementApiInt } private SoftwareModuleType createTestType() { - SoftwareModuleType testType = softwareModuleTypeManagement.create(entityFactory.softwareModuleType().create() - .key("test123").name("TestName123").description("Desc123").colour("colour").maxAssignments(5)); - testType = softwareModuleTypeManagement - .update(entityFactory.softwareModuleType().update(testType.getId()).description("Desc1234")); - return testType; + final SoftwareModuleType testType = softwareModuleTypeManagement.create(SoftwareModuleTypeManagement.Create.builder() + .key("test123").name("TestName123").description("Desc123").colour("colour").maxAssignments(5).build()); + return softwareModuleTypeManagement + .update(SoftwareModuleTypeManagement.Update.builder().id(testType.getId()).description("Desc1234").build()); } } \ No newline at end of file diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetFilterQueryResourceTest.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetFilterQueryResourceTest.java index a51dfd88e..f8d4a64da 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetFilterQueryResourceTest.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetFilterQueryResourceTest.java @@ -31,6 +31,7 @@ import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtActionType; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; import org.eclipse.hawkbit.mgmt.rest.resource.mapper.MgmtRestModelMapper; import org.eclipse.hawkbit.mgmt.rest.resource.util.ResourceUtility; +import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.DeletedException; import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException; @@ -774,8 +775,10 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte private void verifyAutoAssignmentWithIncompleteDs(final TargetFilterQuery tfq) throws Exception { final DistributionSet incompleteDistributionSet = distributionSetManagement - .create(entityFactory.distributionSet().create().name("incomplete").version("1") - .type(testdataFactory.findOrCreateDefaultTestDsType())); + .create(DistributionSetManagement.Create.builder() + .type(testdataFactory.findOrCreateDefaultTestDsType()) + .name("incomplete").version("1") + .build()); mvc.perform(post(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + tfq.getId() + "/autoAssignDS") .content("{\"id\":" + incompleteDistributionSet.getId() + "}").contentType(MediaType.APPLICATION_JSON)) @@ -802,4 +805,4 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte private TargetFilterQuery createSingleTargetFilterQuery(final String name, final String query) { return targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name(name).query(query)); } -} +} \ No newline at end of file diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java index c4a168c51..52b902795 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java @@ -947,9 +947,9 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest { // test - final SoftwareModule os = ds.findFirstModuleByType(osType).get(); - final SoftwareModule jvm = ds.findFirstModuleByType(runtimeType).get(); - final SoftwareModule bApp = ds.findFirstModuleByType(appType).get(); + final SoftwareModule os = findFirstModuleByType(ds, osType).orElseThrow(); + final SoftwareModule jvm = findFirstModuleByType(ds, runtimeType).orElseThrow(); + final SoftwareModule bApp = findFirstModuleByType(ds,appType).orElseThrow(); mvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownControllerId + "/assignedDS")) .andExpect(status().isOk()) .andDo(MockMvcResultPrinter.print()) diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTenantManagementResourceTest.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTenantManagementResourceTest.java index 7209ca194..fb3109d2c 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTenantManagementResourceTest.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTenantManagementResourceTest.java @@ -24,6 +24,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.eclipse.hawkbit.im.authentication.SpPermission; import org.eclipse.hawkbit.mgmt.json.model.system.MgmtSystemTenantConfigurationValueRequest; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; +import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties; @@ -334,10 +335,10 @@ public class MgmtTenantManagementResourceTest extends AbstractManagementApiInteg } private Long createTestDistributionSetType() { - DistributionSetType testDefaultDsType = distributionSetTypeManagement.create(entityFactory.distributionSetType().create() - .key("test123").name("TestName123").description("TestDefaultDsType")); + DistributionSetType testDefaultDsType = distributionSetTypeManagement.create(DistributionSetTypeManagement.Create.builder() + .key("test123").name("TestName123").description("TestDefaultDsType").build()); testDefaultDsType = distributionSetTypeManagement - .update(entityFactory.distributionSetType().update(testDefaultDsType.getId()).description("TestDefaultDsType")); + .update(DistributionSetTypeManagement.Update.builder().id(testDefaultDsType.getId()).description("TestDefaultDsType").build()); return testDefaultDsType.getId(); } diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java index 2f380c14a..5c9f57249 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java @@ -40,7 +40,7 @@ public interface ArtifactManagement { * @return the total amount of local artifacts stored in the artifact * management */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) long count(); /** @@ -56,7 +56,7 @@ public interface ArtifactManagement { * @throws InvalidSHA1HashException if check against provided SHA1 checksum failed * @throws ConstraintViolationException if {@link ArtifactUpload} contains invalid values */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY) + @PreAuthorize(SpringEvalExpressions.HAS_CREATE_REPOSITORY) Artifact create(@NotNull @Valid ArtifactUpload artifactUpload); /** @@ -66,7 +66,7 @@ public interface ArtifactManagement { * @throws ArtifactDeleteFailedException if deletion failed (MongoDB is not available) * @throws EntityNotFoundException if artifact with given ID does not exist */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY) + @PreAuthorize(SpringEvalExpressions.HAS_DELETE_REPOSITORY) void delete(long id); /** @@ -75,7 +75,7 @@ public interface ArtifactManagement { * @param id to search for * @return found {@link Artifact} */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR + SpringEvalExpressions.IS_CONTROLLER) Optional get(long id); @@ -87,7 +87,7 @@ public interface ArtifactManagement { * @return found {@link Artifact} * @throws EntityNotFoundException if software module with given ID does not exist */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR + SpringEvalExpressions.IS_CONTROLLER) Optional getByFilenameAndSoftwareModule(@NotNull String filename, long softwareModuleId); @@ -97,7 +97,7 @@ public interface ArtifactManagement { * @param sha1 the sha1 * @return the first local artifact */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR + SpringEvalExpressions.IS_CONTROLLER) Optional findFirstBySHA1(@NotNull String sha1); @@ -107,7 +107,7 @@ public interface ArtifactManagement { * @param filename to search for * @return found List of {@link Artifact}s. */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR + SpringEvalExpressions.IS_CONTROLLER) Optional getByFilename(@NotNull String filename); @@ -119,7 +119,7 @@ public interface ArtifactManagement { * @return Page * @throws EntityNotFoundException if software module with given ID does not exist */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) Page findBySoftwareModule(long softwareModuleId, @NotNull Pageable pageable); /** @@ -129,7 +129,7 @@ public interface ArtifactManagement { * @return count by software module * @throws EntityNotFoundException if software module with given ID does not exist */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) long countBySoftwareModule(long softwareModuleId); /** diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/BaseRepositoryTypeProvider.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/BaseRepositoryTypeProvider.java deleted file mode 100644 index d019d5db0..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/BaseRepositoryTypeProvider.java +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (c) 2021 Bosch.IO GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository; - -/** - * Provider that returns a base repository implementation dynamically based on repository type - */ -@FunctionalInterface -public interface BaseRepositoryTypeProvider { - - /** - * Return a base repository implementation that shall be used based on provided repository type - * - * @param repositoryType type of repository - * @return base repository implementation class - */ - Class getBaseRepositoryType(final Class repositoryType); -} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ConfirmationManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ConfirmationManagement.java index a5b9300e4..5f75e8016 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ConfirmationManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ConfirmationManagement.java @@ -26,6 +26,8 @@ import org.springframework.security.access.prepost.PreAuthorize; */ public interface ConfirmationManagement { + String CONFIRMATION_CODE_MSG_PREFIX = "Confirmation status code: %d"; + /** * Activate auto confirmation for a given controller ID. In case auto confirmation is active already, this method will fail with an exception. * diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java index 107bb46c0..88955d0ee 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java @@ -121,7 +121,7 @@ public interface DeploymentManagement { @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET) List offlineAssignedDistributionSets(Collection> assignments, String initiatedBy); - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) List offlineAssignedDistributionSets(Collection> assignments); /** diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java index ae1af1f7f..d4c5bbf07 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java @@ -9,20 +9,25 @@ */ package org.eclipse.hawkbit.repository; -import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AUTH_READ_DISTRIBUTION_SET; -import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AUTH_UPDATE_DISTRIBUTION_SET; +import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_READ_REPOSITORY; +import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_UPDATE_REPOSITORY; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; +import java.util.Set; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; -import org.eclipse.hawkbit.im.authentication.SpringEvalExpressions; -import org.eclipse.hawkbit.repository.builder.DistributionSetCreate; -import org.eclipse.hawkbit.repository.builder.DistributionSetUpdate; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; +import lombok.experimental.SuperBuilder; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; @@ -35,6 +40,9 @@ import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThis import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetFilter; import org.eclipse.hawkbit.repository.model.DistributionSetTag; +import org.eclipse.hawkbit.repository.model.DistributionSetType; +import org.eclipse.hawkbit.repository.model.NamedEntity; +import org.eclipse.hawkbit.repository.model.NamedVersionedEntity; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.Statistic; import org.springframework.data.domain.Page; @@ -45,7 +53,14 @@ import org.springframework.security.access.prepost.PreAuthorize; /** * Management service for {@link DistributionSet}s. */ -public interface DistributionSetManagement extends RepositoryManagement { +public interface DistributionSetManagement + extends RepositoryManagement { + + @Override + default String permissionGroup() { + return "DISTRIBUTION_SET"; + } + /** * Find {@link DistributionSet} based on given ID including (lazy loaded) details, e.g. {@link DistributionSet#getModules()}.
@@ -54,8 +69,8 @@ public interface DistributionSetManagement extends RepositoryManagement getWithDetails(long id); + @PreAuthorize(HAS_READ_REPOSITORY) + Optional getWithDetails(long id); /** * Find distribution set by id and throw an exception if it is (soft) deleted. @@ -64,16 +79,16 @@ public interface DistributionSetManagement extends RepositoryManagement moduleIds); + @PreAuthorize(HAS_UPDATE_REPOSITORY) + T assignSoftwareModules(long id, @NotEmpty Collection moduleIds); /** * Unassigns a {@link SoftwareModule} form an existing {@link DistributionSet}. @@ -100,8 +115,8 @@ public interface DistributionSetManagement extends RepositoryManagement assignTag(@NotEmpty Collection ids, long tagId); + @PreAuthorize(HAS_UPDATE_REPOSITORY) + List assignTag(@NotEmpty Collection ids, long tagId); /** * Unassign a {@link DistributionSetTag} assignment to given {@link DistributionSet}s. @@ -122,8 +137,8 @@ public interface DistributionSetManagement extends RepositoryManagement unassignTag(@NotEmpty Collection ids, long tagId); + @PreAuthorize(HAS_UPDATE_REPOSITORY) + List unassignTag(@NotEmpty Collection ids, long tagId); /** * Creates a map of distribution set meta-data entries. @@ -134,7 +149,7 @@ public interface DistributionSetManagement extends RepositoryManagement metadata); /** @@ -144,7 +159,7 @@ public interface DistributionSetManagement extends RepositoryManagement getMetadata(long id); /** @@ -155,7 +170,7 @@ public interface DistributionSetManagement extends RepositoryManagement findByAction(long actionId); + @PreAuthorize(HAS_READ_REPOSITORY) + Optional findByAction(long actionId); /** * Find distribution set by name and version. @@ -228,8 +243,8 @@ public interface DistributionSetManagement extends RepositoryManagement findByNameAndVersion(@NotEmpty String distributionName, @NotEmpty String version); + @PreAuthorize(HAS_READ_REPOSITORY) + Optional findByNameAndVersion(@NotEmpty String distributionName, @NotEmpty String version); /** * Finds all {@link DistributionSet}s based on completeness. @@ -239,8 +254,8 @@ public interface DistributionSetManagement extends RepositoryManagement findByCompleted(Boolean complete, @NotNull Pageable pageable); + @PreAuthorize(HAS_READ_REPOSITORY) + Slice findByCompleted(Boolean complete, @NotNull Pageable pageable); /** * Retrieves {@link DistributionSet}s by filtering on the given parameters. @@ -249,8 +264,8 @@ public interface DistributionSetManagement extends RepositoryManagement findByDistributionSetFilter(@NotNull DistributionSetFilter distributionSetFilter, @NotNull Pageable pageable); + @PreAuthorize(HAS_READ_REPOSITORY) + Slice findByDistributionSetFilter(@NotNull DistributionSetFilter distributionSetFilter, @NotNull Pageable pageable); /** * Retrieves {@link DistributionSet}s by filtering on the given parameters. @@ -263,8 +278,8 @@ public interface DistributionSetManagement extends RepositoryManagement findByTag(long tagId, @NotNull Pageable pageable); + @PreAuthorize(HAS_READ_REPOSITORY) + Page findByTag(long tagId, @NotNull Pageable pageable); /** * Retrieves {@link DistributionSet}s by filtering on the given parameters. @@ -275,8 +290,8 @@ public interface DistributionSetManagement extends RepositoryManagement findByRsqlAndTag(@NotNull String rsql, long tagId, @NotNull Pageable pageable); + @PreAuthorize(HAS_READ_REPOSITORY) + Page findByRsqlAndTag(@NotNull String rsql, long tagId, @NotNull Pageable pageable); /** * Counts all {@link DistributionSet}s based on completeness. @@ -285,7 +300,7 @@ public interface DistributionSetManagement extends RepositoryManagementnull to count both. * @return count of all found {@link DistributionSet}s */ - @PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET) + @PreAuthorize(HAS_READ_REPOSITORY) long countByCompleted(Boolean complete); /** @@ -294,7 +309,7 @@ public interface DistributionSetManagement extends RepositoryManagementtrue if in use */ - @PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET) + @PreAuthorize(HAS_READ_REPOSITORY) boolean isInUse(long id); /** @@ -325,7 +340,7 @@ public interface DistributionSetManagement extends RepositoryManagement countRolloutsByStatusForDistributionSet(@NotNull Long id); /** @@ -335,7 +350,7 @@ public interface DistributionSetManagement extends RepositoryManagement countActionsByStatusForDistributionSet(@NotNull Long id); /** @@ -345,6 +360,60 @@ public interface DistributionSetManagement extends RepositoryManagement modules = Set.of(); + + public Create setType(@NotEmpty DistributionSetType type) { + this.type = Objects.requireNonNull(type, "type must not be null"); + return this; + } + + public boolean isValid() { + return true; + } + } + + @SuperBuilder + @Getter + @EqualsAndHashCode(callSuper = true) + @ToString(callSuper = true) + final class Update extends UpdateCreate implements Identifiable { + + @NotNull + private Long id; + + @Builder.Default + private Boolean locked = false; + } + + @SuperBuilder + @Getter + class UpdateCreate { + + @ValidString + @Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) + @NotNull(groups = Create.class) + private String name; + @ValidString + @Size(min = 1, max = NamedVersionedEntity.VERSION_MAX_SIZE) + @NotNull(groups = Create.class) + private String version; + @ValidString + @Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) + private String description; + @Builder.Default + private Boolean requiredMigrationStep = false; + } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTagManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTagManagement.java index 147738ead..662e2b7fa 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTagManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTagManagement.java @@ -13,13 +13,18 @@ import java.util.Optional; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; +import lombok.experimental.SuperBuilder; import org.eclipse.hawkbit.im.authentication.SpringEvalExpressions; -import org.eclipse.hawkbit.repository.builder.TagCreate; -import org.eclipse.hawkbit.repository.builder.TagUpdate; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetTag; +import org.eclipse.hawkbit.repository.model.NamedEntity; +import org.eclipse.hawkbit.repository.model.Tag; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetTag; import org.springframework.data.domain.Page; @@ -29,7 +34,8 @@ import org.springframework.security.access.prepost.PreAuthorize; /** * Management service for {@link DistributionSetTag}s. */ -public interface DistributionSetTagManagement extends RepositoryManagement { +public interface DistributionSetTagManagement + extends RepositoryManagement { /** * Find {@link DistributionSet} based on given name. @@ -37,8 +43,8 @@ public interface DistributionSetTagManagement extends RepositoryManagement findByName(@NotEmpty String name); + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) + Optional findByName(@NotEmpty String name); /** * Finds all {@link TargetTag} assigned to given {@link Target}. @@ -48,8 +54,8 @@ public interface DistributionSetTagManagement extends RepositoryManagement findByDistributionSet(long distributionSetId, @NotNull Pageable pageable); + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) + Page findByDistributionSet(long distributionSetId, @NotNull Pageable pageable); /** * Deletes {@link DistributionSetTag} by given @@ -58,6 +64,40 @@ public interface DistributionSetTagManagement extends RepositoryManagement { + + @NotNull + private Long id; + } + + @SuperBuilder + @Getter + class UpdateCreate { + + @ValidString + @Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) + @NotNull(groups = Create.class) + private String name; + + @ValidString + @Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) + private String description; + + @ValidString + @Size(max = Tag.COLOUR_MAX_SIZE) + private String colour; + } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTypeManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTypeManagement.java index 3dbfa7d8e..b245d9a67 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTypeManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetTypeManagement.java @@ -11,31 +11,39 @@ package org.eclipse.hawkbit.repository; import java.util.Collection; import java.util.Optional; +import java.util.Set; import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; +import lombok.experimental.SuperBuilder; import org.eclipse.hawkbit.im.authentication.SpringEvalExpressions; -import org.eclipse.hawkbit.repository.builder.DistributionSetTypeCreate; -import org.eclipse.hawkbit.repository.builder.DistributionSetTypeUpdate; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetType; +import org.eclipse.hawkbit.repository.model.NamedEntity; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; +import org.eclipse.hawkbit.repository.model.Type; import org.springframework.security.access.prepost.PreAuthorize; /** * Management service for {@link DistributionSetType}s. */ -public interface DistributionSetTypeManagement - extends RepositoryManagement { +public interface DistributionSetTypeManagement + extends RepositoryManagement { - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Optional findByKey(@NotEmpty String key); + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) + Optional findByKey(@NotEmpty String key); - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Optional findByName(@NotEmpty String name); + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) + Optional findByName(@NotEmpty String name); /** * Assigns {@link DistributionSetType#getMandatoryModuleTypes()}. @@ -48,8 +56,8 @@ public interface DistributionSetTypeManagement * @throws AssignmentQuotaExceededException if the maximum number of {@link SoftwareModuleType}s is exceeded for the addressed * {@link DistributionSetType} */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - DistributionSetType assignOptionalSoftwareModuleTypes(long id, @NotEmpty Collection softwareModuleTypeIds); + @PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY) + T assignOptionalSoftwareModuleTypes(long id, @NotEmpty Collection softwareModuleTypeIds); /** * Assigns {@link DistributionSetType#getOptionalModuleTypes()}. @@ -62,8 +70,8 @@ public interface DistributionSetTypeManagement * @throws AssignmentQuotaExceededException if the maximum number of {@link SoftwareModuleType}s is exceeded for the addressed * {@link DistributionSetType} */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - DistributionSetType assignMandatorySoftwareModuleTypes(long id, @NotEmpty Collection softwareModuleTypeIds); + @PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY) + T assignMandatorySoftwareModuleTypes(long id, @NotEmpty Collection softwareModuleTypeIds); /** * Unassigns a {@link SoftwareModuleType} from the {@link DistributionSetType}. Does nothing if {@link SoftwareModuleType} @@ -75,6 +83,49 @@ public interface DistributionSetTypeManagement * @throws EntityNotFoundException in case the {@link DistributionSetType} does not exist * @throws EntityReadOnlyException if the {@link DistributionSetType} while it is already in use by a {@link DistributionSet} */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - DistributionSetType unassignSoftwareModuleType(long id, long softwareModuleTypeId); + @PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY) + T unassignSoftwareModuleType(long id, long softwareModuleTypeId); + + @SuperBuilder + @Getter + @EqualsAndHashCode(callSuper = true) + @ToString(callSuper = true) + final class Create extends UpdateCreate { + + @Size(min = 1, max = Type.KEY_MAX_SIZE) + @NotNull + private String key; + + @Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) + @NotNull + private String name; + } + + @SuperBuilder + @Getter + @EqualsAndHashCode(callSuper = true) + @ToString(callSuper = true) + final class Update extends UpdateCreate implements Identifiable { + + @NotNull + private Long id; + } + + @SuperBuilder + @Getter + class UpdateCreate { + + @ValidString + @Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) + private String description; + + @ValidString + @Size(max = Type.COLOUR_MAX_SIZE) + private String colour; + + @Builder.Default + private Set mandatoryModuleTypes = Set.of(); + @Builder.Default + private Set optionalModuleTypes = Set.of(); + } } \ No newline at end of file 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 44ccd0234..8b1340b3e 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 @@ -10,18 +10,15 @@ package org.eclipse.hawkbit.repository; import org.eclipse.hawkbit.repository.builder.ActionStatusBuilder; -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.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.builder.TargetTypeBuilder; import org.eclipse.hawkbit.repository.model.BaseEntity; +import org.eclipse.hawkbit.repository.model.Tag; /** * central {@link BaseEntity} generation service. Objects are created but not @@ -34,11 +31,6 @@ public interface EntityFactory { */ ActionStatusBuilder actionStatus(); - /** - * @return {@link DistributionSetBuilder} object - */ - DistributionSetBuilder distributionSet(); - /** * @return {@link SoftwareModuleMetadataBuilder} object */ @@ -47,33 +39,18 @@ public interface EntityFactory { /** * @return {@link TagBuilder} object */ - TagBuilder tag(); + TagBuilder tag(); /** * @return {@link RolloutGroupBuilder} object */ RolloutGroupBuilder rolloutGroup(); - /** - * @return {@link DistributionSetTypeBuilder} object - */ - DistributionSetTypeBuilder distributionSetType(); - /** * @return {@link RolloutBuilder} object */ RolloutBuilder rollout(); - /** - * @return {@link SoftwareModuleBuilder} object - */ - SoftwareModuleBuilder softwareModule(); - - /** - * @return {@link SoftwareModuleTypeBuilder} object - */ - SoftwareModuleTypeBuilder softwareModuleType(); - /** * @return {@link TargetBuilder} object */ diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RepositoryManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RepositoryManagement.java index aa3e9d435..7e02a6bcb 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RepositoryManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RepositoryManagement.java @@ -33,70 +33,30 @@ import org.springframework.security.access.prepost.PreAuthorize; * Generic management methods common to (software) repository content. * * @param type of the {@link BaseEntity} - * @param entity create builder - * @param entity update builder + * @param type of the create request + * @param type of the update request */ -public interface RepositoryManagement { - - /** - * Creates multiple {@link BaseEntity}s. - * - * @param creates to create - * @return created Entity - * @throws ConstraintViolationException if fields are not filled as specified. Check {@link BaseEntity} for field constraints. - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY) - List create(@NotNull @Valid Collection creates); +public interface RepositoryManagement> { /** * Creates new {@link BaseEntity}. * - * @param create to create + * @param create bean with properties of the object to create * @return created Entity * @throws ConstraintViolationException if fields are not filled as specified. Check {@link BaseEntity} for field constraints. */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY) + @PreAuthorize(SpringEvalExpressions.HAS_CREATE_REPOSITORY) T create(@NotNull @Valid C create); /** - * Updates existing {@link BaseEntity}. + * Creates multiple {@link BaseEntity}s. * - * @param update to update - * @return updated Entity - * @throws EntityReadOnlyException if the {@link BaseEntity} cannot be updated (e.g. is already in use) - * @throws EntityNotFoundException in case the {@link BaseEntity} does not exist and cannot be updated + * @param create beans with properties of the object to create + * @return created Entity * @throws ConstraintViolationException if fields are not filled as specified. Check {@link BaseEntity} for field constraints. */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - T update(@NotNull @Valid U update); - - /** - * Deletes or marks as delete in case the {@link BaseEntity} is in use. - * - * @param id to delete - * @throws EntityNotFoundException BaseEntity with given ID does not exist - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY) - void delete(long id); - - /** - * Delete {@link BaseEntity}s by their IDs. That is either a soft delete of the entities have been linked to another entity before or a hard - * delete if not. - * - * @param ids to be deleted - * @throws EntityNotFoundException if (at least one) given distribution set does not exist - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY) - void delete(@NotEmpty Collection ids); - - /** - * Retrieves all {@link BaseEntity}s without details. - * - * @param ids the ids to for - * @return the found {@link BaseEntity}s - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - List get(@NotEmpty Collection ids); + @PreAuthorize(SpringEvalExpressions.HAS_CREATE_REPOSITORY) + List create(@NotNull @Valid Collection create); /** * Retrieve {@link BaseEntity} @@ -104,16 +64,25 @@ public interface RepositoryManagement { * @param id to search for * @return {@link BaseEntity} in the repository with given {@link BaseEntity#getId()} */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) Optional get(long id); + /** + * Retrieves all {@link BaseEntity}s without details. + * + * @param ids the ids to for + * @return the found {@link BaseEntity}s + */ + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) + List get(@NotEmpty Collection ids); + /** * Retrieves {@link Page} of all {@link BaseEntity} of given type. * * @param pageable paging parameter * @return all {@link BaseEntity}s in the repository. */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) Slice findAll(@NotNull Pageable pageable); /** @@ -126,7 +95,7 @@ public interface RepositoryManagement { * {@code fieldNameProvider} * @throws RSQLParameterSyntaxException if the RSQL syntax is wrong */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) Page findByRsql(@NotNull String rsql, @NotNull Pageable pageable); /** @@ -135,12 +104,56 @@ public interface RepositoryManagement { * @param id of entity to check existence * @return true if entity with given ID exists */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) boolean exists(long id); /** * @return number of {@link BaseEntity}s in the repository. */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) long count(); + + /** + * Counts the number of {@link BaseEntity}s matching the given RSQL filter. + * + * @param rsql filter definition in RSQL syntax + * @return number of matching {@link BaseEntity}s in the repository. + */ + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) + long countByRsql(String rsql); + + /** + * Updates existing {@link BaseEntity}. + * + * @param update bean with properties of the object to update + * @return updated Entity + * @throws EntityReadOnlyException if the {@link BaseEntity} cannot be updated (e.g. is already in use) + * @throws EntityNotFoundException in case the {@link BaseEntity} does not exist and cannot be updated + * @throws ConstraintViolationException if fields are not filled as specified. Check {@link BaseEntity} for field constraints. + */ + @PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY) + T update(@NotNull @Valid U update); + + /** + * Deletes or marks as delete in case the {@link BaseEntity} is in use. + * + * @param id to delete + * @throws EntityNotFoundException BaseEntity with given ID does not exist + */ + @PreAuthorize(SpringEvalExpressions.HAS_DELETE_REPOSITORY) + void delete(long id); + + /** + * Delete {@link BaseEntity}s by their IDs. That is either a soft delete of the entities have been linked to another entity before or a hard + * delete if not. + * + * @param ids to be deleted + * @throws EntityNotFoundException if (at least one) given distribution set does not exist + */ + @PreAuthorize(SpringEvalExpressions.HAS_DELETE_REPOSITORY) + void delete(@NotEmpty Collection ids); + + default String permissionGroup() { + return "REPOSITORY"; + } } \ No newline at end of file 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 50615fac3..a3ee059a9 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 @@ -17,19 +17,26 @@ import java.util.Optional; import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; +import lombok.experimental.SuperBuilder; import org.eclipse.hawkbit.im.authentication.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.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.eclipse.hawkbit.repository.model.NamedEntity; +import org.eclipse.hawkbit.repository.model.NamedVersionedEntity; 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.Type; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; @@ -38,19 +45,24 @@ import org.springframework.security.access.prepost.PreAuthorize; /** * Service for managing {@link SoftwareModule}s. */ -public interface SoftwareModuleManagement extends RepositoryManagement { +public interface SoftwareModuleManagement + extends RepositoryManagement { + + @Override + default String permissionGroup() { + return "SOFTWARE_MODULE"; + } /** * Creates a list of software module meta-data entries. * * @param metadata 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 specific key * @throws EntityNotFoundException if software module with given ID does not exist * @throws AssignmentQuotaExceededException if the maximum number of {@link SoftwareModuleMetadata} entries is exceeded for the addressed * {@link SoftwareModule} */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) + @PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY) void createMetadata(@NotNull @Valid Collection metadata); /** @@ -60,7 +72,7 @@ public interface SoftwareModuleManagement extends RepositoryManagement getMetadata(long id); /** @@ -71,7 +83,7 @@ public interface SoftwareModuleManagement extends RepositoryManagement findMetaDataBySoftwareModuleIdAndTargetVisible(long id, @NotNull Pageable pageable); /** @@ -95,7 +107,7 @@ public interface SoftwareModuleManagement extends RepositoryManagement findByAssignedTo(long distributionSetId, @NotNull Pageable pageable); + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) + Page findByAssignedTo(long distributionSetId, @NotNull Pageable pageable); /** * Filter {@link SoftwareModule}s with given {@link SoftwareModule#getName()} or {@link SoftwareModule#getVersion()} @@ -160,8 +172,8 @@ public interface SoftwareModuleManagement extends RepositoryManagement findByTextAndType(String searchText, Long typeId, @NotNull Pageable pageable); + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) + Slice findByTextAndType(String searchText, Long typeId, @NotNull Pageable pageable); /** * Retrieves {@link SoftwareModule} by their name AND version AND type. @@ -172,8 +184,8 @@ public interface SoftwareModuleManagement extends RepositoryManagement findByNameAndVersionAndType(@NotEmpty String name, @NotEmpty String version, long typeId); + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) + Optional findByNameAndVersionAndType(@NotEmpty String name, @NotEmpty String version, long typeId); /** * Retrieves the {@link SoftwareModule}s by their {@link SoftwareModuleType} @@ -183,10 +195,10 @@ public interface SoftwareModuleManagement extends RepositoryManagement findByType(long typeId, @NotNull Pageable pageable); + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) + Slice findByType(long typeId, @NotNull Pageable pageable); - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) Map> findMetaDataBySoftwareModuleIdsAndTargetVisible(Collection moduleIds); /** @@ -196,6 +208,48 @@ public interface SoftwareModuleManagement extends RepositoryManagement { + + @NotNull + private Long id; + @Builder.Default + private Boolean locked = false; + } + + @SuperBuilder + @Getter + class UpdateCreate { + + @ValidString + @Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) + @NotNull(groups = Create.class) + private String name; + @ValidString + @Size(min = 1, max = NamedVersionedEntity.VERSION_MAX_SIZE) + @NotNull(groups = Create.class) + private String version; + @ValidString + @Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) + private String description; + @ValidString + @Size(max = SoftwareModule.VENDOR_MAX_SIZE) + private String vendor; + private SoftwareModuleType type; + } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleTypeManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleTypeManagement.java index ae78aada5..089b4a30b 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleTypeManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareModuleTypeManagement.java @@ -12,30 +12,78 @@ package org.eclipse.hawkbit.repository; import java.util.Optional; import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; +import lombok.experimental.SuperBuilder; import org.eclipse.hawkbit.im.authentication.SpringEvalExpressions; -import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeCreate; -import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeUpdate; +import org.eclipse.hawkbit.repository.model.NamedEntity; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; +import org.eclipse.hawkbit.repository.model.Type; import org.springframework.security.access.prepost.PreAuthorize; /** * Service for managing {@link SoftwareModuleType}s. */ -public interface SoftwareModuleTypeManagement - extends RepositoryManagement { +public interface SoftwareModuleTypeManagement + extends RepositoryManagement { /** * @param key to search for * @return {@link SoftwareModuleType} in the repository with given {@link SoftwareModuleType#getKey()} */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Optional findByKey(@NotEmpty String key); + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) + Optional findByKey(@NotEmpty String key); /** * @param name to search for * @return all {@link SoftwareModuleType}s in the repository with given {@link SoftwareModuleType#getName()} */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Optional findByName(@NotEmpty String name); + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) + Optional findByName(@NotEmpty String name); + + @SuperBuilder + @Getter + @EqualsAndHashCode(callSuper = true) + @ToString(callSuper = true) + final class Create extends UpdateCreate { + + @Size(min = 1, max = Type.KEY_MAX_SIZE) + @NotNull + private String key; + + @Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) + @NotNull + private String name; + + @Builder.Default + private int maxAssignments = 1; + } + + @SuperBuilder + @Getter + @EqualsAndHashCode(callSuper = true) + @ToString(callSuper = true) + final class Update extends UpdateCreate implements Identifiable { + + @NotNull + private Long id; + } + + @SuperBuilder + @Getter + class UpdateCreate { + + @ValidString + @Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) + private String description; + + @ValidString + @Size(max = Type.COLOUR_MAX_SIZE) + private String colour; + } } \ No newline at end of file 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 e2f11cb07..9dc4c0bd6 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 @@ -76,7 +76,7 @@ public interface SystemManagement { /** * @return {@link TenantMetaData} of {@link TenantAware#getCurrentTenant()} */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR + SpringEvalExpressions.HAS_AUTH_READ_TARGET + SpringEvalExpressions.HAS_AUTH_OR + SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION_READ + SpringEvalExpressions.HAS_AUTH_OR + SpringEvalExpressions.IS_CONTROLLER) @@ -85,7 +85,7 @@ public interface SystemManagement { /** * @return {@link TenantMetaData} of {@link TenantAware#getCurrentTenant()} without details ({@link TenantMetaData#getDefaultDsType()}) */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR + @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR + SpringEvalExpressions.HAS_AUTH_READ_TARGET + SpringEvalExpressions.HAS_AUTH_OR + SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION_READ + SpringEvalExpressions.HAS_AUTH_OR + SpringEvalExpressions.IS_CONTROLLER) @@ -118,4 +118,4 @@ public interface SystemManagement { @PreAuthorize(SpringEvalExpressions.IS_SYSTEM_CODE) TenantMetaData getTenantMetadata(long tenantId); -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java index 164067ea5..dd6d1767f 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java @@ -15,12 +15,12 @@ import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AU import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AUTH_CREATE_TARGET; import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AUTH_DELETE_TARGET; import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AUTH_PREFIX; -import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY; +import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_READ_REPOSITORY; import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET; import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AUTH_READ_TARGET; import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ_AND_TARGET_READ; import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AUTH_SUFFIX; -import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY; +import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_UPDATE_REPOSITORY; import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET; import java.util.Collection; @@ -752,7 +752,7 @@ public interface TargetManagement { * @throws EntityAlreadyExistsException in case one of the metad-ata entry already exists for the specific key * @throws AssignmentQuotaExceededException if the maximum number of meta-data entries is exceeded for the addressed {@link Target} */ - @PreAuthorize(HAS_AUTH_UPDATE_REPOSITORY) + @PreAuthorize(HAS_UPDATE_REPOSITORY) void createMetadata(@NotEmpty String controllerId, @NotEmpty Map metadata); /** @@ -762,7 +762,7 @@ public interface TargetManagement { * @return the found target meta-data * @throws EntityNotFoundException if target with given ID does not exist */ - @PreAuthorize(HAS_AUTH_READ_REPOSITORY) + @PreAuthorize(HAS_READ_REPOSITORY) Map getMetadata(@NotEmpty String controllerId); /** @@ -773,7 +773,7 @@ public interface TargetManagement { * @param value meta data-entry to be new value * @throws EntityNotFoundException in case the meta-data entry does not exist and cannot be updated */ - @PreAuthorize(HAS_AUTH_UPDATE_REPOSITORY) + @PreAuthorize(HAS_UPDATE_REPOSITORY) void updateMetadata(@NotEmpty String controllerId, @NotNull String key, @NotNull String value); /** @@ -783,6 +783,6 @@ public interface TargetManagement { * @param key of the meta data element * @throws EntityNotFoundException if given target does not exist */ - @PreAuthorize(HAS_AUTH_UPDATE_REPOSITORY) + @PreAuthorize(HAS_UPDATE_REPOSITORY) void deleteMetadata(@NotEmpty String controllerId, @NotEmpty String key); } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetTagManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetTagManagement.java index 159c1c59c..8759b9688 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetTagManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetTagManagement.java @@ -25,6 +25,7 @@ import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; +import org.eclipse.hawkbit.repository.model.Tag; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetTag; import org.springframework.data.domain.Page; @@ -53,7 +54,7 @@ public interface TargetTagManagement { * @throws ConstraintViolationException if fields are not filled as specified. Check {@link TagCreate} for field constraints. */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_TARGET) - TargetTag create(@NotNull @Valid TagCreate create); + TargetTag create(@NotNull @Valid TagCreate create); /** * Created multiple {@link TargetTag}s. @@ -64,7 +65,7 @@ public interface TargetTagManagement { * @throws ConstraintViolationException if fields are not filled as specified. Check {@link TagCreate} for field constraints. */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_TARGET) - List create(@NotNull @Valid Collection creates); + List create(@NotNull @Valid Collection> creates); /** * Deletes {@link TargetTag} with given name. diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TenantStatsManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TenantStatsManagement.java index 39f9320ec..f213ca117 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TenantStatsManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TenantStatsManagement.java @@ -25,7 +25,7 @@ public interface TenantStatsManagement { * @return collected statistics */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_SYSTEM_ADMIN + SpringEvalExpressions.HAS_AUTH_OR - + SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR + + SpringEvalExpressions.HAS_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR + SpringEvalExpressions.HAS_AUTH_READ_TARGET + SpringEvalExpressions.HAS_AUTH_OR + SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION_READ + SpringEvalExpressions.HAS_AUTH_OR + SpringEvalExpressions.IS_SYSTEM_CODE) diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/DistributionSetBuilder.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/DistributionSetBuilder.java deleted file mode 100644 index b899d3a88..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/DistributionSetBuilder.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.builder; - -import org.eclipse.hawkbit.repository.model.DistributionSet; - -/** - * Builder for {@link DistributionSet}. - */ -public interface DistributionSetBuilder { - - /** - * @param id of the updatable entity - * @return builder instance - */ - DistributionSetUpdate update(long id); - - /** - * @return builder instance - */ - DistributionSetCreate create(); -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/DistributionSetCreate.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/DistributionSetCreate.java deleted file mode 100644 index 64eb5a912..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/DistributionSetCreate.java +++ /dev/null @@ -1,79 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.builder; - -import java.util.Collection; - -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; - -import org.eclipse.hawkbit.repository.model.BaseEntity; -import org.eclipse.hawkbit.repository.model.DistributionSet; -import org.eclipse.hawkbit.repository.model.DistributionSetType; -import org.eclipse.hawkbit.repository.model.NamedEntity; -import org.eclipse.hawkbit.repository.model.NamedVersionedEntity; -import org.eclipse.hawkbit.repository.model.Type; - -/** - * Builder to create a new {@link DistributionSet} 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 DistributionSetCreate { - - /** - * @param name for {@link DistributionSet#getName()} - * @return updated builder instance - */ - DistributionSetCreate name(@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) @NotNull String name); - - /** - * @param version for {@link DistributionSet#getVersion()} - * @return updated builder instance - */ - DistributionSetCreate version(@Size(min = 1, max = NamedVersionedEntity.VERSION_MAX_SIZE) @NotNull String version); - - /** - * @param description for {@link DistributionSet#getDescription()} - * @return updated builder instance - */ - DistributionSetCreate description(@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) String description); - - /** - * @param typeKey for {@link DistributionSet#getType()} - * @return updated builder instance - */ - DistributionSetCreate type(@Size(min = 1, max = Type.KEY_MAX_SIZE) @NotNull String typeKey); - - /** - * @param type for {@link DistributionSet#getType()} - * @return updated builder instance - */ - default DistributionSetCreate type(@NotNull final DistributionSetType type) { - return type(type.getKey()); - } - - /** - * @param modules for {@link DistributionSet#getModules()} - * @return updated builder instance - */ - DistributionSetCreate modules(Collection modules); - - /** - * @param requiredMigrationStep for {@link DistributionSet#isRequiredMigrationStep()} - * @return updated builder instance - */ - DistributionSetCreate requiredMigrationStep(Boolean requiredMigrationStep); - - /** - * @return peek on current state of {@link DistributionSet} in the builder - */ - DistributionSet build(); -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/DistributionSetTypeBuilder.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/DistributionSetTypeBuilder.java deleted file mode 100644 index c9da57a20..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/DistributionSetTypeBuilder.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.builder; - -import org.eclipse.hawkbit.repository.model.DistributionSetType; - -/** - * Builder for {@link DistributionSetType}. - */ -public interface DistributionSetTypeBuilder { - - /** - * @param id of the updatable entity - * @return builder instance - */ - DistributionSetTypeUpdate update(long id); - - /** - * @return builder instance - */ - DistributionSetTypeCreate create(); -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/DistributionSetTypeCreate.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/DistributionSetTypeCreate.java deleted file mode 100644 index 1de017e42..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/DistributionSetTypeCreate.java +++ /dev/null @@ -1,104 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.builder; - -import java.util.Collection; -import java.util.Collections; -import java.util.Optional; - -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; - -import org.eclipse.hawkbit.repository.model.BaseEntity; -import org.eclipse.hawkbit.repository.model.DistributionSetType; -import org.eclipse.hawkbit.repository.model.NamedEntity; -import org.eclipse.hawkbit.repository.model.SoftwareModuleType; -import org.eclipse.hawkbit.repository.model.Type; - -/** - * Builder to create a new {@link DistributionSetType} 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 DistributionSetTypeCreate { - - /** - * @param key for {@link DistributionSetType#getKey()} - * @return updated builder instance - */ - DistributionSetTypeCreate key(@Size(min = 1, max = Type.KEY_MAX_SIZE) @NotNull String key); - - /** - * @param name for {@link DistributionSetType#getName()} - * @return updated builder instance - */ - DistributionSetTypeCreate name(@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) @NotNull String name); - - /** - * @param description for {@link DistributionSetType#getDescription()} - * @return updated builder instance - */ - DistributionSetTypeCreate description(@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) String description); - - /** - * @param colour for {@link DistributionSetType#getColour()} - * @return updated builder instance - */ - DistributionSetTypeCreate colour(@Size(max = Type.COLOUR_MAX_SIZE) String colour); - - /** - * @param mandatory for {@link DistributionSetType#getMandatoryModuleTypes()} - * @return updated builder instance - */ - DistributionSetTypeCreate mandatory(Collection mandatory); - - /** - * @param mandatory for {@link DistributionSetType#getMandatoryModuleTypes()} - * @return updated builder instance - */ - default DistributionSetTypeCreate mandatory(final Long mandatory) { - return mandatory(Collections.singletonList(mandatory)); - } - - /** - * @param mandatory for {@link DistributionSetType#getOptionalModuleTypes()} - * @return updated builder instance - */ - default DistributionSetTypeCreate mandatory(final SoftwareModuleType mandatory) { - return mandatory(Optional.ofNullable(mandatory).map(SoftwareModuleType::getId).orElse(null)); - } - - /** - * @param optional for {@link DistributionSetType#getOptionalModuleTypes()} - * @return updated builder instance - */ - DistributionSetTypeCreate optional(Collection optional); - - /** - * @param optional for {@link DistributionSetType#getOptionalModuleTypes()} - * @return updated builder instance - */ - default DistributionSetTypeCreate optional(final Long optional) { - return optional(Collections.singletonList(optional)); - } - - /** - * @param optional for {@link DistributionSetType#getOptionalModuleTypes()} - * @return updated builder instance - */ - default DistributionSetTypeCreate optional(final SoftwareModuleType optional) { - return optional(Optional.ofNullable(optional).map(SoftwareModuleType::getId).orElse(null)); - } - - /** - * @return peek on current state of {@link DistributionSetType} in the builder - */ - DistributionSetType build(); -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/DistributionSetTypeUpdate.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/DistributionSetTypeUpdate.java deleted file mode 100644 index c5e703e7b..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/DistributionSetTypeUpdate.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.builder; - -import java.util.Collection; - -import jakarta.validation.constraints.Size; - -import org.eclipse.hawkbit.repository.model.DistributionSetType; -import org.eclipse.hawkbit.repository.model.NamedEntity; -import org.eclipse.hawkbit.repository.model.Type; - -/** - * Builder to update an existing {@link DistributionSetType} entry. Defines all - * fields that can be updated. - */ -public interface DistributionSetTypeUpdate { - - /** - * @param description for {@link DistributionSetType#getDescription()} - * @return updated builder instance - */ - DistributionSetTypeUpdate description(@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) String description); - - /** - * @param colour for {@link DistributionSetType#getColour()} - * @return updated builder instance - */ - DistributionSetTypeUpdate colour(@Size(max = Type.COLOUR_MAX_SIZE) String colour); - - /** - * @param mandatory for {@link DistributionSetType#getMandatoryModuleTypes()} - * @return updated builder instance - */ - DistributionSetTypeUpdate mandatory(Collection mandatory); - - /** - * @param optional for {@link DistributionSetType#getOptionalModuleTypes()} - * @return updated builder instance - */ - DistributionSetTypeUpdate optional(Collection optional); -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/DistributionSetUpdate.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/DistributionSetUpdate.java deleted file mode 100644 index 83edb84b7..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/DistributionSetUpdate.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.builder; - -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Null; -import jakarta.validation.constraints.Size; - -import org.eclipse.hawkbit.repository.model.DistributionSet; -import org.eclipse.hawkbit.repository.model.NamedEntity; -import org.eclipse.hawkbit.repository.model.NamedVersionedEntity; - -/** - * Builder to update an existing {@link DistributionSet} entry. Defines all fields that can be updated. - */ -public interface DistributionSetUpdate { - - /** - * @param name for {@link DistributionSet#getName()} - * @return updated builder instance - */ - DistributionSetUpdate name(@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) @NotNull String name); - - /** - * @param version for {@link DistributionSet#getVersion()} - * @return updated builder instance - */ - DistributionSetUpdate version(@Size(min = 1, max = NamedVersionedEntity.VERSION_MAX_SIZE) @NotNull String version); - - /** - * @param description for {@link DistributionSet#getDescription()} - * @return updated builder instance - */ - DistributionSetUpdate description(@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) String description); - - /** - * @param locked update request if any. If not empty shall be true - * @return updated builder instance - */ - DistributionSetUpdate locked(@Null Boolean locked); - - /** - * @param requiredMigrationStep for {@link DistributionSet#isRequiredMigrationStep()} - * @return updated builder instance - */ - DistributionSetUpdate requiredMigrationStep(Boolean requiredMigrationStep); -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleBuilder.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleBuilder.java deleted file mode 100644 index 6535161f4..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleBuilder.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.builder; - -import org.eclipse.hawkbit.repository.model.SoftwareModule; - -/** - * Builder for {@link SoftwareModule}. - */ -public interface SoftwareModuleBuilder { - - /** - * @param id of the updatable entity - * @return builder instance - */ - SoftwareModuleUpdate update(long id); - - /** - * @return builder instance - */ - SoftwareModuleCreate create(); -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleCreate.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleCreate.java deleted file mode 100644 index b9621b19c..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleCreate.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.builder; - -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; - -import org.eclipse.hawkbit.repository.model.BaseEntity; -import org.eclipse.hawkbit.repository.model.NamedEntity; -import org.eclipse.hawkbit.repository.model.NamedVersionedEntity; -import org.eclipse.hawkbit.repository.model.SoftwareModule; -import org.eclipse.hawkbit.repository.model.SoftwareModuleType; -import org.eclipse.hawkbit.repository.model.Type; - -/** - * Builder to create a new {@link SoftwareModule} 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 SoftwareModuleCreate { - - /** - * @param name for {@link SoftwareModule#getName()} - * @return updated builder instance - */ - SoftwareModuleCreate name(@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) @NotNull String name); - - /** - * @param version for {@link SoftwareModule#getVersion()} - * @return updated builder instance - */ - SoftwareModuleCreate version(@Size(min = 1, max = NamedVersionedEntity.VERSION_MAX_SIZE) @NotNull String version); - - /** - * @param description for {@link SoftwareModule#getDescription()} - * @return updated builder instance - */ - SoftwareModuleCreate description(@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) String description); - - /** - * @param vendor for {@link SoftwareModule#getVendor()} - * @return updated builder instance - */ - SoftwareModuleCreate vendor(@Size(max = SoftwareModule.VENDOR_MAX_SIZE) String vendor); - - /** - * @param typeKey for {@link SoftwareModule#getType()} - * @return updated builder instance - */ - SoftwareModuleCreate type(@Size(min = 1, max = Type.KEY_MAX_SIZE) @NotNull String typeKey); - - /** - * @param type for {@link SoftwareModule#getType()} - * @return updated builder instance - */ - default SoftwareModuleCreate type(@NotNull final SoftwareModuleType type) { - return type(type.getKey()); - } - - /** - * @param encrypted if should be encrypted - * @return updated builder instance - */ - SoftwareModuleCreate encrypted(boolean encrypted); - - /** - * @return peek on current state of {@link SoftwareModule} in the builder - */ - SoftwareModule build(); -} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleTypeBuilder.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleTypeBuilder.java deleted file mode 100644 index e14775f72..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleTypeBuilder.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.builder; - -import org.eclipse.hawkbit.repository.model.SoftwareModuleType; - -/** - * Builder for {@link SoftwareModuleType}. - */ -public interface SoftwareModuleTypeBuilder { - - /** - * @param id of the updatable entity - * @return builder instance - */ - SoftwareModuleTypeUpdate update(long id); - - /** - * @return builder instance - */ - SoftwareModuleTypeCreate create(); -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleTypeCreate.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleTypeCreate.java deleted file mode 100644 index 76b5e59c1..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleTypeCreate.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.builder; - -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; - -import org.eclipse.hawkbit.repository.model.BaseEntity; -import org.eclipse.hawkbit.repository.model.NamedEntity; -import org.eclipse.hawkbit.repository.model.SoftwareModuleType; -import org.eclipse.hawkbit.repository.model.Type; - -/** - * Builder to create a new {@link SoftwareModuleType} 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 SoftwareModuleTypeCreate { - - /** - * @param key for {@link SoftwareModuleType#getKey()} - * @return updated builder instance - */ - SoftwareModuleTypeCreate key(@Size(min = 1, max = Type.KEY_MAX_SIZE) @NotNull String key); - - /** - * @param name for {@link SoftwareModuleType#getName()} - * @return updated builder instance - */ - SoftwareModuleTypeCreate name(@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) @NotNull String name); - - /** - * @param description for {@link SoftwareModuleType#getDescription()} - * @return updated builder instance - */ - SoftwareModuleTypeCreate description(@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) String description); - - /** - * @param colour for {@link SoftwareModuleType#getColour()} - * @return updated builder instance - */ - SoftwareModuleTypeCreate colour(@Size(max = Type.COLOUR_MAX_SIZE) String colour); - - /** - * @param maxAssignments for {@link SoftwareModuleType#getMaxAssignments()} - * @return updated builder instance - */ - SoftwareModuleTypeCreate maxAssignments(int maxAssignments); - - /** - * @return peek on current state of {@link SoftwareModuleType} in the - * builder - */ - SoftwareModuleType build(); -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleTypeUpdate.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleTypeUpdate.java deleted file mode 100644 index 1ccf7b7bd..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleTypeUpdate.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.builder; - -import jakarta.validation.constraints.Size; - -import org.eclipse.hawkbit.repository.model.NamedEntity; -import org.eclipse.hawkbit.repository.model.SoftwareModuleType; -import org.eclipse.hawkbit.repository.model.Type; - -/** - * Builder to update an existing {@link SoftwareModuleType} entry. Defines all - * fields that can be updated. - */ -public interface SoftwareModuleTypeUpdate { - - /** - * @param description for {@link SoftwareModuleType#getDescription()} - * @return updated builder instance - */ - SoftwareModuleTypeUpdate description(@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) String description); - - /** - * @param colour for {@link SoftwareModuleType#getColour()} - * @return updated builder instance - */ - SoftwareModuleTypeUpdate colour(@Size(max = Type.COLOUR_MAX_SIZE) String colour); -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleUpdate.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleUpdate.java deleted file mode 100644 index b6edcffaf..000000000 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/SoftwareModuleUpdate.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.builder; - -import jakarta.validation.constraints.Null; -import jakarta.validation.constraints.Size; - -import org.eclipse.hawkbit.repository.model.NamedEntity; -import org.eclipse.hawkbit.repository.model.SoftwareModule; - -/** - * Builder to update an existing {@link SoftwareModule} entry. Defines all - * fields that can be updated. - */ -public interface SoftwareModuleUpdate { - - /** - * @param description for {@link SoftwareModule#getDescription()} - * @return updated builder instance - */ - SoftwareModuleUpdate description(@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) String description); - - /** - * @param vendor for {@link SoftwareModule#getVendor()} - * @return updated builder instance - */ - SoftwareModuleUpdate vendor(@Size(max = SoftwareModule.VENDOR_MAX_SIZE) String vendor); - - /** - * @param locked update request if any. If not empty shall be true - * @return updated builder instance - */ - SoftwareModuleUpdate locked(@Null Boolean locked); -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/TagBuilder.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/TagBuilder.java index f8c14468d..d08647c41 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/TagBuilder.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/TagBuilder.java @@ -14,7 +14,7 @@ import org.eclipse.hawkbit.repository.model.Tag; /** * Builder for {@link Tag}. */ -public interface TagBuilder { +public interface TagBuilder { /** * @param id of the updatable entity @@ -25,5 +25,5 @@ public interface TagBuilder { /** * @return builder instance */ - TagCreate create(); + TagCreate create(); } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/TagCreate.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/TagCreate.java index d0972d899..3560bc172 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/TagCreate.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/builder/TagCreate.java @@ -21,28 +21,28 @@ import org.eclipse.hawkbit.repository.model.Tag; * at creation time. Other fields are set by the repository automatically, e.g. * {@link BaseEntity#getCreatedAt()}. */ -public interface TagCreate { +public interface TagCreate { /** * @param name for {@link Tag#getName()} * @return updated builder instance */ - TagCreate name(@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) @NotNull String name); + TagCreate name(@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) @NotNull String name); /** * @param description for {@link Tag#getDescription()} * @return updated builder instance */ - TagCreate description(@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) String description); + TagCreate description(@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) String description); /** * @param colour for {@link Tag#getColour()} * @return updated builder instance */ - TagCreate colour(@Size(max = Tag.COLOUR_MAX_SIZE) String colour); + TagCreate colour(@Size(max = Tag.COLOUR_MAX_SIZE) String colour); /** * @return peek on current state of {@link Tag} in the builder */ - Tag build(); + T build(); } diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactBinaryNoLongerExistsException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactBinaryNoLongerExistsException.java index 34a4923d6..6c88392a7 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactBinaryNoLongerExistsException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactBinaryNoLongerExistsException.java @@ -11,6 +11,8 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.repository.model.SoftwareModule; @@ -19,6 +21,8 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule; * Exception indicating that an artifact's binary does not exist anymore. This * might be caused due to the soft deletion of a {@link SoftwareModule}. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class ArtifactBinaryNoLongerExistsException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactBinaryNotFoundException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactBinaryNotFoundException.java index 13695c848..1d267b2df 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactBinaryNotFoundException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactBinaryNotFoundException.java @@ -11,9 +11,13 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public final class ArtifactBinaryNotFoundException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactDeleteFailedException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactDeleteFailedException.java index e906fa1ab..cc151d477 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactDeleteFailedException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactDeleteFailedException.java @@ -11,12 +11,16 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** * Thrown if artifact deletion failed. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public final class ArtifactDeleteFailedException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactUploadFailedException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactUploadFailedException.java index 8df676af6..f9e310f7e 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactUploadFailedException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactUploadFailedException.java @@ -11,9 +11,13 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public final class ArtifactUploadFailedException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/AssignmentQuotaExceededException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/AssignmentQuotaExceededException.java index 76f2a0085..526226fa9 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/AssignmentQuotaExceededException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/AssignmentQuotaExceededException.java @@ -9,6 +9,8 @@ */ package org.eclipse.hawkbit.repository.exception; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.repository.model.BaseEntity; @@ -16,6 +18,8 @@ import org.eclipse.hawkbit.repository.model.BaseEntity; /** * Thrown if assignment quota is exceeded */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class AssignmentQuotaExceededException extends AbstractServerRtException { private static final String ASSIGNMENT_QUOTA_EXCEEDED_MESSAGE = "Quota exceeded: Cannot assign %s more %s entities to %s '%s'. The maximum is %s."; diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/AutoConfirmationAlreadyActiveException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/AutoConfirmationAlreadyActiveException.java index 5bca345b7..d762d69c0 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/AutoConfirmationAlreadyActiveException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/AutoConfirmationAlreadyActiveException.java @@ -11,15 +11,17 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** - * The {@link AutoConfirmationAlreadyActiveException} is thrown when auto - * confirmation is already active for a device but the - * {@link org.eclipse.hawkbit.repository.ConfirmationManagement#activateAutoConfirmation} - * is getting called. + * The {@link AutoConfirmationAlreadyActiveException} is thrown when auto confirmation is already active for a device but the + * {@link org.eclipse.hawkbit.repository.ConfirmationManagement#activateAutoConfirmation} is getting called. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class AutoConfirmationAlreadyActiveException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/CancelActionNotAllowedException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/CancelActionNotAllowedException.java index aa950ea67..6b710d5c6 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/CancelActionNotAllowedException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/CancelActionNotAllowedException.java @@ -11,15 +11,17 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** - * Thrown if cancellation of action is requested where the action cannot be - * cancelled (e.g. the action is not active or is already a canceled action) or - * controller provides cancellation feedback on an action that is actually not - * in canceling state. + * Thrown if cancellation of action is requested where the action cannot be cancelled (e.g. the action is not active or is already a canceled + * action) or controller provides cancellation feedback on an action that is actually not in canceling state. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public final class CancelActionNotAllowedException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ConcurrentModificationException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ConcurrentModificationException.java index 0f97017ef..9c9d377dd 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ConcurrentModificationException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ConcurrentModificationException.java @@ -11,14 +11,17 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** - * {@link ConcurrentModificationException} is thrown when a given entity in's - * actual and cannot be stored within the current session. Reason could be that - * it has been changed within another session. + * {@link ConcurrentModificationException} is thrown when a given entity in's actual and cannot be stored within the current session. + * Reason could be that it has been changed within another session. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class ConcurrentModificationException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/DeletedException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/DeletedException.java index d8442b379..2dee20093 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/DeletedException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/DeletedException.java @@ -11,6 +11,8 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.repository.model.BaseEntity; @@ -18,6 +20,8 @@ import org.eclipse.hawkbit.repository.model.BaseEntity; /** * Thrown if assignment quota is exceeded */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class DeletedException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/DistributionSetTypeUndefinedException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/DistributionSetTypeUndefinedException.java index 0a3d5d3db..3453d2d83 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/DistributionSetTypeUndefinedException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/DistributionSetTypeUndefinedException.java @@ -11,15 +11,18 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetType; /** - * Thrown if the user tries to assign modules to a {@link DistributionSet} that - * has to {@link DistributionSetType} defined. + * Thrown if the user tries to assign modules to a {@link DistributionSet} that has to {@link DistributionSetType} defined. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class DistributionSetTypeUndefinedException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityAlreadyExistsException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityAlreadyExistsException.java index 68274d186..0ee046d5e 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityAlreadyExistsException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityAlreadyExistsException.java @@ -11,13 +11,17 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** - * the {@link EntityAlreadyExistsException} is thrown when an entity is tried to - * be saved which already exists or which violates unique key constraints. + * the {@link EntityAlreadyExistsException} is thrown when an entity is tried to be saved which already exists or which violates unique key + * constraints. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class EntityAlreadyExistsException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityNotFoundException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityNotFoundException.java index 3d036f821..fbcb0d782 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityNotFoundException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityNotFoundException.java @@ -14,7 +14,10 @@ import java.util.Collection; import java.util.Map; import java.util.stream.Collectors; +import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.Getter; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.repository.model.BaseEntity; @@ -22,14 +25,18 @@ import org.eclipse.hawkbit.repository.model.BaseEntity; /** * the {@link EntityNotFoundException} is thrown when a entity queried but not found. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) @Getter public class EntityNotFoundException extends AbstractServerRtException { + @Serial + private static final long serialVersionUID = 1L; + public static final String KEY = "key"; public static final String ENTITY_ID = "entityId"; public static final String TYPE = "type"; - @Serial - private static final long serialVersionUID = 1L; + private static final SpServerError THIS_ERROR = SpServerError.SP_REPO_ENTITY_NOT_EXISTS; private static final int ENTITY_STRING_MAX_LENGTH = 100; diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityReadOnlyException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityReadOnlyException.java index 4a5f5d820..c0e022632 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityReadOnlyException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityReadOnlyException.java @@ -11,13 +11,16 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** - * the {@link EntityReadOnlyException} is thrown when a entity is in read only - * mode and a user tries to change it. + * the {@link EntityReadOnlyException} is thrown when a entity is in read only mode and a user tries to change it. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class EntityReadOnlyException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/FileSizeQuotaExceededException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/FileSizeQuotaExceededException.java index 41b0ae792..4c8777d6e 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/FileSizeQuotaExceededException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/FileSizeQuotaExceededException.java @@ -12,6 +12,7 @@ package org.eclipse.hawkbit.repository.exception; import static org.eclipse.hawkbit.repository.SizeConversionHelper.byteValueToReadableString; import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; @@ -19,6 +20,7 @@ import org.eclipse.hawkbit.exception.SpServerError; * Thrown if file size quota is exceeded */ @EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class FileSizeQuotaExceededException extends AbstractServerRtException { private static final String MAX_ARTIFACT_SIZE_EXCEEDED = "Maximum artifact size (%s) exceeded."; diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ForceQuitActionNotAllowedException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ForceQuitActionNotAllowedException.java index 6c5328e44..cc617b773 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ForceQuitActionNotAllowedException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ForceQuitActionNotAllowedException.java @@ -11,12 +11,16 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** * Thrown when force quitting an actions is not allowed. e.g. the action is not active, or it is not canceled before. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public final class ForceQuitActionNotAllowedException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/IncompatibleTargetTypeException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/IncompatibleTargetTypeException.java index 445541334..8941f13e4 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/IncompatibleTargetTypeException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/IncompatibleTargetTypeException.java @@ -14,6 +14,7 @@ import java.util.Collection; import java.util.Collections; import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -24,6 +25,7 @@ import org.eclipse.hawkbit.repository.model.TargetType; * Thrown if user tries to assign a {@link DistributionSet} to a {@link Target} that has an incompatible {@link TargetType} */ @EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class IncompatibleTargetTypeException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/IncompleteDistributionSetException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/IncompleteDistributionSetException.java index 67b4131c4..d3158f8fc 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/IncompleteDistributionSetException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/IncompleteDistributionSetException.java @@ -11,13 +11,16 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** - * Thrown if a distribution set is assigned to a a target that is incomplete - * (i.e. mandatory modules are missing). + * Thrown if a distribution set is assigned to a target that is incomplete (i.e. mandatory modules are missing). */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public final class IncompleteDistributionSetException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InsufficientPermissionException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InsufficientPermissionException.java index ba271e860..88296a8f5 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InsufficientPermissionException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InsufficientPermissionException.java @@ -11,35 +11,30 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** - * Exception which is thrown in case the current security context object does - * not hold a required authority/permission. + * Exception which is thrown in case the current security context object does not hold a required authority/permission. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class InsufficientPermissionException extends AbstractServerRtException { @Serial private static final long serialVersionUID = 1L; - /** - * creates new InsufficientPermissionException. - * - * @param cause the cause of the exception - */ public InsufficientPermissionException(final Throwable cause) { super(SpServerError.SP_INSUFFICIENT_PERMISSION, cause); } - /** - * creates new InsufficientPermissionException. - */ public InsufficientPermissionException(final String message) { super(message, SpServerError.SP_INSUFFICIENT_PERMISSION); } public InsufficientPermissionException() { - super(SpServerError.SP_INSUFFICIENT_PERMISSION, null); + this((String)null); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidAutoAssignActionTypeException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidAutoAssignActionTypeException.java index 6baa7a964..fcabaa053 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidAutoAssignActionTypeException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidAutoAssignActionTypeException.java @@ -12,12 +12,16 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** * Thrown if an action type for auto-assignment is neither 'forced', nor 'soft'. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class InvalidAutoAssignActionTypeException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidConfirmationFeedbackException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidConfirmationFeedbackException.java index d966202d0..a9a4b5567 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidConfirmationFeedbackException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidConfirmationFeedbackException.java @@ -12,6 +12,7 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; @@ -20,6 +21,7 @@ import org.eclipse.hawkbit.exception.SpServerError; * listed as enum {@link Reason}. */ @EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class InvalidConfirmationFeedbackException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidDistributionSetException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidDistributionSetException.java index efeac84aa..29185f377 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidDistributionSetException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidDistributionSetException.java @@ -11,9 +11,13 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class InvalidDistributionSetException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidMD5HashException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidMD5HashException.java index 2655ff7b5..aca3cd333 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidMD5HashException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidMD5HashException.java @@ -11,12 +11,16 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** * Thrown if MD5 checksum check fails. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class InvalidMD5HashException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidMaintenanceScheduleException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidMaintenanceScheduleException.java index 2295ab3e2..6610eb00f 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidMaintenanceScheduleException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidMaintenanceScheduleException.java @@ -12,6 +12,7 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; @@ -21,6 +22,7 @@ import org.eclipse.hawkbit.exception.SpServerError; * time. */ @EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class InvalidMaintenanceScheduleException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSHA1HashException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSHA1HashException.java index bf0ca5416..068f2ae39 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSHA1HashException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSHA1HashException.java @@ -11,12 +11,16 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** * Thrown if SHA1 checksum check fails. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class InvalidSHA1HashException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSHA256HashException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSHA256HashException.java index b2f6ec087..2c34491b8 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSHA256HashException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSHA256HashException.java @@ -11,12 +11,16 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** * Thrown if SHA256 checksum check fails. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class InvalidSHA256HashException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTargetAddressException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTargetAddressException.java index 7c0c87232..67955458a 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTargetAddressException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTargetAddressException.java @@ -11,12 +11,16 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** * Exception which is thrown when trying to set an invalid target address. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class InvalidTargetAddressException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTargetAttributeException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTargetAttributeException.java index 7745ca9b5..577a33a18 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTargetAttributeException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTargetAttributeException.java @@ -12,9 +12,13 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class InvalidTargetAttributeException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTenantConfigurationKeyException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTenantConfigurationKeyException.java index 4a2b28bf0..26c19bd66 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTenantConfigurationKeyException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTenantConfigurationKeyException.java @@ -11,13 +11,16 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** - * The {@link #InvalidTenantConfigurationKeyException} is thrown when an invalid - * configuration key is used. + * The {@link #InvalidTenantConfigurationKeyException} is thrown when an invalid configuration key is used. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class InvalidTenantConfigurationKeyException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/LockedException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/LockedException.java index aecd4974b..382fcdea3 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/LockedException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/LockedException.java @@ -11,6 +11,8 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.repository.model.BaseEntity; @@ -18,6 +20,8 @@ import org.eclipse.hawkbit.repository.model.BaseEntity; /** * Thrown if there is attempt to functionally modify a locked entity */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class LockedException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/MethodNotSupportedException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/MethodNotSupportedException.java index 6a2f10fd6..06102de4a 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/MethodNotSupportedException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/MethodNotSupportedException.java @@ -11,12 +11,16 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** * Thrown if repository operation is no longer supported. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public final class MethodNotSupportedException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/MultiAssignmentIsNotEnabledException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/MultiAssignmentIsNotEnabledException.java index 4c5020af1..63170f7e8 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/MultiAssignmentIsNotEnabledException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/MultiAssignmentIsNotEnabledException.java @@ -11,13 +11,16 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** - * This exception is thrown if an operation requires multiassignments, but the - * feature is not enabled. + * This exception is thrown if an operation requires multi-assignments, but the feature is not enabled. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class MultiAssignmentIsNotEnabledException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/NoWeightProvidedInMultiAssignmentModeException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/NoWeightProvidedInMultiAssignmentModeException.java index ef1723961..d0b35b15d 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/NoWeightProvidedInMultiAssignmentModeException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/NoWeightProvidedInMultiAssignmentModeException.java @@ -11,13 +11,16 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** - * This exception is thrown if multi assignments is enabled and an target - * distribution set assignment request does not contain a weight value + * This exception is thrown if multi assignments is enabled and a target distribution set assignment request does not contain a weight value */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class NoWeightProvidedInMultiAssignmentModeException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterSyntaxException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterSyntaxException.java index d93b0e887..490667477 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterSyntaxException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterSyntaxException.java @@ -19,8 +19,8 @@ import org.eclipse.hawkbit.exception.SpServerError; /** * Exception used by the REST API in case of RSQL search filter query. */ -@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class RSQLParameterSyntaxException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterUnsupportedFieldException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterUnsupportedFieldException.java index 5c6186030..c5dfe9f39 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterUnsupportedFieldException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterUnsupportedFieldException.java @@ -19,8 +19,8 @@ import org.eclipse.hawkbit.exception.SpServerError; /** * Exception used by the REST API in case of invalid field name in the rsql search parameter. */ -@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class RSQLParameterUnsupportedFieldException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RolloutIllegalStateException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RolloutIllegalStateException.java index 0ca71c505..d624abbc7 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RolloutIllegalStateException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RolloutIllegalStateException.java @@ -11,14 +11,17 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** - * the {@link RolloutIllegalStateException} is thrown when a rollout is changing - * it's state which is not valid. E.g. trying to start a already running - * rollout, or trying to resume a already finished rollout. + * the {@link RolloutIllegalStateException} is thrown when a rollout is changing it's state which is not valid. E.g. trying to start an already + * running rollout, or trying to resume a already finished rollout. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class RolloutIllegalStateException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/SoftwareModuleNotAssignedToTargetException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/SoftwareModuleNotAssignedToTargetException.java index 2c7a27a16..da6bd0080 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/SoftwareModuleNotAssignedToTargetException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/SoftwareModuleNotAssignedToTargetException.java @@ -12,6 +12,8 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; import java.lang.annotation.Target; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.SoftwareModule; @@ -19,6 +21,8 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule; * the {@link SoftwareModuleNotAssignedToTargetException} is thrown when a {@link SoftwareModule} is requested as part of an {@link Action} * that has however never been assigned to the {@link Target}. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class SoftwareModuleNotAssignedToTargetException extends EntityNotFoundException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/SoftwareModuleTypeNotInDistributionSetTypeException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/SoftwareModuleTypeNotInDistributionSetTypeException.java index 2ceb41e04..991f11964 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/SoftwareModuleTypeNotInDistributionSetTypeException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/SoftwareModuleTypeNotInDistributionSetTypeException.java @@ -11,16 +11,18 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; /** - * the {@link SoftwareModuleTypeNotInDistributionSetTypeException} is thrown - * when a {@link SoftwareModuleType} is requested as part of a - * {@link DistributionSetType} but actually neither - * {@link DistributionSetType#getMandatoryModuleTypes()} or + * The {@link SoftwareModuleTypeNotInDistributionSetTypeException} is thrown when a {@link SoftwareModuleType} is requested as part of a + * {@link DistributionSetType} but actually neither {@link DistributionSetType#getMandatoryModuleTypes()} or * {@link DistributionSetType#getOptionalModuleTypes()}. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class SoftwareModuleTypeNotInDistributionSetTypeException extends EntityNotFoundException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/StopRolloutException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/StopRolloutException.java index 1d827648f..7a70eaa9e 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/StopRolloutException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/StopRolloutException.java @@ -11,14 +11,17 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** - * {@link StopRolloutException} is thrown when an error occurs while stopping - * the rollout (due to an invalidation of distribution set). This could be - * caused by a long ongoing creation of a rollout. + * {@link StopRolloutException} is thrown when an error occurs while stopping the rollout (due to an invalidation of distribution set). + * This could be caused by a long ongoing creation of a rollout. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class StopRolloutException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/StorageQuotaExceededException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/StorageQuotaExceededException.java index 7a8a9c8ca..bdc12826b 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/StorageQuotaExceededException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/StorageQuotaExceededException.java @@ -12,6 +12,7 @@ package org.eclipse.hawkbit.repository.exception; import static org.eclipse.hawkbit.repository.SizeConversionHelper.byteValueToReadableString; import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; @@ -19,6 +20,7 @@ import org.eclipse.hawkbit.exception.SpServerError; * Thrown if storage quota is exceeded */ @EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class StorageQuotaExceededException extends AbstractServerRtException { private static final String MAX_ARTIFACT_SIZE_TOTAL_EXCEEDED = "Storage quota exceeded, %s left."; diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TargetTypeInUseException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TargetTypeInUseException.java index da3e9645a..07503b614 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TargetTypeInUseException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TargetTypeInUseException.java @@ -11,12 +11,16 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** * Thrown if target type is assigned */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class TargetTypeInUseException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TargetTypeKeyOrNameRequiredException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TargetTypeKeyOrNameRequiredException.java index c389072ba..e2c3952a3 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TargetTypeKeyOrNameRequiredException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TargetTypeKeyOrNameRequiredException.java @@ -11,12 +11,16 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** * Thrown if tried creation of type with no key nor name. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class TargetTypeKeyOrNameRequiredException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantConfigurationValidatorException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantConfigurationValidatorException.java index de7edd711..37a067097 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantConfigurationValidatorException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantConfigurationValidatorException.java @@ -11,13 +11,16 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** - * Exception which is thrown, when the validation of the configuration value has - * not been successful. + * Exception which is thrown, when the validation of the configuration value has not been successful. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class TenantConfigurationValidatorException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantConfigurationValueChangeNotAllowedException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantConfigurationValueChangeNotAllowedException.java index edac5e629..31578cdbc 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantConfigurationValueChangeNotAllowedException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantConfigurationValueChangeNotAllowedException.java @@ -11,12 +11,16 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** * Exception which is supposed to be thrown if a property value is valid but cannot be set in the current context. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class TenantConfigurationValueChangeNotAllowedException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantNotExistException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantNotExistException.java index 1b02564cc..7f5be4bb6 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantNotExistException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantNotExistException.java @@ -11,15 +11,17 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; /** - * the {@link TenantNotExistException} is thrown when e.g. a controller tries to - * register itself at SP as plug'n play target and the tenant specified in the - * URL for this target does not exist. To avoid that targets could register - * automatically new tenants. + * The {@link TenantNotExistException} is thrown when e.g. a controller tries to register itself at SP as plug'n play target and the tenant + * specified in the URL for this target does not exist. To avoid that targets could register automatically new tenants. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class TenantNotExistException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/UnsupportedSoftwareModuleForThisDistributionSetException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/UnsupportedSoftwareModuleForThisDistributionSetException.java index 3e2c4a7d5..99a5175d3 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/UnsupportedSoftwareModuleForThisDistributionSetException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/UnsupportedSoftwareModuleForThisDistributionSetException.java @@ -11,6 +11,8 @@ package org.eclipse.hawkbit.repository.exception; import java.io.Serial; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -18,10 +20,10 @@ import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.SoftwareModule; /** - * Thrown if user tries to add a {@link SoftwareModule} to a - * {@link DistributionSet} that is not defined by the - * {@link DistributionSetType}. + * Thrown if user tries to add a {@link SoftwareModule} to a {@link DistributionSet} that is not defined by the {@link DistributionSetType}. */ +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class UnsupportedSoftwareModuleForThisDistributionSetException extends AbstractServerRtException { @Serial diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSet.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSet.java index 300707e29..70f21fe44 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSet.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSet.java @@ -74,14 +74,4 @@ public interface DistributionSet extends NamedVersionedEntity { * and not automatically canceled if overridden by a newer update. */ boolean isRequiredMigrationStep(); - - /** - * Searches through modules for the given type. - * - * @param type to search for - * @return SoftwareModule of given type - */ - default Optional findFirstModuleByType(final SoftwareModuleType type) { - return getModules().stream().filter(module -> module.getType().equals(type)).findAny(); - } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/RepositoryConfiguration.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/RepositoryConfiguration.java index 589cb7471..d9eb5a6f6 100644 --- a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/RepositoryConfiguration.java +++ b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/RepositoryConfiguration.java @@ -14,6 +14,7 @@ import java.util.List; import java.util.Optional; import java.util.function.Supplier; +import lombok.extern.slf4j.Slf4j; import org.aopalliance.intercept.MethodInvocation; import org.eclipse.hawkbit.im.authentication.Hierarchy; import org.eclipse.hawkbit.tenancy.configuration.ControllerPollProperties; @@ -26,6 +27,8 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.PropertySource; import org.springframework.expression.EvaluationContext; +import org.springframework.security.access.PermissionEvaluator; +import org.springframework.security.access.expression.DenyAllPermissionEvaluator; import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations; @@ -40,6 +43,7 @@ import org.springframework.util.function.SingletonSupplier; /** * Default configuration that is common to all repository implementations. */ +@Slf4j @Configuration @EnableMethodSecurity(proxyTargetClass = true, securedEnabled = true) @EnableConfigurationProperties({ RepositoryProperties.class, ControllerPollProperties.class, TenantConfigurationProperties.class }) @@ -52,10 +56,37 @@ public class RepositoryConfiguration { return RoleHierarchyImpl.fromHierarchy(Hierarchy.DEFAULT); } + @Bean + PermissionEvaluator permissionEvaluator(final RoleHierarchy roleHierarchy) { + return new DenyAllPermissionEvaluator() { + + @Override + public boolean hasPermission(final Authentication authentication, final Object targetDomainObject, final Object permission) { + if (targetDomainObject instanceof MethodSecurityExpressionOperations root) { + final String neededPermission = + permission + "_" + (root.getThis() instanceof RepositoryManagement repositoryManagement + ? repositoryManagement.permissionGroup() + : "REPOSITORY"); // TODO - should not fall back here - all using parmissions should extend repository management interface + final boolean hasPermission = roleHierarchy.getReachableGrantedAuthorities(authentication.getAuthorities()).stream() + .map(GrantedAuthority::getAuthority) + .anyMatch(authority -> authority.equals(neededPermission)); + if (!hasPermission) { + log.debug( + "User {} does not have permission {} for target {}", + authentication.getName(), neededPermission, targetDomainObject); + } + return hasPermission; + } + return super.hasPermission(authentication, targetDomainObject, permission); + } + }; + } + @Bean @Primary MethodSecurityExpressionHandler methodSecurityExpressionHandler( - final Optional roleHierarchy, final Optional applicationContext) { + final RoleHierarchy roleHierarchy, final PermissionEvaluator permissionEvaluator, + final Optional applicationContext) { final DefaultMethodSecurityExpressionHandler methodSecurityExpressionHandler = new DefaultMethodSecurityExpressionHandler() { @Override @@ -69,7 +100,8 @@ public class RepositoryConfiguration { return super.createSecurityExpressionRoot(new RawAuthoritiesAuthentication(authentication), mi); } }; - roleHierarchy.ifPresent(methodSecurityExpressionHandler::setRoleHierarchy); + methodSecurityExpressionHandler.setRoleHierarchy(roleHierarchy); + methodSecurityExpressionHandler.setPermissionEvaluator(permissionEvaluator); applicationContext.ifPresent(methodSecurityExpressionHandler::setApplicationContext); return methodSecurityExpressionHandler; } diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractDistributionSetTypeUpdateCreate.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractDistributionSetTypeUpdateCreate.java deleted file mode 100644 index 284e40ee3..000000000 --- a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractDistributionSetTypeUpdateCreate.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.builder; - -import java.util.Collection; -import java.util.Optional; - -/** - * Create and update builder DTO. - * - * @param update or create builder interface - */ -public abstract class AbstractDistributionSetTypeUpdateCreate extends AbstractTypeUpdateCreate { - - protected Collection mandatory; - protected Collection optional; - - public T mandatory(final Collection mandatory) { - this.mandatory = mandatory; - return (T) this; - } - - public T optional(final Collection optional) { - this.optional = optional; - return (T) this; - } - - public Optional> getMandatory() { - return Optional.ofNullable(mandatory); - } - - public Optional> getOptional() { - return Optional.ofNullable(optional); - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractDistributionSetUpdateCreate.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractDistributionSetUpdateCreate.java deleted file mode 100644 index 814b89158..000000000 --- a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractDistributionSetUpdateCreate.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.builder; - -import java.util.Collection; -import java.util.Optional; - -import lombok.Getter; -import org.eclipse.hawkbit.repository.ValidString; - -/** - * Create and update builder DTO. - * - * @param update or create builder interface - */ -public abstract class AbstractDistributionSetUpdateCreate extends AbstractNamedEntityBuilder { - - @ValidString - protected String version; - protected Boolean requiredMigrationStep; - @Getter - protected Collection modules; - - public T modules(final Collection modules) { - this.modules = modules; - return (T) this; - } - - public T requiredMigrationStep(final Boolean requiredMigrationStep) { - this.requiredMigrationStep = requiredMigrationStep; - return (T) this; - } - - public Boolean isRequiredMigrationStep() { - return requiredMigrationStep; - } - - public T version(final String version) { - this.version = strip(version); - return (T) this; - } - - public Optional getVersion() { - return Optional.ofNullable(version); - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractSoftwareModuleTypeUpdateCreate.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractSoftwareModuleTypeUpdateCreate.java deleted file mode 100644 index c77887242..000000000 --- a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractSoftwareModuleTypeUpdateCreate.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.builder; - -/** - * Create and update builder DTO. - * - * @param update or create builder interface - */ -public abstract class AbstractSoftwareModuleTypeUpdateCreate extends AbstractTypeUpdateCreate { - - protected int maxAssignments = 1; - - public T maxAssignments(final int maxAssignments) { - this.maxAssignments = maxAssignments; - return (T) this; - } - - public int getMaxAssignments() { - return maxAssignments; - } -} diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractSoftwareModuleUpdateCreate.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractSoftwareModuleUpdateCreate.java deleted file mode 100644 index 3a2176e7f..000000000 --- a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/AbstractSoftwareModuleUpdateCreate.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.builder; - -import java.util.Optional; - -import org.eclipse.hawkbit.repository.ValidString; - -/** - * Create and update builder DTO. - * - * @param update or create builder interface - */ -public abstract class AbstractSoftwareModuleUpdateCreate extends AbstractNamedEntityBuilder { - - @ValidString - protected String version; - @ValidString - protected String vendor; - @ValidString - protected String type; - - public T type(final String type) { - this.type = AbstractBaseEntityBuilder.strip(type); - return (T) this; - } - - public Optional getType() { - return Optional.ofNullable(type); - } - - public T vendor(final String vendor) { - this.vendor = AbstractBaseEntityBuilder.strip(vendor); - return (T) this; - } - - public Optional getVendor() { - return Optional.ofNullable(vendor); - } - - public T version(final String version) { - this.version = AbstractBaseEntityBuilder.strip(version); - return (T) this; - } - - public Optional getVersion() { - return Optional.ofNullable(version); - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/GenericDistributionSetTypeUpdate.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/GenericDistributionSetTypeUpdate.java deleted file mode 100644 index 70ac5e496..000000000 --- a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/GenericDistributionSetTypeUpdate.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.builder; - -/** - * Update implementation. - */ -public class GenericDistributionSetTypeUpdate extends AbstractDistributionSetTypeUpdateCreate - implements DistributionSetTypeUpdate { - - public GenericDistributionSetTypeUpdate(final Long id) { - super.id = id; - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/GenericDistributionSetUpdate.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/GenericDistributionSetUpdate.java deleted file mode 100644 index 758afa67b..000000000 --- a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/GenericDistributionSetUpdate.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.builder; - -import jakarta.annotation.Nullable; - -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import lombok.experimental.Accessors; - -/** - * Update implementation. - */ -@Data -@Accessors(fluent = true) // override locked() -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class GenericDistributionSetUpdate extends AbstractDistributionSetUpdateCreate implements DistributionSetUpdate { - - @Nullable - protected Boolean locked; - - public GenericDistributionSetUpdate(final Long id) { - super.id = id; - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/GenericSoftwareModuleTypeUpdate.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/GenericSoftwareModuleTypeUpdate.java deleted file mode 100644 index 8cdfca95f..000000000 --- a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/GenericSoftwareModuleTypeUpdate.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.builder; - -/** - * Update implementation. - */ -public class GenericSoftwareModuleTypeUpdate extends AbstractSoftwareModuleTypeUpdateCreate - implements SoftwareModuleTypeUpdate { - - public GenericSoftwareModuleTypeUpdate(final Long id) { - super.id = id; - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/GenericSoftwareModuleUpdate.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/GenericSoftwareModuleUpdate.java deleted file mode 100644 index 76e203e5f..000000000 --- a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/builder/GenericSoftwareModuleUpdate.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.builder; - -import jakarta.annotation.Nullable; - -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import lombok.experimental.Accessors; - -/** - * Update implementation. - */ -@Data -@Accessors(fluent = true) // override locked() -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class GenericSoftwareModuleUpdate extends AbstractSoftwareModuleUpdateCreate - implements SoftwareModuleUpdate { - - @Nullable - protected Boolean locked; - - public GenericSoftwareModuleUpdate(final Long id) { - super.id = id; - } -} \ No newline at end of file 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 new file mode 100644 index 000000000..7488a45d6 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa-api/src/main/java/org/eclipse/hawkbit/repository/jpa/utils/ExceptionMapper.java @@ -0,0 +1,127 @@ +/** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.repository.jpa.utils; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.eclipse.hawkbit.exception.GenericSpServerException; +import org.eclipse.hawkbit.repository.exception.ConcurrentModificationException; +import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; +import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.dao.OptimisticLockingFailureException; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.authorization.AuthorizationDeniedException; +import org.springframework.transaction.TransactionSystemException; + +/** + * Maps the exception thrown by the management classes to management exceptions + */ +@NoArgsConstructor(access = lombok.AccessLevel.PRIVATE) +@Slf4j +public class ExceptionMapper { + + private static final Map EXCEPTION_MAPPING = new HashMap<>(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 + private static final List> MAPPED_EXCEPTION_ORDER = new ArrayList<>(4); + + static { + MAPPED_EXCEPTION_ORDER.add(DuplicateKeyException.class); + MAPPED_EXCEPTION_ORDER.add(OptimisticLockingFailureException.class); + MAPPED_EXCEPTION_ORDER.add(AccessDeniedException.class); + + EXCEPTION_MAPPING.put(DuplicateKeyException.class.getName(), EntityAlreadyExistsException.class.getName()); + EXCEPTION_MAPPING.put(OptimisticLockingFailureException.class.getName(), ConcurrentModificationException.class.getName()); + EXCEPTION_MAPPING.put(AccessDeniedException.class.getName(), InsufficientPermissionException.class.getName()); + + EXCEPTION_MAPPING.put("org.hibernate.exception.ConstraintViolationException", EntityAlreadyExistsException.class.getName()); + EXCEPTION_MAPPING.put(AuthorizationDeniedException.class.getName(), InsufficientPermissionException.class.getName()); + } + + public static RuntimeException mapRe(final Exception e) { + final Exception mapped = map(e); + if (RuntimeException.class.isAssignableFrom(mapped.getClass())) { + return (RuntimeException) mapped; + } else { + return new GenericSpServerException(mapped); + } + } + + /** + * Maps exceptions of the TransactionManager and PreAuthorize and wrap them to custom exceptions. + * + * @param e the thrown and catch exception + * @return the mapped exception + */ + public static Exception map(final Exception e) { + if (log.isTraceEnabled()) { + log.trace("Handling exception {}", e.getClass().getName(), e); + } else { + log.debug("Handling exception {}", e.getClass().getName()); + } + + // Workaround for EclipseLink merge where it does not throw ConstraintViolationException directly in case of existing entity update + if (e instanceof TransactionSystemException transactionSystemException) { + return replaceWithCauseIfConstraintViolationException(transactionSystemException); + } + + for (final Class mappedEx : MAPPED_EXCEPTION_ORDER) { + if (!mappedEx.isAssignableFrom(e.getClass())) { + continue; + } + + if (EXCEPTION_MAPPING.containsKey(mappedEx.getName())) { + try { + return (Exception) Class.forName(EXCEPTION_MAPPING.get(mappedEx.getName())).getConstructor(Throwable.class).newInstance(e); + } catch (final ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException ex) { + log.error(ex.getMessage(), ex); + return e; + } + } + + log.error("there is no mapping configured for exception class {}", mappedEx.getName()); + return new GenericSpServerException(e); + } + + // not ordered + final String mappingClass = EXCEPTION_MAPPING.get(e.getClass().getName()); + if (mappingClass != null) { + try { + return (Exception) Class.forName(mappingClass).getConstructor(Throwable.class).newInstance(e); + } catch (final ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException ex) { + log.error(ex.getMessage(), ex); + return e; + } + } + + return e; + } + + private static Exception replaceWithCauseIfConstraintViolationException(final TransactionSystemException rex) { + Throwable exception = rex; + do { + final Throwable cause = exception.getCause(); + if (cause instanceof jakarta.validation.ConstraintViolationException) { + return (Exception) cause; + } + exception = cause; + } while (exception != null); + + return rex; + } +} \ No newline at end of file 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 bb32ddc8a..49007c814 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 @@ -61,15 +61,13 @@ public class JpaConfiguration extends JpaBaseConfiguration { } /** - * {@link MultiTenantJpaTransactionManager} bean. - * - * @return a new {@link PlatformTransactionManager} - * @see org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration#transactionManager(ObjectProvider) + * {@link TransactionManager} bean. It mainly handles the tenancy but some other thins like conversion of dao / jpa exceptions to + * transaction exceptions */ @Override @Bean public PlatformTransactionManager transactionManager(final ObjectProvider transactionManagerCustomizers) { - return new MultiTenantJpaTransactionManager(tenantResolver); + return new TransactionManager(tenantResolver); } @Override diff --git a/hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/MultiTenantJpaTransactionManager.java b/hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/TransactionManager.java similarity index 79% rename from hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/MultiTenantJpaTransactionManager.java rename to hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/TransactionManager.java index c78bc86f7..d069be7ab 100644 --- a/hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/MultiTenantJpaTransactionManager.java +++ b/hawkbit-repository/hawkbit-repository-jpa-eclipselink/src/main/java/org/eclipse/hawkbit/repository/jpa/TransactionManager.java @@ -16,32 +16,37 @@ import jakarta.persistence.EntityManager; import jakarta.transaction.Transaction; import org.eclipse.hawkbit.repository.jpa.model.EntityPropertyChangeListener; +import org.eclipse.hawkbit.repository.jpa.utils.ExceptionMapper; import org.eclipse.hawkbit.tenancy.TenantAware; import org.eclipse.persistence.config.PersistenceUnitProperties; import org.eclipse.persistence.descriptors.ClassDescriptor; import org.eclipse.persistence.descriptors.DescriptorEventManager; import org.eclipse.persistence.sessions.Session; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.orm.jpa.EntityManagerHolder; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.transaction.TransactionDefinition; +import org.springframework.transaction.support.DefaultTransactionStatus; import org.springframework.transaction.support.TransactionSynchronizationManager; /** - * {@link JpaTransactionManager} that sets the {@link TenantAware#getCurrentTenant()} in the eclipselink session. This has + * {@link org.springframework.orm.jpa.JpaTransactionManager} that sets the {@link TenantAware#getCurrentTenant()} in the eclipselink session. This has * to be done in eclipselink after a {@link Transaction} has been started. *

- * The class also handles setting the {@link EntityPropertyChangeListener} to the {@link DescriptorEventManager} of the + * The class also handles setting: + *

    + *
  • the {@link EntityPropertyChangeListener} to the {@link DescriptorEventManager}
  • + *
  • exception on doCommit mapping to management exceptions
  • + *
*/ -class MultiTenantJpaTransactionManager extends JpaTransactionManager { +class TransactionManager extends JpaTransactionManager { @Serial private static final long serialVersionUID = 1L; + + private static final Class JPA_TARGET; private transient TenantAware.TenantResolver tenantResolver; - private static final Class JPA_TARGET; - static { try { JPA_TARGET = Class.forName("org.eclipse.hawkbit.repository.jpa.model.JpaTarget"); @@ -52,7 +57,7 @@ class MultiTenantJpaTransactionManager extends JpaTransactionManager { } } - MultiTenantJpaTransactionManager(final TenantAware.TenantResolver tenantResolver) { + TransactionManager(final TenantAware.TenantResolver tenantResolver) { this.tenantResolver = tenantResolver; } @@ -86,6 +91,15 @@ class MultiTenantJpaTransactionManager extends JpaTransactionManager { } } + @Override + protected void doCommit(final DefaultTransactionStatus status) { + try { + super.doCommit(status); + } catch (final RuntimeException e) { + throw ExceptionMapper.mapRe(e); + } + } + private void cleanupTenant(final EntityManager em) { if (em.isOpen() && em.getProperties().containsKey(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT)) { em.setProperty(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT, ""); diff --git a/hawkbit-repository/hawkbit-repository-jpa-hibernate/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaConfiguration.java b/hawkbit-repository/hawkbit-repository-jpa-hibernate/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaConfiguration.java index e1453b975..d095c5ace 100644 --- a/hawkbit-repository/hawkbit-repository-jpa-hibernate/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaConfiguration.java +++ b/hawkbit-repository/hawkbit-repository-jpa-hibernate/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaConfiguration.java @@ -16,6 +16,7 @@ import java.util.Map; import lombok.Data; import org.eclipse.hawkbit.repository.jpa.model.EntityPropertyChangeListener; +import org.eclipse.hawkbit.repository.jpa.utils.ExceptionMapper; import org.eclipse.hawkbit.repository.jpa.utils.JpaExceptionTranslator; import org.eclipse.hawkbit.tenancy.TenantAware; import org.hibernate.boot.Metadata; @@ -29,17 +30,21 @@ import org.hibernate.integrator.spi.Integrator; import org.hibernate.jpa.boot.spi.IntegratorProvider; import org.hibernate.service.spi.SessionFactoryServiceRegistry; import org.springframework.beans.factory.ObjectProvider; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration; import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties; +import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter; import org.springframework.orm.jpa.vendor.HibernateJpaDialect; import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.security.core.parameters.P; +import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.jta.JtaTransactionManager; +import org.springframework.transaction.support.DefaultTransactionStatus; import javax.sql.DataSource; @@ -88,6 +93,25 @@ public class JpaConfiguration extends JpaBaseConfiguration { }; } + /** + * {@link PlatformTransactionManager} bean. It handles conversion of dao / jpa exceptions to transaction exceptions + */ + @Override + @Bean + public PlatformTransactionManager transactionManager(final ObjectProvider transactionManagerCustomizers) { + return new JpaTransactionManager() { + + @Override + protected void doCommit(final DefaultTransactionStatus status) { + try { + super.doCommit(status); + } catch (final RuntimeException e) { + throw ExceptionMapper.mapRe(e); + } + } + }; + } + @Override protected Map getVendorProperties(final DataSource dataSource) { final Map properties = new HashMap<>(); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/CustomBaseRepositoryFactoryBean.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/CustomBaseRepositoryFactoryBean.java deleted file mode 100644 index e8eb42ff4..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/CustomBaseRepositoryFactoryBean.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright (c) 2021 Bosch.IO GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.jpa; - -import jakarta.persistence.EntityManager; - -import org.eclipse.hawkbit.repository.BaseRepositoryTypeProvider; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean; -import org.springframework.data.repository.Repository; -import org.springframework.data.repository.core.support.RepositoryFactorySupport; -import org.springframework.lang.NonNull; - -/** - * A {@link JpaRepositoryFactoryBean} extension that allow injection of custom repository factories by using a - * {@link BaseRepositoryTypeProvider} implementation, allows injecting different base repository implementations based on repository type - */ -@SuppressWarnings("java:S119") // java:S119 - ID is inherited from JpaRepositoryFactoryBean -public class CustomBaseRepositoryFactoryBean, S, ID> extends JpaRepositoryFactoryBean { - - private BaseRepositoryTypeProvider baseRepoProvider; - - /** - * Creates a new {@link JpaRepositoryFactoryBean} for the given repository interface. - * - * @param repositoryInterface must not be {@literal null}. - */ - public CustomBaseRepositoryFactoryBean(final Class repositoryInterface) { - super(repositoryInterface); - } - - @Autowired // if it is a constructor injection sometimes doesn't work - base repo provider is not available at construct time - public void setBaseRepoProvider(final BaseRepositoryTypeProvider baseRepoProvider) { - this.baseRepoProvider = baseRepoProvider; - } - - @Override - protected RepositoryFactorySupport createRepositoryFactory(@NonNull final EntityManager entityManager) { - final RepositoryFactorySupport rfs = super.createRepositoryFactory(entityManager); - rfs.setRepositoryBaseClass(baseRepoProvider.getBaseRepositoryType(getObjectType())); - return rfs; - } -} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/HawkbitBaseRepositoryFactoryBean.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/HawkbitBaseRepositoryFactoryBean.java new file mode 100644 index 000000000..e4ca8d306 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/HawkbitBaseRepositoryFactoryBean.java @@ -0,0 +1,140 @@ +/** + * Copyright (c) 2021 Bosch.IO GmbH and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.repository.jpa; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Proxy; +import java.util.Collections; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; + +import org.eclipse.hawkbit.repository.jpa.repository.HawkbitBaseRepository; +import org.eclipse.hawkbit.repository.jpa.utils.ExceptionMapper; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.jpa.repository.query.EscapeCharacter; +import org.springframework.data.jpa.repository.query.JpaQueryMethodFactory; +import org.springframework.data.jpa.repository.support.JpaRepositoryFactory; +import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean; +import org.springframework.data.jpa.repository.support.JpaRepositoryImplementation; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.querydsl.EntityPathResolver; +import org.springframework.data.querydsl.SimpleEntityPathResolver; +import org.springframework.data.repository.Repository; +import org.springframework.data.repository.core.RepositoryInformation; +import org.springframework.data.repository.core.support.RepositoryFactorySupport; +import org.springframework.data.repository.core.support.TransactionalRepositoryFactoryBeanSupport; +import org.springframework.lang.Nullable; + +/** + * A {@link TransactionalRepositoryFactoryBeanSupport} extension that uses {@link HawkbitBaseRepository} as base repository and + * proxied repositories in order to convert exceptions to management exceptions. + */ +@SuppressWarnings("java:S119") // java:S119 - ID is inherited from TransactionalRepositoryFactoryBeanSupport +public class HawkbitBaseRepositoryFactoryBean, S, ID> extends TransactionalRepositoryFactoryBeanSupport { + + private EntityPathResolver entityPathResolver; + private EscapeCharacter escapeCharacter = EscapeCharacter.DEFAULT; + private JpaQueryMethodFactory queryMethodFactory; + + @Nullable + private EntityManager entityManager; + + /** + * Creates a new {@link JpaRepositoryFactoryBean} for the given repository interface. + * + * @param repositoryInterface must not be {@literal null}. + */ + public HawkbitBaseRepositoryFactoryBean(final Class repositoryInterface) { + super(repositoryInterface); + } + + @Autowired + public void setEntityPathResolver(final ObjectProvider resolver) { + this.entityPathResolver = resolver.getIfAvailable(() -> SimpleEntityPathResolver.INSTANCE); + } + + @Autowired + public void setEscapeCharacter(final char escapeCharacter) { + this.escapeCharacter = EscapeCharacter.of(escapeCharacter); + } + + @Autowired + public void setQueryMethodFactory(@Nullable final JpaQueryMethodFactory factory) { + if (factory != null) { + this.queryMethodFactory = factory; + } + } + + @PersistenceContext + public void setEntityManager(final EntityManager entityManager) { + this.entityManager = entityManager; + } + + @Override + public void afterPropertiesSet() { + Objects.requireNonNull(entityManager, "EntityManager must not be null"); + super.afterPropertiesSet(); + } + + @Override + public void setMappingContext(final MappingContext mappingContext) { + super.setMappingContext(mappingContext); + } + + @Override + protected RepositoryFactorySupport doCreateRepositoryFactory() { + Objects.requireNonNull(entityManager, "EntityManager must not be null"); + final JpaRepositoryFactory jpaRepositoryFactory = new JpaRepositoryFactory(entityManager) { + + @Override + protected JpaRepositoryImplementation getTargetRepository( + final RepositoryInformation information, final EntityManager entityManager) { + final JpaRepositoryImplementation jpaRepositoryImplementation = super.getTargetRepository(information, entityManager); + return (JpaRepositoryImplementation) Proxy.newProxyInstance( + jpaRepositoryImplementation.getClass().getClassLoader(), + interfaces(jpaRepositoryImplementation.getClass(), new HashSet<>()).toArray(new Class[0]), + (proxy, method, args) -> { + try { + return method.invoke(jpaRepositoryImplementation, args); + } catch (final InvocationTargetException e) { + final Throwable cause = e.getCause() == null ? e : e.getCause(); + throw cause instanceof Exception exc ? ExceptionMapper.map(exc) : e; + } catch (final Exception e) { + throw ExceptionMapper.map(e); + } + }); + } + }; + + jpaRepositoryFactory.setEntityPathResolver(entityPathResolver); + jpaRepositoryFactory.setEscapeCharacter(escapeCharacter); + + if (queryMethodFactory != null) { + jpaRepositoryFactory.setQueryMethodFactory(queryMethodFactory); + } + jpaRepositoryFactory.setRepositoryBaseClass(HawkbitBaseRepository.class); + return jpaRepositoryFactory; + } + + private static Set> interfaces(final Class type, final Set> interfaces) { + Collections.addAll(interfaces, type.getInterfaces()); + final Class superclass = type.getSuperclass(); + if (superclass != null && superclass != Object.class) { + return interfaces(superclass, interfaces); + } else { + return interfaces; + } + } +} \ No newline at end of file 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 3a3eb0902..624880002 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 @@ -11,21 +11,17 @@ package org.eclipse.hawkbit.repository.jpa; import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.builder.ActionStatusBuilder; -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.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.builder.TargetTypeBuilder; import org.eclipse.hawkbit.repository.jpa.builder.JpaActionStatusBuilder; 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.model.Tag; import org.springframework.validation.annotation.Validated; /** @@ -37,26 +33,19 @@ public class JpaEntityFactory implements EntityFactory { private final TargetBuilder targetBuilder; private final TargetTypeBuilder targetTypeBuilder; private final TargetFilterQueryBuilder targetFilterQueryBuilder; - private final SoftwareModuleBuilder softwareModuleBuilder; private final SoftwareModuleMetadataBuilder softwareModuleMetadataBuilder; - private final DistributionSetBuilder distributionSetBuilder; - private final DistributionSetTypeBuilder distributionSetTypeBuilder; private final RolloutBuilder rolloutBuilder; @SuppressWarnings("java:S107") public JpaEntityFactory( final TargetBuilder targetBuilder, final TargetTypeBuilder targetTypeBuilder, final TargetFilterQueryBuilder targetFilterQueryBuilder, - final SoftwareModuleBuilder softwareModuleBuilder, final SoftwareModuleMetadataBuilder softwareModuleMetadataBuilder, - final DistributionSetBuilder distributionSetBuilder, final DistributionSetTypeBuilder distributionSetTypeBuilder, + final SoftwareModuleMetadataBuilder softwareModuleMetadataBuilder, final RolloutBuilder rolloutBuilder) { this.targetBuilder = targetBuilder; this.targetTypeBuilder = targetTypeBuilder; this.targetFilterQueryBuilder = targetFilterQueryBuilder; - this.softwareModuleBuilder = softwareModuleBuilder; this.softwareModuleMetadataBuilder = softwareModuleMetadataBuilder; - this.distributionSetBuilder = distributionSetBuilder; - this.distributionSetTypeBuilder = distributionSetTypeBuilder; this.rolloutBuilder = rolloutBuilder; } @Override @@ -64,46 +53,27 @@ public class JpaEntityFactory implements EntityFactory { return new JpaActionStatusBuilder(); } - @Override - public DistributionSetBuilder distributionSet() { - return distributionSetBuilder; - } - @Override public SoftwareModuleMetadataBuilder softwareModuleMetadata() { return softwareModuleMetadataBuilder; } @Override - public TagBuilder tag() { - return new JpaTagBuilder(); + public TagBuilder tag() { + return (TagBuilder)new JpaTagBuilder(); } + @Override public RolloutGroupBuilder rolloutGroup() { return new JpaRolloutGroupBuilder(); } - @Override - public DistributionSetTypeBuilder distributionSetType() { - return distributionSetTypeBuilder; - } - @Override public RolloutBuilder rollout() { return rolloutBuilder; } - @Override - public SoftwareModuleBuilder softwareModule() { - return softwareModuleBuilder; - } - - @Override - public SoftwareModuleTypeBuilder softwareModuleType() { - return new JpaSoftwareModuleTypeBuilder(); - } - @Override public TargetBuilder target() { return targetBuilder; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRepositoryConfiguration.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRepositoryConfiguration.java index e3c13a0c5..ee3a4989c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRepositoryConfiguration.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRepositoryConfiguration.java @@ -11,7 +11,6 @@ package org.eclipse.hawkbit.repository.jpa; import java.util.List; import java.util.Optional; -import java.util.concurrent.ScheduledExecutorService; import javax.sql.DataSource; @@ -19,19 +18,10 @@ import jakarta.persistence.EntityManager; import jakarta.validation.Validation; import io.micrometer.core.instrument.MeterRegistry; +import org.aopalliance.intercept.MethodInvocation; import org.eclipse.hawkbit.ContextAware; -import org.eclipse.hawkbit.repository.artifact.ArtifactRepository; -import org.eclipse.hawkbit.cache.TenancyCacheManager; -import org.eclipse.hawkbit.repository.artifact.encryption.ArtifactEncryption; -import org.eclipse.hawkbit.repository.artifact.encryption.ArtifactEncryptionSecretsStore; -import org.eclipse.hawkbit.repository.artifact.encryption.ArtifactEncryptionService; -import org.eclipse.hawkbit.repository.ArtifactManagement; -import org.eclipse.hawkbit.repository.BaseRepositoryTypeProvider; -import org.eclipse.hawkbit.repository.ConfirmationManagement; -import org.eclipse.hawkbit.repository.ControllerManagement; import org.eclipse.hawkbit.repository.DeploymentManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement; -import org.eclipse.hawkbit.repository.DistributionSetTagManagement; import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.PropertiesQuotaManagement; @@ -44,20 +34,16 @@ import org.eclipse.hawkbit.repository.RolloutGroupManagement; import org.eclipse.hawkbit.repository.RolloutHandler; import org.eclipse.hawkbit.repository.RolloutManagement; import org.eclipse.hawkbit.repository.RolloutStatusCache; -import org.eclipse.hawkbit.repository.SoftwareModuleManagement; -import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.TargetManagement; -import org.eclipse.hawkbit.repository.TargetTagManagement; import org.eclipse.hawkbit.repository.TargetTypeManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement; -import org.eclipse.hawkbit.repository.TenantStatsManagement; +import org.eclipse.hawkbit.repository.artifact.encryption.ArtifactEncryption; +import org.eclipse.hawkbit.repository.artifact.encryption.ArtifactEncryptionSecretsStore; +import org.eclipse.hawkbit.repository.artifact.encryption.ArtifactEncryptionService; import org.eclipse.hawkbit.repository.autoassign.AutoAssignExecutor; -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.TargetBuilder; import org.eclipse.hawkbit.repository.builder.TargetFilterQueryBuilder; @@ -73,38 +59,18 @@ import org.eclipse.hawkbit.repository.jpa.autoassign.AutoAssignScheduler; import org.eclipse.hawkbit.repository.jpa.autocleanup.AutoActionCleanup; import org.eclipse.hawkbit.repository.jpa.autocleanup.AutoCleanupScheduler; import org.eclipse.hawkbit.repository.jpa.autocleanup.CleanupTask; -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.JpaTargetBuilder; import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetFilterQueryBuilder; import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetTypeBuilder; -import org.eclipse.hawkbit.repository.jpa.cluster.LockProperties; import org.eclipse.hawkbit.repository.jpa.cluster.DistributedLockRepository; +import org.eclipse.hawkbit.repository.jpa.cluster.LockProperties; import org.eclipse.hawkbit.repository.jpa.event.JpaEventEntityManager; import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitDefaultServiceExecutor; import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor; -import org.eclipse.hawkbit.repository.jpa.management.JpaArtifactManagement; -import org.eclipse.hawkbit.repository.jpa.management.JpaConfirmationManagement; -import org.eclipse.hawkbit.repository.jpa.management.JpaControllerManagement; -import org.eclipse.hawkbit.repository.jpa.management.JpaDeploymentManagement; -import org.eclipse.hawkbit.repository.jpa.management.JpaDistributionSetInvalidationManagement; -import org.eclipse.hawkbit.repository.jpa.management.JpaDistributionSetManagement; -import org.eclipse.hawkbit.repository.jpa.management.JpaDistributionSetTagManagement; -import org.eclipse.hawkbit.repository.jpa.management.JpaDistributionSetTypeManagement; -import org.eclipse.hawkbit.repository.jpa.management.JpaRolloutGroupManagement; -import org.eclipse.hawkbit.repository.jpa.management.JpaRolloutManagement; +import org.eclipse.hawkbit.repository.jpa.utils.ExceptionMapper; import org.eclipse.hawkbit.repository.jpa.management.JpaSoftwareModuleManagement; -import org.eclipse.hawkbit.repository.jpa.management.JpaSoftwareModuleTypeManagement; -import org.eclipse.hawkbit.repository.jpa.management.JpaSystemManagement; -import org.eclipse.hawkbit.repository.jpa.management.JpaTargetFilterQueryManagement; -import org.eclipse.hawkbit.repository.jpa.management.JpaTargetManagement; -import org.eclipse.hawkbit.repository.jpa.management.JpaTargetTagManagement; -import org.eclipse.hawkbit.repository.jpa.management.JpaTargetTypeManagement; -import org.eclipse.hawkbit.repository.jpa.management.JpaTenantConfigurationManagement; -import org.eclipse.hawkbit.repository.jpa.management.JpaTenantStatsManagement; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.jpa.model.JpaArtifact; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; @@ -118,24 +84,16 @@ import org.eclipse.hawkbit.repository.jpa.model.helper.EntityInterceptorHolder; import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityTokenGeneratorHolder; import org.eclipse.hawkbit.repository.jpa.model.helper.TenantAwareHolder; import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository; -import org.eclipse.hawkbit.repository.jpa.repository.ActionStatusRepository; import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetRepository; -import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetTagRepository; import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetTypeRepository; -import org.eclipse.hawkbit.repository.jpa.repository.HawkbitBaseRepository; import org.eclipse.hawkbit.repository.jpa.repository.LocalArtifactRepository; import org.eclipse.hawkbit.repository.jpa.repository.RolloutGroupRepository; import org.eclipse.hawkbit.repository.jpa.repository.RolloutRepository; import org.eclipse.hawkbit.repository.jpa.repository.RolloutTargetGroupRepository; -import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleMetadataRepository; import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleRepository; import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleTypeRepository; -import org.eclipse.hawkbit.repository.jpa.repository.TargetFilterQueryRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository; -import org.eclipse.hawkbit.repository.jpa.repository.TargetTagRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetTypeRepository; -import org.eclipse.hawkbit.repository.jpa.repository.TenantConfigurationRepository; -import org.eclipse.hawkbit.repository.jpa.repository.TenantMetaDataRepository; import org.eclipse.hawkbit.repository.jpa.rollout.RolloutScheduler; import org.eclipse.hawkbit.repository.jpa.rollout.condition.PauseRolloutGroupAction; import org.eclipse.hawkbit.repository.jpa.rollout.condition.RolloutGroupActionEvaluator; @@ -144,25 +102,19 @@ import org.eclipse.hawkbit.repository.jpa.rollout.condition.RolloutGroupEvaluati import org.eclipse.hawkbit.repository.jpa.rollout.condition.StartNextGroupRolloutGroupSuccessAction; import org.eclipse.hawkbit.repository.jpa.rollout.condition.ThresholdRolloutGroupErrorCondition; import org.eclipse.hawkbit.repository.jpa.rollout.condition.ThresholdRolloutGroupSuccessCondition; -import org.eclipse.hawkbit.repository.model.DistributionSet; -import org.eclipse.hawkbit.repository.model.DistributionSetType; +import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility; import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.SoftwareModule; -import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.repository.model.TargetType; import org.eclipse.hawkbit.repository.model.helper.SystemSecurityContextHolder; import org.eclipse.hawkbit.repository.model.helper.TenantConfigurationManagementHolder; -import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility; import org.eclipse.hawkbit.security.HawkbitSecurityProperties; import org.eclipse.hawkbit.security.SecurityTokenGenerator; import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.tenancy.TenantAware; import org.eclipse.hawkbit.tenancy.UserAuthoritiesResolver; -import org.eclipse.hawkbit.tenancy.configuration.ControllerPollProperties; -import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties; -import org.eclipse.hawkbit.utils.TenantConfigHelper; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -172,16 +124,13 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; -import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties; -import org.springframework.cache.CacheManager; -import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Profile; import org.springframework.context.annotation.PropertySource; -import org.springframework.data.domain.AuditorAware; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.integration.jdbc.lock.DefaultLockRepository; @@ -192,14 +141,19 @@ import org.springframework.integration.support.locks.LockRegistry; import org.springframework.lang.NonNull; import org.springframework.retry.annotation.EnableRetry; import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.security.authorization.AuthorizationDeniedException; +import org.springframework.security.authorization.AuthorizationResult; +import org.springframework.security.authorization.method.MethodAuthorizationDeniedHandler; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.validation.beanvalidation.MethodValidationPostProcessor; +; + /** * General configuration for hawkBit's Repository. */ -@EnableJpaRepositories(value = "org.eclipse.hawkbit.repository.jpa.repository", repositoryFactoryBeanClass = CustomBaseRepositoryFactoryBean.class) +@EnableJpaRepositories(value = "org.eclipse.hawkbit.repository.jpa.repository", repositoryFactoryBeanClass = HawkbitBaseRepositoryFactoryBean.class) @EnableTransactionManagement @EnableJpaAuditing @EnableAspectJAutoProxy @@ -207,8 +161,10 @@ import org.springframework.validation.beanvalidation.MethodValidationPostProcess @EnableScheduling @EnableRetry @EntityScan("org.eclipse.hawkbit.repository.jpa.model") +@ComponentScan("org.eclipse.hawkbit.repository.jpa.management") @PropertySource("classpath:/hawkbit-jpa-defaults.properties") -@Import({ JpaConfiguration.class, RepositoryConfiguration.class, LockProperties.class, DataSourceAutoConfiguration.class, SystemManagementCacheKeyGenerator.class }) +@Import({ JpaConfiguration.class, RepositoryConfiguration.class, LockProperties.class, DataSourceAutoConfiguration.class, + SystemManagementCacheKeyGenerator.class }) @AutoConfigureAfter(DataSourceAutoConfiguration.class) public class JpaRepositoryConfiguration { @@ -224,7 +180,8 @@ public class JpaRepositoryConfiguration { // methods shall not be called - we need the validator in future processor.setValidator(Validation.byDefaultProvider() .configure() - .addProperty(org.hibernate.validator.BaseHibernateValidatorConfiguration.ALLOW_PARALLEL_METHODS_DEFINE_PARAMETER_CONSTRAINTS, "true") + .addProperty(org.hibernate.validator.BaseHibernateValidatorConfiguration.ALLOW_PARALLEL_METHODS_DEFINE_PARAMETER_CONSTRAINTS, + "true") .buildValidatorFactory() .getValidator()); return processor; @@ -270,7 +227,8 @@ public class JpaRepositoryConfiguration { @Bean @ConditionalOnProperty(name = "hawkbit.lock", havingValue = "distributed", matchIfMissing = true) @ConditionalOnMissingBean - LockRepository lockRepository(final DataSource dataSource, final LockProperties lockProperties, final PlatformTransactionManager txManager) { + LockRepository lockRepository(final DataSource dataSource, final LockProperties lockProperties, + final PlatformTransactionManager txManager) { final DefaultLockRepository repository = new DistributedLockRepository(dataSource, lockProperties, txManager); repository.setPrefix("SP_"); return repository; @@ -279,7 +237,7 @@ public class JpaRepositoryConfiguration { @Bean @ConditionalOnMissingBean public LockRegistry lockRegistry(final Optional lockRepository) { - return lockRepository.map(JdbcLockRegistry::new).orElseGet(DefaultLockRegistry::new); + return lockRepository. map(JdbcLockRegistry::new).orElseGet(DefaultLockRegistry::new); } @Bean @@ -351,17 +309,6 @@ public class JpaRepositoryConfiguration { return e -> e instanceof TargetPollEvent && !repositoryProperties.isPublishTargetPollEvent(); } - /** - * @param distributionSetTypeManagement to loading the {@link DistributionSetType} - * @param softwareManagement for loading {@link DistributionSet#getModules()} - * @return DistributionSetBuilder bean - */ - @Bean - DistributionSetBuilder distributionSetBuilder(final DistributionSetTypeManagement distributionSetTypeManagement, - final SoftwareModuleManagement softwareManagement) { - return new JpaDistributionSetBuilder(distributionSetTypeManagement, softwareManagement); - } - @Bean TargetBuilder targetBuilder(final TargetTypeManagement targetTypeManagement) { return new JpaTargetBuilder(targetTypeManagement); @@ -378,30 +325,10 @@ public class JpaRepositoryConfiguration { @Bean SoftwareModuleMetadataBuilder softwareModuleMetadataBuilder( - final SoftwareModuleManagement softwareModuleManagement) { + final JpaSoftwareModuleManagement softwareModuleManagement) { return new JpaSoftwareModuleMetadataBuilder(softwareModuleManagement); } - /** - * @param softwareModuleTypeManagement for loading {@link DistributionSetType#getMandatoryModuleTypes()} - * and {@link DistributionSetType#getOptionalModuleTypes()} - * @return DistributionSetTypeBuilder bean - */ - @Bean - DistributionSetTypeBuilder distributionSetTypeBuilder( - final SoftwareModuleTypeManagement softwareModuleTypeManagement) { - return new JpaDistributionSetTypeBuilder(softwareModuleTypeManagement); - } - - /** - * @param softwareModuleTypeManagement for loading {@link SoftwareModule#getType()} - * @return SoftwareModuleBuilder bean - */ - @Bean - SoftwareModuleBuilder softwareModuleBuilder(final SoftwareModuleTypeManagement softwareModuleTypeManagement) { - return new JpaSoftwareModuleBuilder(softwareModuleTypeManagement); - } - /** * @param distributionSetManagement for loading {@link Rollout#getDistributionSet()} * @return RolloutBuilder bean @@ -485,221 +412,6 @@ public class JpaRepositoryConfiguration { return new ExceptionMappingAspectHandler(); } - /** - * Default {@link BaseRepositoryTypeProvider} bean always provides the NoCountBaseRepository - * - * @return a {@link BaseRepositoryTypeProvider} bean - */ - @Bean - @ConditionalOnMissingBean - BaseRepositoryTypeProvider baseRepositoryTypeProvider() { - return new HawkbitBaseRepository.RepositoryTypeProvider(); - } - - /** - * {@link JpaSystemManagement} bean. - * - * @return a new {@link SystemManagement} - */ - @Bean - @ConditionalOnMissingBean - SystemManagement systemManagement( - final TargetRepository targetRepository, final TargetTypeRepository targetTypeRepository, - final TargetTagRepository targetTagRepository, final TargetFilterQueryRepository targetFilterQueryRepository, - final SoftwareModuleRepository softwareModuleRepository, final SoftwareModuleTypeRepository softwareModuleTypeRepository, - final DistributionSetRepository distributionSetRepository, final DistributionSetTypeRepository distributionSetTypeRepository, - final DistributionSetTagRepository distributionSetTagRepository, final RolloutRepository rolloutRepository, - final TenantConfigurationRepository tenantConfigurationRepository, final TenantMetaDataRepository tenantMetaDataRepository, - final TenantStatsManagement systemStatsManagement, final SystemManagementCacheKeyGenerator currentTenantCacheKeyGenerator, - final SystemSecurityContext systemSecurityContext, final TenantAware tenantAware, final PlatformTransactionManager txManager, - final TenancyCacheManager cacheManager, final RolloutStatusCache rolloutStatusCache, - final EntityManager entityManager, final RepositoryProperties repositoryProperties, - final JpaProperties properties) { - return new JpaSystemManagement(targetRepository, targetTypeRepository, targetTagRepository, - targetFilterQueryRepository, softwareModuleRepository, softwareModuleTypeRepository, distributionSetRepository, - distributionSetTypeRepository, distributionSetTagRepository, rolloutRepository, tenantConfigurationRepository, - tenantMetaDataRepository, systemStatsManagement, currentTenantCacheKeyGenerator, systemSecurityContext, - tenantAware, txManager, cacheManager, rolloutStatusCache, entityManager, repositoryProperties, properties); - } - - /** - * {@link JpaDistributionSetManagement} bean. - * - * @return a new {@link DistributionSetManagement} - */ - @Bean - @ConditionalOnMissingBean - DistributionSetManagement distributionSetManagement( - final EntityManager entityManager, - final DistributionSetRepository distributionSetRepository, - final DistributionSetTagManagement distributionSetTagManagement, final SystemManagement systemManagement, - final DistributionSetTypeManagement distributionSetTypeManagement, final QuotaManagement quotaManagement, - final TargetRepository targetRepository, - final TargetFilterQueryRepository targetFilterQueryRepository, final ActionRepository actionRepository, - final SystemSecurityContext systemSecurityContext, final TenantConfigurationManagement tenantConfigurationManagement, - final SoftwareModuleRepository softwareModuleRepository, - final DistributionSetTagRepository distributionSetTagRepository, final RepositoryProperties repositoryProperties) { - return new JpaDistributionSetManagement(entityManager, distributionSetRepository, distributionSetTagManagement, - systemManagement, distributionSetTypeManagement, quotaManagement, - targetRepository, targetFilterQueryRepository, actionRepository, - TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement), - softwareModuleRepository, distributionSetTagRepository, repositoryProperties); - } - - /** - * {@link JpaDistributionSetManagement} bean. - * - * @return a new {@link DistributionSetManagement} - */ - @Bean - @ConditionalOnMissingBean - DistributionSetTypeManagement distributionSetTypeManagement( - final DistributionSetTypeRepository distributionSetTypeRepository, - final SoftwareModuleTypeRepository softwareModuleTypeRepository, - final DistributionSetRepository distributionSetRepository, final TargetTypeRepository targetTypeRepository, - final QuotaManagement quotaManagement) { - return new JpaDistributionSetTypeManagement(distributionSetTypeRepository, softwareModuleTypeRepository, - distributionSetRepository, targetTypeRepository, quotaManagement); - } - - /** - * {@link JpaTargetTypeManagement} bean. - * - * @return a new {@link TargetTypeManagement} - */ - @Bean - @ConditionalOnMissingBean - TargetTypeManagement targetTypeManagement(final TargetTypeRepository targetTypeRepository, - final TargetRepository targetRepository, final DistributionSetTypeRepository distributionSetTypeRepository, - final QuotaManagement quotaManagement) { - return new JpaTargetTypeManagement(targetTypeRepository, targetRepository, distributionSetTypeRepository, quotaManagement); - } - - /** - * {@link JpaTenantStatsManagement} bean. - * - * @return a new {@link TenantStatsManagement} - */ - @Bean - @ConditionalOnMissingBean - TenantStatsManagement tenantStatsManagement( - final TargetRepository targetRepository, final LocalArtifactRepository artifactRepository, final ActionRepository actionRepository, - final TenantAware tenantAware) { - return new JpaTenantStatsManagement(targetRepository, artifactRepository, actionRepository, tenantAware); - } - - /** - * {@link JpaTenantConfigurationManagement} bean. - * - * @return a new {@link TenantConfigurationManagement} - */ - @Bean - @ConditionalOnMissingBean - TenantConfigurationManagement tenantConfigurationManagement( - final TenantConfigurationRepository tenantConfigurationRepository, - final TenantConfigurationProperties tenantConfigurationProperties, - final CacheManager cacheManager, final AfterTransactionCommitExecutor afterCommitExecutor, - final ApplicationContext applicationContext) { - return new JpaTenantConfigurationManagement(tenantConfigurationRepository, tenantConfigurationProperties, - cacheManager, afterCommitExecutor, applicationContext); - } - - /** - * {@link JpaTargetManagement} bean. - * - * @return a new {@link JpaTargetManagement} - */ - @Bean - @ConditionalOnMissingBean - TargetManagement targetManagement( - final EntityManager entityManager, final QuotaManagement quotaManagement, - final TargetRepository targetRepository, - final RolloutGroupRepository rolloutGroupRepository, - final TargetFilterQueryRepository targetFilterQueryRepository, - final TargetTypeRepository targetTypeRepository, final TargetTagRepository targetTagRepository, - final TenantAware tenantAware, final DistributionSetManagement distributionSetManagement) { - return new JpaTargetManagement(entityManager, distributionSetManagement, quotaManagement, targetRepository, - targetTypeRepository, rolloutGroupRepository, targetFilterQueryRepository, - targetTagRepository, tenantAware); - } - - /** - * {@link JpaTargetFilterQueryManagement} bean. - * - * @param targetFilterQueryRepository holding {@link TargetFilterQuery} entities - * @param targetManagement managing {@link Target} entities - * @param distributionSetManagement for auto assign DS access - * @param quotaManagement to access quotas - * @return a new {@link TargetFilterQueryManagement} - */ - @Bean - @ConditionalOnMissingBean - TargetFilterQueryManagement targetFilterQueryManagement( - final TargetFilterQueryRepository targetFilterQueryRepository, final TargetManagement targetManagement, - final DistributionSetManagement distributionSetManagement, final QuotaManagement quotaManagement, - final TenantConfigurationManagement tenantConfigurationManagement, final RepositoryProperties repositoryProperties, - final SystemSecurityContext systemSecurityContext, final ContextAware contextAware, final AuditorAware auditorAware) { - return new JpaTargetFilterQueryManagement(targetFilterQueryRepository, targetManagement, - distributionSetManagement, quotaManagement, tenantConfigurationManagement, repositoryProperties, - systemSecurityContext, contextAware, auditorAware); - } - - /** - * {@link JpaTargetTagManagement} bean. - * - * @return a new {@link TargetTagManagement} - */ - @Bean - @ConditionalOnMissingBean - TargetTagManagement targetTagManagement(final TargetTagRepository targetTagRepository) { - return new JpaTargetTagManagement(targetTagRepository); - } - - /** - * {@link JpaDistributionSetTagManagement} bean. - * - * @return a new {@link JpaDistributionSetTagManagement} - */ - @Bean - @ConditionalOnMissingBean - DistributionSetTagManagement distributionSetTagManagement( - final DistributionSetTagRepository distributionSetTagRepository, - final DistributionSetRepository distributionSetRepository) { - return new JpaDistributionSetTagManagement( - distributionSetTagRepository, distributionSetRepository); - } - - /** - * {@link JpaSoftwareModuleManagement} bean. - * - * @return a new {@link SoftwareModuleManagement} - */ - @Bean - @ConditionalOnMissingBean - SoftwareModuleManagement softwareModuleManagement(final EntityManager entityManager, - final DistributionSetRepository distributionSetRepository, - final SoftwareModuleRepository softwareModuleRepository, - final SoftwareModuleMetadataRepository softwareModuleMetadataRepository, - final SoftwareModuleTypeRepository softwareModuleTypeRepository, final AuditorAware auditorProvider, - final ArtifactManagement artifactManagement, final QuotaManagement quotaManagement) { - return new JpaSoftwareModuleManagement(entityManager, distributionSetRepository, softwareModuleRepository, - softwareModuleMetadataRepository, softwareModuleTypeRepository, auditorProvider, artifactManagement, quotaManagement); - } - - /** - * {@link JpaSoftwareModuleTypeManagement} bean. - * - * @return a new {@link SoftwareModuleTypeManagement} - */ - @Bean - @ConditionalOnMissingBean - SoftwareModuleTypeManagement softwareModuleTypeManagement( - final DistributionSetTypeRepository distributionSetTypeRepository, - final SoftwareModuleTypeRepository softwareModuleTypeRepository, - final SoftwareModuleRepository softwareModuleRepository) { - return new JpaSoftwareModuleTypeManagement(distributionSetTypeRepository, softwareModuleTypeRepository, softwareModuleRepository); - } - @Bean @ConditionalOnMissingBean RolloutHandler rolloutHandler(final TenantAware tenantAware, final RolloutManagement rolloutManagement, @@ -726,28 +438,6 @@ public class JpaRepositoryConfiguration { tenantAware, repositoryProperties); } - @Bean - @ConditionalOnMissingBean - RolloutManagement rolloutManagement( - final RolloutRepository rolloutRepository, - final RolloutGroupRepository rolloutGroupRepository, - final RolloutApprovalStrategy rolloutApprovalStrategy, - final StartNextGroupRolloutGroupSuccessAction startNextRolloutGroupAction, - final RolloutStatusCache rolloutStatusCache, - final ActionRepository actionRepository, - final TargetManagement targetManagement, - final DistributionSetManagement distributionSetManagement, - final TenantConfigurationManagement tenantConfigurationManagement, - final QuotaManagement quotaManagement, - final AfterTransactionCommitExecutor afterCommit, - final SystemSecurityContext systemSecurityContext, final ContextAware contextAware, - final RepositoryProperties repositoryProperties) { - return new JpaRolloutManagement(rolloutRepository, rolloutGroupRepository, rolloutApprovalStrategy, - startNextRolloutGroupAction, rolloutStatusCache, actionRepository, targetManagement, - distributionSetManagement, tenantConfigurationManagement, quotaManagement, afterCommit, - systemSecurityContext, contextAware, repositoryProperties); - } - /** * {@link DefaultRolloutApprovalStrategy} bean. * @@ -758,90 +448,7 @@ public class JpaRepositoryConfiguration { RolloutApprovalStrategy rolloutApprovalStrategy(final UserAuthoritiesResolver userAuthoritiesResolver, final TenantConfigurationManagement tenantConfigurationManagement, final SystemSecurityContext systemSecurityContext) { - return new DefaultRolloutApprovalStrategy(userAuthoritiesResolver, tenantConfigurationManagement, - systemSecurityContext); - } - - /** - * {@link JpaRolloutGroupManagement} bean. - * - * @return a new {@link RolloutGroupManagement} - */ - @Bean - @ConditionalOnMissingBean - RolloutGroupManagement rolloutGroupManagement(final RolloutGroupRepository rolloutGroupRepository, - final RolloutRepository rolloutRepository, final ActionRepository actionRepository, - final TargetRepository targetRepository, final EntityManager entityManager, final RolloutStatusCache rolloutStatusCache) { - return new JpaRolloutGroupManagement(rolloutGroupRepository, rolloutRepository, actionRepository, - targetRepository, entityManager, rolloutStatusCache); - } - - /** - * {@link JpaDeploymentManagement} bean. - * - * @return a new {@link DeploymentManagement} - */ - @Bean - @ConditionalOnMissingBean - DeploymentManagement deploymentManagement(final EntityManager entityManager, - final ActionRepository actionRepository, - final DistributionSetManagement distributionSetManagement, final TargetRepository targetRepository, - final ActionStatusRepository actionStatusRepository, final AuditorAware auditorProvider, - final AfterTransactionCommitExecutor afterCommit, final PlatformTransactionManager txManager, - final TenantConfigurationManagement tenantConfigurationManagement, final QuotaManagement quotaManagement, - final SystemSecurityContext systemSecurityContext, final TenantAware tenantAware, final AuditorAware auditorAware, - final JpaProperties properties, final RepositoryProperties repositoryProperties) { - return new JpaDeploymentManagement(entityManager, actionRepository, distributionSetManagement, targetRepository, actionStatusRepository, - auditorProvider, - afterCommit, txManager, tenantConfigurationManagement, - quotaManagement, systemSecurityContext, tenantAware, auditorAware, properties.getDatabase(), repositoryProperties); - } - - @Bean - @ConditionalOnMissingBean - ConfirmationManagement confirmationManagement(final TargetRepository targetRepository, - final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository, - final RepositoryProperties repositoryProperties, final QuotaManagement quotaManagement, - final EntityManager entityManager, final EntityFactory entityFactory) { - return new JpaConfirmationManagement(targetRepository, actionRepository, actionStatusRepository, - repositoryProperties, quotaManagement, entityManager, entityFactory); - } - - /** - * {@link JpaControllerManagement} bean. - * - * @return a new {@link ControllerManagement} - */ - @Bean - @ConditionalOnMissingBean - ControllerManagement controllerManagement( - final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository, final QuotaManagement quotaManagement, - final RepositoryProperties repositoryProperties, - final TargetRepository targetRepository, final TargetTypeManagement targetTypeManagement, - final DeploymentManagement deploymentManagement, final ConfirmationManagement confirmationManagement, - final SoftwareModuleRepository softwareModuleRepository, final SoftwareModuleMetadataRepository softwareModuleMetadataRepository, - final DistributionSetManagement distributionSetManagement, - final TenantConfigurationManagement tenantConfigurationManagement, final ControllerPollProperties controllerPollProperties, - final PlatformTransactionManager txManager, final EntityFactory entityFactory, final EntityManager entityManager, - final AfterTransactionCommitExecutor afterCommit, - final SystemSecurityContext systemSecurityContext, final TenantAware tenantAware, - final ScheduledExecutorService executorService) { - return new JpaControllerManagement(actionRepository, actionStatusRepository, quotaManagement, repositoryProperties, - targetRepository, targetTypeManagement, deploymentManagement, confirmationManagement, softwareModuleRepository, - softwareModuleMetadataRepository, distributionSetManagement, tenantConfigurationManagement, controllerPollProperties, - txManager,entityFactory, entityManager, afterCommit, systemSecurityContext, tenantAware, executorService); - } - - @Bean - @ConditionalOnMissingBean - ArtifactManagement artifactManagement( - final EntityManager entityManager, final PlatformTransactionManager txManager, - final LocalArtifactRepository localArtifactRepository, final SoftwareModuleRepository softwareModuleRepository, - final Optional artifactRepository, - final QuotaManagement quotaManagement, final TenantAware tenantAware) { - return new JpaArtifactManagement( - entityManager, txManager, localArtifactRepository, softwareModuleRepository, artifactRepository.orElse(null), - quotaManagement, tenantAware); + return new DefaultRolloutApprovalStrategy(userAuthoritiesResolver, tenantConfigurationManagement, systemSecurityContext); } /** @@ -854,11 +461,11 @@ public class JpaRepositoryConfiguration { EntityFactory entityFactory( final TargetBuilder targetBuilder, final TargetTypeBuilder targetTypeBuilder, final TargetFilterQueryBuilder targetFilterQueryBuilder, - final SoftwareModuleBuilder softwareModuleBuilder, final SoftwareModuleMetadataBuilder softwareModuleMetadataBuilder, - final DistributionSetBuilder distributionSetBuilder, final DistributionSetTypeBuilder distributionSetTypeBuilder, + final SoftwareModuleMetadataBuilder softwareModuleMetadataBuilder, final RolloutBuilder rolloutBuilder) { - return new JpaEntityFactory(targetBuilder, targetTypeBuilder, targetFilterQueryBuilder, softwareModuleBuilder, - softwareModuleMetadataBuilder, distributionSetBuilder, distributionSetTypeBuilder, rolloutBuilder); + return new JpaEntityFactory( + targetBuilder, targetTypeBuilder, targetFilterQueryBuilder, + softwareModuleMetadataBuilder, rolloutBuilder); } /** @@ -976,7 +583,7 @@ public class JpaRepositoryConfiguration { RolloutScheduler rolloutScheduler( final SystemManagement systemManagement, final RolloutHandler rolloutHandler, final SystemSecurityContext systemSecurityContext, @Value("${hawkbit.rollout.executor.thread-pool.size:1}") final int threadPoolSize, final Optional meterRegistry) { - return new RolloutScheduler(rolloutHandler, systemManagement, systemSecurityContext, threadPoolSize, meterRegistry); + return new RolloutScheduler(rolloutHandler, systemManagement, systemSecurityContext, threadPoolSize, meterRegistry); } /** @@ -989,25 +596,6 @@ public class JpaRepositoryConfiguration { return RsqlUtility.getInstance(); } - /** - * {@link JpaDistributionSetInvalidationManagement} bean. - * - * @return a new {@link JpaDistributionSetInvalidationManagement} - */ - @Bean - @ConditionalOnMissingBean - JpaDistributionSetInvalidationManagement distributionSetInvalidationManagement( - final DistributionSetManagement distributionSetManagement, final RolloutManagement rolloutManagement, - final DeploymentManagement deploymentManagement, - final TargetFilterQueryManagement targetFilterQueryManagement, final ActionRepository actionRepository, - final PlatformTransactionManager txManager, final RepositoryProperties repositoryProperties, - final TenantAware tenantAware, final LockRegistry lockRegistry, - final SystemSecurityContext systemSecurityContext) { - return new JpaDistributionSetInvalidationManagement(distributionSetManagement, rolloutManagement, - deploymentManagement, targetFilterQueryManagement, actionRepository, txManager, repositoryProperties, - tenantAware, lockRegistry, systemSecurityContext); - } - /** * Default artifact encryption service bean that internally uses {@link ArtifactEncryption} and * {@link ArtifactEncryptionSecretsStore} beans for {@link SoftwareModule} artifacts encryption/decryption @@ -1019,4 +607,20 @@ public class JpaRepositoryConfiguration { ArtifactEncryptionService artifactEncryptionService() { return ArtifactEncryptionService.getInstance(); } -} + + @Bean + ManagementExceptionThrowingMethodAuthorizationDeniedHandler managementExceptionThrowingMethodAuthorizationDeniedHandler() { + return new ManagementExceptionThrowingMethodAuthorizationDeniedHandler(); + } + + public static class ManagementExceptionThrowingMethodAuthorizationDeniedHandler implements MethodAuthorizationDeniedHandler { + + @Override + public Object handleDeniedInvocation(final MethodInvocation methodInvocation, final AuthorizationResult authorizationResult) { + throw ExceptionMapper.mapRe( + authorizationResult instanceof AuthorizationDeniedException denied + ? denied + : new AuthorizationDeniedException("Access Denied", authorizationResult)); + } + } +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/aspects/ExceptionMappingAspectHandler.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/aspects/ExceptionMappingAspectHandler.java index 7715fd34c..78a95a750 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/aspects/ExceptionMappingAspectHandler.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/aspects/ExceptionMappingAspectHandler.java @@ -9,25 +9,13 @@ */ package org.eclipse.hawkbit.repository.jpa.aspects; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import jakarta.transaction.TransactionManager; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; -import org.eclipse.hawkbit.exception.GenericSpServerException; -import org.eclipse.hawkbit.repository.exception.ConcurrentModificationException; -import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; -import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; +import org.eclipse.hawkbit.repository.jpa.utils.ExceptionMapper; import org.springframework.core.Ordered; -import org.springframework.dao.DuplicateKeyException; -import org.springframework.dao.OptimisticLockingFailureException; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.transaction.TransactionSystemException; /** * {@link Aspect} catches persistence exceptions and wraps them to custom @@ -38,27 +26,8 @@ import org.springframework.transaction.TransactionSystemException; @Aspect public class ExceptionMappingAspectHandler implements Ordered { - private static final Map EXCEPTION_MAPPING = new HashMap<>(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. - */ - private static final List> MAPPED_EXCEPTION_ORDER = new ArrayList<>(4); - - static { - MAPPED_EXCEPTION_ORDER.add(DuplicateKeyException.class); - MAPPED_EXCEPTION_ORDER.add(OptimisticLockingFailureException.class); - MAPPED_EXCEPTION_ORDER.add(AccessDeniedException.class); - - EXCEPTION_MAPPING.put(DuplicateKeyException.class.getName(), EntityAlreadyExistsException.class.getName()); - - EXCEPTION_MAPPING.put(OptimisticLockingFailureException.class.getName(), ConcurrentModificationException.class.getName()); - EXCEPTION_MAPPING.put(AccessDeniedException.class.getName(), InsufficientPermissionException.class.getName()); - } - - /** - * catch exceptions of the {@link TransactionManager} and wrap them to custom exceptions. + * Catches exceptions of the {@link TransactionManager} and wrap them to custom exceptions. * * @param ex the thrown and catched exception * @throws Throwable @@ -68,48 +37,11 @@ public class ExceptionMappingAspectHandler implements Ordered { // It is a AspectJ proxy which deals with exceptions. @SuppressWarnings({ "squid:S00112", "squid:S1162" }) public void catchAndWrapJpaExceptionsService(final Exception ex) throws Throwable { - if (log.isTraceEnabled()) { - log.trace("Handling exception {}", ex.getClass().getName(), ex); - } else { - log.debug("Handling exception {}", ex.getClass().getName()); - } - - // Workaround for EclipseLink merge where it does not throw ConstraintViolationException directly in case of existing entity update - if (ex instanceof TransactionSystemException transactionSystemException) { - throw replaceWithCauseIfConstraintViolationException(transactionSystemException); - } - - for (final Class mappedEx : MAPPED_EXCEPTION_ORDER) { - if (!mappedEx.isAssignableFrom(ex.getClass())) { - continue; - } - - if (EXCEPTION_MAPPING.containsKey(mappedEx.getName())) { - throw (Exception) Class.forName(EXCEPTION_MAPPING.get(mappedEx.getName())).getConstructor(Throwable.class).newInstance(ex); - } - - log.error("there is no mapping configured for exception class {}", mappedEx.getName()); - throw new GenericSpServerException(ex); - } - - throw ex; + throw ExceptionMapper.map(ex); } @Override public int getOrder() { return 1; } - - private static Exception replaceWithCauseIfConstraintViolationException(final TransactionSystemException rex) { - Throwable exception = rex; - do { - final Throwable cause = exception.getCause(); - if (cause instanceof jakarta.validation.ConstraintViolationException) { - return (Exception) cause; - } - exception = cause; - } while (exception != null); - - return rex; - } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetBuilder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetBuilder.java deleted file mode 100644 index 6bfa10697..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetBuilder.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.jpa.builder; - -import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; -import org.eclipse.hawkbit.repository.SoftwareModuleManagement; -import org.eclipse.hawkbit.repository.builder.DistributionSetBuilder; -import org.eclipse.hawkbit.repository.builder.DistributionSetCreate; -import org.eclipse.hawkbit.repository.builder.DistributionSetUpdate; -import org.eclipse.hawkbit.repository.builder.GenericDistributionSetUpdate; -import org.eclipse.hawkbit.repository.model.DistributionSet; - -/** - * Builder implementation for {@link DistributionSet}. - */ -public class JpaDistributionSetBuilder implements DistributionSetBuilder { - - private final DistributionSetTypeManagement distributionSetTypeManagement; - private final SoftwareModuleManagement softwareModuleManagement; - - public JpaDistributionSetBuilder(final DistributionSetTypeManagement distributionSetTypeManagement, - final SoftwareModuleManagement softwareManagement) { - this.distributionSetTypeManagement = distributionSetTypeManagement; - this.softwareModuleManagement = softwareManagement; - } - - @Override - public DistributionSetUpdate update(final long id) { - return new GenericDistributionSetUpdate(id); - } - - @Override - public DistributionSetCreate create() { - return new JpaDistributionSetCreate(distributionSetTypeManagement, softwareModuleManagement); - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetCreate.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetCreate.java deleted file mode 100644 index 47ae763c3..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetCreate.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.jpa.builder; - -import java.util.Collection; -import java.util.Collections; -import java.util.Optional; - -import lombok.Getter; -import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; -import org.eclipse.hawkbit.repository.SoftwareModuleManagement; -import org.eclipse.hawkbit.repository.ValidString; -import org.eclipse.hawkbit.repository.builder.AbstractDistributionSetUpdateCreate; -import org.eclipse.hawkbit.repository.builder.DistributionSetCreate; -import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; -import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; -import org.eclipse.hawkbit.repository.model.DistributionSetType; -import org.eclipse.hawkbit.repository.model.SoftwareModule; -import org.springframework.util.CollectionUtils; - -/** - * Create/build implementation. - */ -public class JpaDistributionSetCreate extends AbstractDistributionSetUpdateCreate implements DistributionSetCreate { - - private final DistributionSetTypeManagement distributionSetTypeManagement; - private final SoftwareModuleManagement softwareModuleManagement; - - @Getter - @ValidString - private String type; - - JpaDistributionSetCreate( - final DistributionSetTypeManagement distributionSetTypeManagement, final SoftwareModuleManagement softwareManagement) { - this.distributionSetTypeManagement = distributionSetTypeManagement; - this.softwareModuleManagement = softwareManagement; - } - - @Override - public DistributionSetCreate type(final String type) { - this.type = type.strip(); - return this; - } - - @Override - public JpaDistributionSet build() { - return new JpaDistributionSet( - name, version, description, - Optional.ofNullable(type).map(this::findDistributionSetTypeWithExceptionIfNotFound).orElse(null), - findSoftwareModuleWithExceptionIfNotFound(modules), - Optional.ofNullable(requiredMigrationStep).orElse(Boolean.FALSE)); - } - - private DistributionSetType findDistributionSetTypeWithExceptionIfNotFound(final String distributionSetTypekey) { - return distributionSetTypeManagement.findByKey(distributionSetTypekey) - .orElseThrow(() -> new EntityNotFoundException(DistributionSetType.class, distributionSetTypekey)); - } - - private Collection findSoftwareModuleWithExceptionIfNotFound(final Collection softwareModuleIds) { - if (CollectionUtils.isEmpty(softwareModuleIds)) { - return Collections.emptyList(); - } - - final Collection modules = softwareModuleManagement.get(softwareModuleIds); - if (modules.size() < softwareModuleIds.size()) { - throw new EntityNotFoundException(SoftwareModule.class, softwareModuleIds); - } - - return modules; - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetTypeBuilder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetTypeBuilder.java deleted file mode 100644 index 81980ac7f..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetTypeBuilder.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.jpa.builder; - -import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; -import org.eclipse.hawkbit.repository.builder.DistributionSetTypeBuilder; -import org.eclipse.hawkbit.repository.builder.DistributionSetTypeCreate; -import org.eclipse.hawkbit.repository.builder.DistributionSetTypeUpdate; -import org.eclipse.hawkbit.repository.builder.GenericDistributionSetTypeUpdate; -import org.eclipse.hawkbit.repository.model.DistributionSetType; - -/** - * Builder implementation for {@link DistributionSetType}. - */ -public class JpaDistributionSetTypeBuilder implements DistributionSetTypeBuilder { - - private final SoftwareModuleTypeManagement softwareModuleTypeManagement; - - public JpaDistributionSetTypeBuilder(final SoftwareModuleTypeManagement softwareModuleTypeManagement) { - this.softwareModuleTypeManagement = softwareModuleTypeManagement; - } - - @Override - public DistributionSetTypeUpdate update(final long id) { - return new GenericDistributionSetTypeUpdate(id); - } - - @Override - public DistributionSetTypeCreate create() { - return new JpaDistributionSetTypeCreate(softwareModuleTypeManagement); - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetTypeCreate.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetTypeCreate.java deleted file mode 100644 index 5f285ecf5..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaDistributionSetTypeCreate.java +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.jpa.builder; - -import java.util.Collection; -import java.util.Collections; - -import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; -import org.eclipse.hawkbit.repository.builder.AbstractDistributionSetTypeUpdateCreate; -import org.eclipse.hawkbit.repository.builder.DistributionSetTypeCreate; -import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; -import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType; -import org.eclipse.hawkbit.repository.model.SoftwareModuleType; -import org.springframework.util.CollectionUtils; - -/** - * Create/build implementation. - */ -public class JpaDistributionSetTypeCreate extends AbstractDistributionSetTypeUpdateCreate - implements DistributionSetTypeCreate { - - private final SoftwareModuleTypeManagement softwareModuleTypeManagement; - - JpaDistributionSetTypeCreate(final SoftwareModuleTypeManagement softwareModuleTypeManagement) { - this.softwareModuleTypeManagement = softwareModuleTypeManagement; - } - - @Override - public JpaDistributionSetType build() { - final JpaDistributionSetType result = new JpaDistributionSetType(key, name, description, colour); - - findSoftwareModuleTypeWithExceptionIfNotFound(mandatory).forEach(result::addMandatoryModuleType); - findSoftwareModuleTypeWithExceptionIfNotFound(optional).forEach(result::addOptionalModuleType); - - return result; - } - - private Collection findSoftwareModuleTypeWithExceptionIfNotFound( - final Collection softwareModuleTypeId) { - if (CollectionUtils.isEmpty(softwareModuleTypeId)) { - return Collections.emptyList(); - } - - final Collection module = softwareModuleTypeManagement.get(softwareModuleTypeId); - if (module.size() < softwareModuleTypeId.size()) { - throw new EntityNotFoundException(SoftwareModuleType.class, softwareModuleTypeId); - } - - return module; - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleBuilder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleBuilder.java deleted file mode 100644 index beb264438..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleBuilder.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.jpa.builder; - -import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; -import org.eclipse.hawkbit.repository.builder.GenericSoftwareModuleUpdate; -import org.eclipse.hawkbit.repository.builder.SoftwareModuleBuilder; -import org.eclipse.hawkbit.repository.builder.SoftwareModuleCreate; -import org.eclipse.hawkbit.repository.builder.SoftwareModuleUpdate; -import org.eclipse.hawkbit.repository.model.SoftwareModule; - -/** - * Builder implementation for {@link SoftwareModule}. - */ -public class JpaSoftwareModuleBuilder implements SoftwareModuleBuilder { - - private final SoftwareModuleTypeManagement softwareModuleTypeManagement; - - public JpaSoftwareModuleBuilder(final SoftwareModuleTypeManagement softwareModuleTypeManagement) { - this.softwareModuleTypeManagement = softwareModuleTypeManagement; - } - - @Override - public SoftwareModuleUpdate update(final long id) { - return new GenericSoftwareModuleUpdate(id); - } - - @Override - public SoftwareModuleCreate create() { - return new JpaSoftwareModuleCreate(softwareModuleTypeManagement); - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleCreate.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleCreate.java deleted file mode 100644 index 5ecda4a65..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleCreate.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.jpa.builder; - -import jakarta.validation.ValidationException; - -import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; -import org.eclipse.hawkbit.repository.builder.AbstractSoftwareModuleUpdateCreate; -import org.eclipse.hawkbit.repository.builder.SoftwareModuleCreate; -import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; -import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; -import org.eclipse.hawkbit.repository.model.SoftwareModuleType; - -/** - * Create/build implementation. - */ -public class JpaSoftwareModuleCreate extends AbstractSoftwareModuleUpdateCreate implements SoftwareModuleCreate { - - private final SoftwareModuleTypeManagement softwareModuleTypeManagement; - private boolean encrypted; - - JpaSoftwareModuleCreate(final SoftwareModuleTypeManagement softwareModuleTypeManagement) { - this.softwareModuleTypeManagement = softwareModuleTypeManagement; - } - - @Override - public SoftwareModuleCreate encrypted(final boolean encrypted) { - this.encrypted = encrypted; - return this; - } - - @Override - public JpaSoftwareModule build() { - return new JpaSoftwareModule(getSoftwareModuleTypeFromKeyString(type), name, version, description, vendor, - encrypted); - } - - public boolean isEncrypted() { - return encrypted; - } - - private SoftwareModuleType getSoftwareModuleTypeFromKeyString(final String type) { - if (type == null) { - throw new ValidationException("type cannot be null"); - } - - return softwareModuleTypeManagement.findByKey(type.trim()) - .orElseThrow(() -> new EntityNotFoundException(SoftwareModuleType.class, type.trim())); - } -} \ No newline at end of file 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 index e4e63a318..81ccf74d3 100644 --- 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 @@ -9,11 +9,11 @@ */ 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.jpa.management.JpaSoftwareModuleManagement; import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; /** @@ -21,9 +21,9 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; */ public class JpaSoftwareModuleMetadataBuilder implements SoftwareModuleMetadataBuilder { - private final SoftwareModuleManagement softwareModuleManagement; + private final JpaSoftwareModuleManagement softwareModuleManagement; - public JpaSoftwareModuleMetadataBuilder(final SoftwareModuleManagement softwareModuleManagement) { + public JpaSoftwareModuleMetadataBuilder(final JpaSoftwareModuleManagement softwareModuleManagement) { this.softwareModuleManagement = 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 index 947976e10..db11e9771 100644 --- 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 @@ -9,10 +9,11 @@ */ 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.management.JpaSoftwareModuleManagement; +import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleMetadata; import org.eclipse.hawkbit.repository.model.SoftwareModule; @@ -23,16 +24,16 @@ public class JpaSoftwareModuleMetadataCreate extends AbstractSoftwareModuleMetadataUpdateCreate implements SoftwareModuleMetadataCreate { - private final SoftwareModuleManagement softwareModuleManagement; + private final JpaSoftwareModuleManagement softwareModuleManagement; - JpaSoftwareModuleMetadataCreate(final long softwareModuleId, final SoftwareModuleManagement softwareModuleManagement) { + JpaSoftwareModuleMetadataCreate(final long softwareModuleId, final JpaSoftwareModuleManagement softwareModuleManagement) { this.softwareModuleManagement = softwareModuleManagement; this.softwareModuleId = softwareModuleId; } @Override public JpaSoftwareModuleMetadata build() { - final SoftwareModule module = softwareModuleManagement.get(softwareModuleId) + final JpaSoftwareModule module = softwareModuleManagement.get(softwareModuleId) .orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, softwareModuleId)); if (key == null) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleTypeBuilder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleTypeBuilder.java deleted file mode 100644 index d22284765..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleTypeBuilder.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.jpa.builder; - -import org.eclipse.hawkbit.repository.builder.GenericSoftwareModuleTypeUpdate; -import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeBuilder; -import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeCreate; -import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeUpdate; -import org.eclipse.hawkbit.repository.model.SoftwareModuleType; - -/** - * Builder implementation for {@link SoftwareModuleType}. - */ -public class JpaSoftwareModuleTypeBuilder implements SoftwareModuleTypeBuilder { - - @Override - public SoftwareModuleTypeUpdate update(final long id) { - return new GenericSoftwareModuleTypeUpdate(id); - } - - @Override - public SoftwareModuleTypeCreate create() { - return new JpaSoftwareModuleTypeCreate(); - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleTypeCreate.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleTypeCreate.java deleted file mode 100644 index 7b3d582a0..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaSoftwareModuleTypeCreate.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.eclipse.hawkbit.repository.jpa.builder; - -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import org.eclipse.hawkbit.repository.builder.AbstractSoftwareModuleTypeUpdateCreate; -import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeCreate; -import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType; - -/** - * Create/build implementation. - */ -@NoArgsConstructor(access = AccessLevel.PACKAGE) -public class JpaSoftwareModuleTypeCreate extends AbstractSoftwareModuleTypeUpdateCreate - implements SoftwareModuleTypeCreate { - - @Override - public JpaSoftwareModuleType build() { - return new JpaSoftwareModuleType(key, name, description, maxAssignments, colour); - } -} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTagBuilder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTagBuilder.java index 9334c954c..ad9e325ae 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTagBuilder.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTagBuilder.java @@ -13,12 +13,13 @@ import org.eclipse.hawkbit.repository.builder.GenericTagUpdate; import org.eclipse.hawkbit.repository.builder.TagBuilder; import org.eclipse.hawkbit.repository.builder.TagCreate; import org.eclipse.hawkbit.repository.builder.TagUpdate; +import org.eclipse.hawkbit.repository.jpa.model.JpaTag; import org.eclipse.hawkbit.repository.model.Tag; /** * Builder implementation for {@link Tag}. */ -public class JpaTagBuilder implements TagBuilder { +public class JpaTagBuilder implements TagBuilder { @Override public TagUpdate update(final long id) { @@ -26,7 +27,7 @@ public class JpaTagBuilder implements TagBuilder { } @Override - public TagCreate create() { + public TagCreate create() { return new JpaTagCreate(); } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTagCreate.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTagCreate.java index f2d859538..b0fed3f48 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTagCreate.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/builder/JpaTagCreate.java @@ -13,27 +13,21 @@ import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.eclipse.hawkbit.repository.builder.AbstractTagUpdateCreate; import org.eclipse.hawkbit.repository.builder.TagCreate; -import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag; import org.eclipse.hawkbit.repository.jpa.model.JpaTag; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag; -import org.eclipse.hawkbit.repository.model.Tag; /** * Create/build implementation. */ @NoArgsConstructor(access = AccessLevel.PACKAGE) -public class JpaTagCreate extends AbstractTagUpdateCreate implements TagCreate { - - public JpaDistributionSetTag buildDistributionSetTag() { - return new JpaDistributionSetTag(name, description, colour); - } +public class JpaTagCreate extends AbstractTagUpdateCreate> implements TagCreate { public JpaTargetTag buildTargetTag() { return new JpaTargetTag(name, description, colour); } @Override - public Tag build() { + public JpaTag build() { return new JpaTag(name, description, colour); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/AbstractJpaRepositoryManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/AbstractJpaRepositoryManagement.java new file mode 100644 index 000000000..3c42ea421 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/AbstractJpaRepositoryManagement.java @@ -0,0 +1,333 @@ +/** + * Copyright (c) 2015 Bosch Software Innovations GmbH and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.repository.jpa.management; + +import static org.eclipse.hawkbit.repository.jpa.configuration.Constants.TX_RT_DELAY; +import static org.eclipse.hawkbit.repository.jpa.configuration.Constants.TX_RT_MAX; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaUpdate; +import jakarta.persistence.criteria.Root; +import jakarta.validation.constraints.NotNull; + +import org.eclipse.hawkbit.repository.DistributionSetManagement; +import org.eclipse.hawkbit.repository.Identifiable; +import org.eclipse.hawkbit.repository.RepositoryManagement; +import org.eclipse.hawkbit.repository.RsqlQueryField; +import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; +import org.eclipse.hawkbit.repository.jpa.Jpa; +import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper; +import org.eclipse.hawkbit.repository.jpa.JpaRepositoryConfiguration; +import org.eclipse.hawkbit.repository.jpa.acm.AccessController; +import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity; +import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_; +import org.eclipse.hawkbit.repository.jpa.repository.BaseEntityRepository; +import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility; +import org.eclipse.hawkbit.utils.ObjectCopyUtil; +import org.springframework.dao.ConcurrencyFailureException; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.retry.annotation.Backoff; +import org.springframework.retry.annotation.Retryable; +import org.springframework.security.authorization.method.HandleAuthorizationDenied; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.ObjectUtils; +import org.springframework.util.function.SingletonSupplier; +import org.springframework.validation.annotation.Validated; + +/** + * JPA implementation of {@link DistributionSetManagement}. + * + * @param the JPA entity type + * @param the type of the create request + * @param the type of the update request + * @param the type of the entity JPA repository + * @param RSQL query field enum + */ +// Spring AOP doesn't support bridge methods and the AspectJ advices as ExceptionMappingAspectHandler could not handle the +// thrown exception (e.g. to convert AuthorizationDeniedException to InsufficientPermissionException). +// That's why we explictly handle the insufficient permission exception with this @HandleAuthorizationDenied annotation. +@HandleAuthorizationDenied(handlerClass = JpaRepositoryConfiguration.ManagementExceptionThrowingMethodAuthorizationDeniedHandler.class) +@Transactional(readOnly = true) +@Validated +abstract class AbstractJpaRepositoryManagement, R extends BaseEntityRepository, A extends Enum & RsqlQueryField> + implements RepositoryManagement { + + public static final String DELETED = "deleted"; + + protected final R jpaRepository; + protected final EntityManager entityManager; + private final Constructor entityConstructor; + + protected AbstractJpaRepositoryManagement(final R jpaRepository, final EntityManager entityManager) { + this.jpaRepository = jpaRepository; + this.entityManager = entityManager; + try { + entityConstructor = jpaRepository.getDomainClass().getConstructor(); + // test if method works, if fine - it shall never fail when called later + entityConstructor.newInstance(); + } catch (final NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { + throw new IllegalStateException("JPA domain class " + jpaRepository.getDomainClass() + " shall have public no-args constructor", e); + } + } + + @Override + @Transactional + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) + public T create(final C create) { + return jpaRepository.save(AccessController.Operation.CREATE, jpaEntity(create)); + } + + @Override + @Transactional + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) + public List create(final Collection create) { + return jpaRepository.saveAll(AccessController.Operation.CREATE, create.stream().map(this::jpaEntity).toList()); + } + + @Override + public Optional get(final long id) { + return jpaRepository.findById(id); + } + + @Override + public List get(final Collection ids) { + return findAllById(ids); + } + + @Override + public boolean exists(final long id) { + return jpaRepository.existsById(id); + } + + @Override + public long count() { + return jpaRepository.count(isNotDeleted().orElse(null)); + } + + @Override + public long countByRsql(String rsql) { + return jpaRepository.count(JpaManagementHelper.combineWithAnd(rsqlSpec(rsql))); + } + + @Override + public Slice findAll(final Pageable pageable) { + return JpaManagementHelper.findAllWithoutCountBySpec( + jpaRepository, isNotDeleted().map(List::of).orElseGet(Collections::emptyList), pageable); + } + + @Override + public Page findByRsql(final String rsql, final Pageable pageable) { + return JpaManagementHelper.findAllWithCountBySpec(jpaRepository, rsqlSpec(rsql), pageable); + } + + @Override + @Transactional + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) + @SuppressWarnings("java:S1066") // javaS1066 - better readable that way + public T update(final U update) { + final T entity = jpaRepository + .findById(update.getId()) + .orElseThrow(() -> new EntityNotFoundException(managementClass(), update.getId())); + return update(update, entity); + } + + protected T update(final Identifiable update, final T entity) { + // update getId has not setter in target JPA entity but shall have getter and the value shall be the same + // otherwise the Utils will throw an exception that there is no counterpart setter for getId + if (ObjectCopyUtil.copy(update, entity, false, this::attach)) { + return jpaRepository.save(entity); + } else { // otherwise it is not changed, so return the same entity + return entity; + } + } + + @Override + @Transactional + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) + public void delete(final long id) { + delete0(List.of(id)); + } + + @Override + @Transactional + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) + public void delete(final Collection ids) { + delete0(ids); + } + + @NotNull + private List> rsqlSpec(final String rsql) { + return isNotDeleted() + .map(isNotDeleted -> List.of(RsqlUtility.getInstance(). buildRsqlSpecification(rsql, fieldsClass()), isNotDeleted)) + .orElseGet(() -> List.of(RsqlUtility.getInstance().buildRsqlSpecification(rsql, fieldsClass()))); + } + + // return which are for soft deletion + @SuppressWarnings("java:S1172") // java:S1172 - it is intended to be used by subclasses + protected Collection softDelete(final Collection toDelete) { + return Collections.emptyList(); + } + + protected void delete0(final Collection ids) { + if (ObjectUtils.isEmpty(ids)) { + return; + } + + final List toDelete = findAllById(ids); // throws EntityNotFoundException if any of these does not exist + jpaRepository.getAccessController().ifPresent(ac -> { + for (final T entity : toDelete) { + ac.assertOperationAllowed(AccessController.Operation.DELETE, entity); + } + }); + + // mark the rest as hard delete + final Collection toSoftDelete = softDelete(toDelete).stream().map(T::getId).toList(); + if (!toSoftDelete.isEmpty()) { + if (!supportSoftDelete()) { + throw new IllegalStateException("Soft delete is not supported for " + jpaRepository.getDomainClass().getSimpleName()); + } + + final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + final CriteriaUpdate update = cb.createCriteriaUpdate(jpaRepository.getDomainClass()); + final Root root = update.from(jpaRepository.getDomainClass()); + final CriteriaBuilder.In in = cb.in(root.get(AbstractJpaBaseEntity_.id)); + toSoftDelete.forEach(in::value); + update.set(root.get(DELETED), true).where(in); + entityManager.createQuery(update).executeUpdate(); + } + + final List toHardDelete = toDelete.stream() + .map(AbstractJpaBaseEntity::getId) + .filter(id -> !toSoftDelete.contains(id)) + .toList(); + // hard delete the rest if exists + if (!toHardDelete.isEmpty()) { + // don't give the delete statement an empty list, JPA/Oracle cannot + // handle the empty list + jpaRepository.deleteAllById(toHardDelete); + } + } + + private List findAllById(final Collection ids) { + final List foundDs = jpaRepository.findAllById(ids); + if (foundDs.size() != ids.size()) { + throw new EntityNotFoundException(managementClass(), ids, foundDs.stream().map(T::getId).toList()); + } + return foundDs; + } + + private final Supplier> managementClassSupplier = SingletonSupplier.of(this::managementClass0); + + private Class managementClass() { + return managementClassSupplier.get(); + } + + @SuppressWarnings("unchecked") + private Class managementClass0() { + return (Class) jpaRepository.getManagementClass(); + } + + private final Supplier> fieldsClassSupplier = SingletonSupplier.of(this::fieldsClass0); + + private Class fieldsClass() { + return fieldsClassSupplier.get(); + } + + @SuppressWarnings("unchecked") + private Class fieldsClass0() { + try { + return (Class) Class.forName("org.eclipse.hawkbit.repository." + managementClass().getSimpleName() + "Fields"); + } catch (ClassNotFoundException e) { + throw new IllegalStateException(e); + } + } + + private final Supplier supportSoftDeleteSupplier = SingletonSupplier.of(this::supportSoftDelete0); + + private boolean supportSoftDelete() { + return supportSoftDeleteSupplier.get(); + } + + private boolean supportSoftDelete0() { + return Stream.of(jpaRepository.getDomainClass().getDeclaredFields()).map(Field::getName).anyMatch(DELETED::equals); + } + + private final Supplier>> isNotDeletedSupplier = SingletonSupplier.of(this::isNotDeleted0); + + private Optional> isNotDeleted() { + return isNotDeletedSupplier.get(); + } + + private Optional> isNotDeleted0() { + return supportSoftDelete() + ? Optional.of((root, query, cb) -> cb.equal(root.get(DELETED), false)) + : Optional.empty(); + } + + private T jpaEntity(final Object create) { + final T jpaEntity; + try { + jpaEntity = entityConstructor.newInstance(); + } catch (final InstantiationException | IllegalAccessException | InvocationTargetException e) { + throw new IllegalStateException("Must NEVER happen!", e); + } + ObjectCopyUtil.copy(create, jpaEntity, false, this::attach); + return jpaEntity; + } + + private Object attach(final Object propertyValue) { + if (Jpa.JPA_VENDOR != Jpa.JpaVendor.HIBERNATE) { + return propertyValue; // no need to attach, only Hibernate supports this + } + + if (propertyValue instanceof List list) { + return list.stream().map(this::attach).toList(); + } else if (propertyValue instanceof Set set) { + return set.stream().map(this::attach).collect(Collectors.toSet()); + } else if (propertyValue instanceof Map map) { + return map.entrySet().stream().collect(Collectors.toMap( + entry -> attach(entry.getKey()), + entry -> attach(entry.getValue()))); + } else if (attachable(propertyValue)) { + // hibernate require detached entities to be attached before setting to jpa entity as a sub-property + return entityManager.merge(propertyValue); + } else { + return propertyValue; // no change + } + } + + private boolean attachable(final Object propertyValue) { + if (propertyValue == null) { + return false; + } + + final Class clazz = propertyValue.getClass(); + return !clazz.isPrimitive() && !clazz.isEnum() && + clazz != String.class && !Number.class.isAssignableFrom(clazz) && !Boolean.class.isAssignableFrom(clazz) && + !entityManager.contains(propertyValue); // no need to attach + } +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaActionManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaActionManagement.java index c697841ab..72436052b 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaActionManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaActionManagement.java @@ -47,7 +47,7 @@ public class JpaActionManagement { protected final QuotaManagement quotaManagement; protected final RepositoryProperties repositoryProperties; - public JpaActionManagement( + protected JpaActionManagement( final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository, final QuotaManagement quotaManagement, final RepositoryProperties repositoryProperties) { this.actionRepository = actionRepository; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaArtifactManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaArtifactManagement.java index 048e3263f..24e72ea09 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaArtifactManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaArtifactManagement.java @@ -51,11 +51,13 @@ import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.ArtifactUpload; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.tenancy.TenantAware; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; +import org.springframework.stereotype.Service; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -66,6 +68,8 @@ import org.springframework.validation.annotation.Validated; @Slf4j @Transactional(readOnly = true) @Validated +@Service +@ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "artifact-management" }, matchIfMissing = true) public class JpaArtifactManagement implements ArtifactManagement { private final EntityManager entityManager; @@ -77,7 +81,7 @@ public class JpaArtifactManagement implements ArtifactManagement { private final TenantAware tenantAware; private final QuotaManagement quotaManagement; - public JpaArtifactManagement( + protected JpaArtifactManagement( final EntityManager entityManager, final PlatformTransactionManager txManager, final LocalArtifactRepository localArtifactRepository, diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaConfirmationManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaConfirmationManagement.java index aa44fa4fc..4adc7b0e1 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaConfirmationManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaConfirmationManagement.java @@ -41,10 +41,11 @@ import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.AutoConfirmationStatus; -import org.eclipse.hawkbit.repository.model.Target; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; +import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; @@ -56,15 +57,15 @@ import org.springframework.validation.annotation.Validated; @Slf4j @Transactional(readOnly = true) @Validated +@Service +@ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "confirmation-management" }, matchIfMissing = true) public class JpaConfirmationManagement extends JpaActionManagement implements ConfirmationManagement { - public static final String CONFIRMATION_CODE_MSG_PREFIX = "Confirmation status code: %d"; - private final EntityManager entityManager; private final EntityFactory entityFactory; private final TargetRepository targetRepository; - public JpaConfirmationManagement( + protected JpaConfirmationManagement( final TargetRepository targetRepository, final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository, final RepositoryProperties repositoryProperties, final QuotaManagement quotaManagement, 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 517a1c1e0..364b82fb2 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 @@ -106,6 +106,7 @@ import org.eclipse.hawkbit.tenancy.configuration.ControllerPollProperties; import org.eclipse.hawkbit.tenancy.configuration.DurationHelper; import org.eclipse.hawkbit.tenancy.configuration.PollingTime; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -116,6 +117,7 @@ import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.repository.Modifying; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; +import org.springframework.stereotype.Service; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; @@ -124,12 +126,11 @@ import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import org.springframework.validation.annotation.Validated; -/** - * JPA based {@link ControllerManagement} implementation. - */ @Slf4j @Transactional(readOnly = true) @Validated +@Service +@ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "controller-management" }, matchIfMissing = true) public class JpaControllerManagement extends JpaActionManagement implements ControllerManagement { private static final Pattern PATTERN = Pattern.compile("[a-zA-Z0-9_\\-!@#$%^&*()+=\\[\\]{}|;:'\",.<>/\\\\?\\s]*"); @@ -143,10 +144,11 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont private final ConfirmationManagement confirmationManagement; private final SoftwareModuleRepository softwareModuleRepository; private final SoftwareModuleMetadataRepository softwareModuleMetadataRepository; - private final DistributionSetManagement distributionSetManagement; + private final DistributionSetManagement distributionSetManagement; private final TenantConfigurationManagement tenantConfigurationManagement; private final ControllerPollProperties controllerPollProperties; - private final Duration minPollingTime, maxPollingTime; + private final Duration minPollingTime; + private final Duration maxPollingTime; private final PlatformTransactionManager txManager; private final EntityFactory entityFactory; private final EntityManager entityManager; @@ -155,13 +157,13 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont private final TenantAware tenantAware; @SuppressWarnings("squid:S00107") - public JpaControllerManagement( + protected JpaControllerManagement( final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository, final QuotaManagement quotaManagement, final RepositoryProperties repositoryProperties, final TargetRepository targetRepository, final TargetTypeManagement targetTypeManagement, final DeploymentManagement deploymentManagement, final ConfirmationManagement confirmationManagement, final SoftwareModuleRepository softwareModuleRepository, final SoftwareModuleMetadataRepository softwareModuleMetadataRepository, - final DistributionSetManagement distributionSetManagement, + final DistributionSetManagement distributionSetManagement, final TenantConfigurationManagement tenantConfigurationManagement, final ControllerPollProperties controllerPollProperties, final PlatformTransactionManager txManager, final EntityFactory entityFactory, final EntityManager entityManager, final AfterTransactionCommitExecutor afterCommit, diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java index 4bf2c8054..6267c0101 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java @@ -39,7 +39,6 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.ListUtils; import org.eclipse.hawkbit.repository.ActionFields; import org.eclipse.hawkbit.repository.DeploymentManagement; -import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.RepositoryConstants; import org.eclipse.hawkbit.repository.RepositoryProperties; @@ -89,6 +88,8 @@ import org.eclipse.hawkbit.repository.model.TargetWithActionType; import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.tenancy.TenantAware; import org.eclipse.hawkbit.utils.TenantConfigHelper; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; +import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.data.domain.AuditorAware; import org.springframework.data.domain.Page; @@ -104,17 +105,17 @@ import org.springframework.retry.annotation.Retryable; import org.springframework.retry.backoff.FixedBackOffPolicy; import org.springframework.retry.policy.SimpleRetryPolicy; import org.springframework.retry.support.RetryTemplate; +import org.springframework.stereotype.Service; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; -/** - * JPA implementation for {@link DeploymentManagement}. - */ @Slf4j @Transactional(readOnly = true) @Validated +@Service +@ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "deployment-management" }, matchIfMissing = true) public class JpaDeploymentManagement extends JpaActionManagement implements DeploymentManagement { /** @@ -146,7 +147,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl } private final EntityManager entityManager; - private final DistributionSetManagement distributionSetManagement; + private final JpaDistributionSetManagement distributionSetManagement; private final TargetRepository targetRepository; private final AuditorAware auditorProvider; private final PlatformTransactionManager txManager; @@ -160,14 +161,14 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl private final RetryTemplate retryTemplate; @SuppressWarnings("java:S107") - public JpaDeploymentManagement( + protected JpaDeploymentManagement( final EntityManager entityManager, final ActionRepository actionRepository, - final DistributionSetManagement distributionSetManagement, final TargetRepository targetRepository, + final JpaDistributionSetManagement distributionSetManagement, final TargetRepository targetRepository, final ActionStatusRepository actionStatusRepository, final AuditorAware auditorProvider, final AfterTransactionCommitExecutor afterCommit, final PlatformTransactionManager txManager, final TenantConfigurationManagement tenantConfigurationManagement, final QuotaManagement quotaManagement, final SystemSecurityContext systemSecurityContext, final TenantAware tenantAware, final AuditorAware auditorAware, - final Database database, final RepositoryProperties repositoryProperties) { + final JpaProperties jpaProperties, final RepositoryProperties repositoryProperties) { super(actionRepository, actionStatusRepository, quotaManagement, repositoryProperties); this.entityManager = entityManager; this.distributionSetManagement = distributionSetManagement; @@ -184,7 +185,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl this.systemSecurityContext = systemSecurityContext; this.tenantAware = tenantAware; this.auditorAware = auditorAware; - this.database = database; + this.database = jpaProperties.getDatabase(); this.retryTemplate = createRetryTemplate(); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetInvalidationManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetInvalidationManagement.java index 5b92da01c..ba2e76696 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetInvalidationManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetInvalidationManagement.java @@ -31,16 +31,20 @@ import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation.Cancelat import org.eclipse.hawkbit.repository.model.DistributionSetInvalidationCount; import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.tenancy.TenantAware; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.integration.support.locks.LockRegistry; +import org.springframework.stereotype.Service; import org.springframework.transaction.PlatformTransactionManager; /** * Jpa implementation for {@link DistributionSetInvalidationManagement} */ @Slf4j +@Service +@ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "distribution-set-invalidation-management" }, matchIfMissing = true) public class JpaDistributionSetInvalidationManagement implements DistributionSetInvalidationManagement { - private final DistributionSetManagement distributionSetManagement; + private final DistributionSetManagement distributionSetManagement; private final RolloutManagement rolloutManagement; private final DeploymentManagement deploymentManagement; private final TargetFilterQueryManagement targetFilterQueryManagement; @@ -52,7 +56,7 @@ public class JpaDistributionSetInvalidationManagement implements DistributionSet private final SystemSecurityContext systemSecurityContext; @SuppressWarnings("java:S107") - public JpaDistributionSetInvalidationManagement(final DistributionSetManagement distributionSetManagement, + protected JpaDistributionSetInvalidationManagement(final DistributionSetManagement distributionSetManagement, final RolloutManagement rolloutManagement, final DeploymentManagement deploymentManagement, final TargetFilterQueryManagement targetFilterQueryManagement, final ActionRepository actionRepository, final PlatformTransactionManager txManager, final RepositoryProperties repositoryProperties, @@ -134,7 +138,7 @@ public class JpaDistributionSetInvalidationManagement implements DistributionSet throw new IncompleteDistributionSetException("Distribution set of type " + distributionSet.getType().getKey() + " is incomplete: " + distributionSet.getId()); } - distributionSetManagement.invalidate(distributionSet); + ((DistributionSetManagement)distributionSetManagement).invalidate(distributionSet); log.debug("Distribution set {} marked as invalid.", setId); // rollout cancellation should only be permitted with UPDATE_ROLLOUT permission diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetManagement.java index 8dd1a4fd1..4226a1e81 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetManagement.java @@ -9,11 +9,14 @@ */ package org.eclipse.hawkbit.repository.jpa.management; +import static org.eclipse.hawkbit.repository.jpa.configuration.Constants.TX_RT_DELAY; +import static org.eclipse.hawkbit.repository.jpa.configuration.Constants.TX_RT_MAX; import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.IMPLICIT_LOCK_ENABLED; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -37,10 +40,7 @@ import org.eclipse.hawkbit.repository.DistributionSetTagManagement; import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.RepositoryProperties; -import org.eclipse.hawkbit.repository.SystemManagement; -import org.eclipse.hawkbit.repository.builder.DistributionSetCreate; -import org.eclipse.hawkbit.repository.builder.DistributionSetUpdate; -import org.eclipse.hawkbit.repository.builder.GenericDistributionSetUpdate; +import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.exception.DeletedException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; @@ -49,11 +49,10 @@ import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetExcepti import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException; import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper; -import org.eclipse.hawkbit.repository.jpa.acm.AccessController; -import org.eclipse.hawkbit.repository.jpa.builder.JpaDistributionSetCreate; -import org.eclipse.hawkbit.repository.jpa.configuration.Constants; import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; +import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag; +import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository; @@ -73,7 +72,9 @@ import org.eclipse.hawkbit.repository.model.DistributionSetTag; import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.Statistic; +import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.utils.TenantConfigHelper; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -81,229 +82,120 @@ import org.springframework.data.domain.Slice; import org.springframework.data.jpa.domain.Specification; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; +import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; -import org.springframework.validation.annotation.Validated; -/** - * JPA implementation of {@link DistributionSetManagement}. - */ -@Transactional(readOnly = true) -@Validated -public class JpaDistributionSetManagement implements DistributionSetManagement { +@Service +@ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "distribution-set-management" }, matchIfMissing = true) +public class JpaDistributionSetManagement + extends AbstractJpaRepositoryManagement + implements DistributionSetManagement { - private final EntityManager entityManager; - private final DistributionSetRepository distributionSetRepository; - private final DistributionSetTagManagement distributionSetTagManagement; - private final SystemManagement systemManagement; - private final DistributionSetTypeManagement distributionSetTypeManagement; - private final QuotaManagement quotaManagement; + private final DistributionSetTagManagement distributionSetTagManagement; + private final DistributionSetTypeManagement distributionSetTypeManagement; + private final SoftwareModuleRepository softwareModuleRepository; + private final DistributionSetTagRepository distributionSetTagRepository; private final TargetRepository targetRepository; private final TargetFilterQueryRepository targetFilterQueryRepository; private final ActionRepository actionRepository; + private final QuotaManagement quotaManagement; private final TenantConfigHelper tenantConfigHelper; - private final SoftwareModuleRepository softwareModuleRepository; - private final DistributionSetTagRepository distributionSetTagRepository; private final RepositoryProperties repositoryProperties; @SuppressWarnings("java:S107") - public JpaDistributionSetManagement( + protected JpaDistributionSetManagement( + final DistributionSetRepository jpaRepository, final EntityManager entityManager, - final DistributionSetRepository distributionSetRepository, - final DistributionSetTagManagement distributionSetTagManagement, final SystemManagement systemManagement, - final DistributionSetTypeManagement distributionSetTypeManagement, final QuotaManagement quotaManagement, - final TargetRepository targetRepository, - final TargetFilterQueryRepository targetFilterQueryRepository, final ActionRepository actionRepository, - final TenantConfigHelper tenantConfigHelper, + final DistributionSetTagManagement distributionSetTagManagement, + final DistributionSetTypeManagement distributionSetTypeManagement, final SoftwareModuleRepository softwareModuleRepository, final DistributionSetTagRepository distributionSetTagRepository, + final TargetRepository targetRepository, + final TargetFilterQueryRepository targetFilterQueryRepository, + final ActionRepository actionRepository, + final QuotaManagement quotaManagement, + final SystemSecurityContext systemSecurityContext, + final TenantConfigurationManagement tenantConfigurationManagement, final RepositoryProperties repositoryProperties) { - this.entityManager = entityManager; - this.distributionSetRepository = distributionSetRepository; + super(jpaRepository, entityManager); this.distributionSetTagManagement = distributionSetTagManagement; - this.systemManagement = systemManagement; this.distributionSetTypeManagement = distributionSetTypeManagement; - this.quotaManagement = quotaManagement; + this.softwareModuleRepository = softwareModuleRepository; + this.distributionSetTagRepository = distributionSetTagRepository; this.targetRepository = targetRepository; this.targetFilterQueryRepository = targetFilterQueryRepository; this.actionRepository = actionRepository; - this.tenantConfigHelper = tenantConfigHelper; - this.softwareModuleRepository = softwareModuleRepository; - this.distributionSetTagRepository = distributionSetTagRepository; + this.quotaManagement = quotaManagement; + this.tenantConfigHelper = TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement); this.repositoryProperties = repositoryProperties; } @Override - @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public List create(final Collection creates) { - final List toCreate = creates.stream().map(JpaDistributionSetCreate.class::cast) - .map(this::setDefaultTypeIfMissing) - .map(JpaDistributionSetCreate::build) - .toList(); - return Collections.unmodifiableList(distributionSetRepository.saveAll(AccessController.Operation.CREATE, toCreate)); - } - - @Override - @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public DistributionSet create(final DistributionSetCreate c) { - final JpaDistributionSetCreate create = (JpaDistributionSetCreate) c; - setDefaultTypeIfMissing(create); - return distributionSetRepository.save(AccessController.Operation.CREATE, create.build()); - } - - @Override - @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - @SuppressWarnings("java:S1066") // javaS1066 - better readable that way - public DistributionSet update(final DistributionSetUpdate u) { - final GenericDistributionSetUpdate update = (GenericDistributionSetUpdate) u; - - final JpaDistributionSet set = (JpaDistributionSet) getValid(update.getId()); - - update.getName().ifPresent(set::setName); - update.getDescription().ifPresent(set::setDescription); - update.getVersion().ifPresent(set::setVersion); + public JpaDistributionSet update(final Update update) { + final JpaDistributionSet distributionSet = getValid0(update.getId()); // lock/unlock ONLY if locked flag is present! - if (Boolean.TRUE.equals(update.locked())) { - if (!set.isLocked()) { - lockSoftwareModules(set); - set.lock(); + if (Boolean.TRUE.equals(update.getLocked())) { + if (!distributionSet.isLocked()) { + lockSoftwareModules(distributionSet); + distributionSet.lock(); } - } else if (Boolean.FALSE.equals(update.locked())) { - if (set.isLocked()) { - set.unlock(); + } else if (Boolean.FALSE.equals(update.getLocked())) { + if (distributionSet.isLocked()) { + distributionSet.unlock(); } } - if (update.isRequiredMigrationStep() != null - && !update.isRequiredMigrationStep().equals(set.isRequiredMigrationStep())) { + if (update.getRequiredMigrationStep() != null && !update.getRequiredMigrationStep().equals(distributionSet.isRequiredMigrationStep())) { assertDistributionSetIsNotAssignedToTargets(update.getId()); - set.setRequiredMigrationStep(update.isRequiredMigrationStep()); } - return distributionSetRepository.save(set); + return super.update(update, distributionSet); } @Override - @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public void delete(final long id) { - delete0(List.of(id)); - } - - @Override - @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public void delete(final Collection distributionSetIDs) { - delete0(distributionSetIDs); - } - private void delete0(final Collection distributionSetIDs) { - getDistributionSets(distributionSetIDs); // throws EntityNotFoundException if any of these do not exists - final List setsFound = distributionSetRepository.findAll( - AccessController.Operation.DELETE, distributionSetRepository.byIdsSpec(distributionSetIDs)); - if (setsFound.size() < distributionSetIDs.size()) { - throw new InsufficientPermissionException("No DELETE access to some of distribution sets!"); - } - - final List assigned = distributionSetRepository - .findAssignedToTargetDistributionSetsById(distributionSetIDs); - assigned.addAll(distributionSetRepository.findAssignedToRolloutDistributionSetsById(distributionSetIDs)); - + protected Collection softDelete(final Collection toDelete) { // soft delete assigned - if (!assigned.isEmpty()) { - distributionSetRepository.saveAll( - setsFound.stream() - .filter(set -> assigned.contains(set.getId())) - .map(toSoftDelete -> { - // don't use peek since it is by documentation mainly for debugging and could be skipped in some cases - toSoftDelete.setDeleted(true); - return toSoftDelete; - }) - .toList()); - targetFilterQueryRepository.unsetAutoAssignDistributionSetAndActionTypeAndAccessContext(assigned.toArray(new Long[0])); + final List ids = toDelete.stream().map(JpaDistributionSet::getId).toList(); + final Set assigned = new HashSet<>(jpaRepository.findAssignedToTargetDistributionSetsById(ids)); + assigned.addAll(jpaRepository.findAssignedToRolloutDistributionSetsById(ids)); + return toDelete.stream().filter(distributionSet -> assigned.contains(distributionSet.getId())).toList(); + } + + protected void delete0(final Collection distributionSetIDs) { + if (ObjectUtils.isEmpty(distributionSetIDs)) { + return; // super checks but if empty we don't want to unassign from target filters } - // mark the rest as hard delete - final List toHardDelete = distributionSetIDs.stream().filter(setId -> !assigned.contains(setId)).toList(); - - // hard delete the rest if exists - if (!toHardDelete.isEmpty()) { - targetFilterQueryRepository.unsetAutoAssignDistributionSetAndActionTypeAndAccessContext( - toHardDelete.toArray(new Long[0])); - // don't give the delete statement an empty list, JPA/Oracle cannot - // handle the empty list - distributionSetRepository.deleteAllById(toHardDelete); - } + // if delete fail (because of permission denied) transaction will be rolled back + targetFilterQueryRepository.unsetAutoAssignDistributionSetAndActionTypeAndAccessContext(distributionSetIDs.toArray(new Long[0])); + super.delete0(distributionSetIDs); } @Override - public Optional get(final long id) { - return distributionSetRepository.findById(id).map(DistributionSet.class::cast); - } - - @Override - public List get(final Collection ids) { - return Collections.unmodifiableList(getDistributionSets(ids)); - } - - @Override - public boolean exists(final long id) { - return distributionSetRepository.existsById(id); - } - - @Override - public long count() { - return distributionSetRepository.count(DistributionSetSpecification.isNotDeleted()); - } - - @Override - public Slice findAll(final Pageable pageable) { - return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetRepository, List.of( - DistributionSetSpecification.isNotDeleted()), pageable); - } - - @Override - public Page findByRsql(final String rsql, final Pageable pageable) { - return JpaManagementHelper.findAllWithCountBySpec(distributionSetRepository, List.of( - RsqlUtility.getInstance().buildRsqlSpecification(rsql, DistributionSetFields.class), - DistributionSetSpecification.isNotDeleted()), pageable); - } - - @Override - public Optional getWithDetails(final long id) { - return distributionSetRepository - .findOne(distributionSetRepository.byIdSpec(id), JpaDistributionSet_.GRAPH_DISTRIBUTION_SET_DETAIL) - .map(DistributionSet.class::cast); + public Optional getWithDetails(final long id) { + return jpaRepository.findOne(jpaRepository.byIdSpec(id), JpaDistributionSet_.GRAPH_DISTRIBUTION_SET_DETAIL); } @Override @Transactional - public void invalidate(final DistributionSet distributionSet) { - final JpaDistributionSet jpaSet = (JpaDistributionSet) distributionSet; - jpaSet.invalidate(); - distributionSetRepository.save(jpaSet); + public void invalidate(final JpaDistributionSet distributionSet) { + distributionSet.invalidate(); + jpaRepository.save(distributionSet); } @Override - public DistributionSet getOrElseThrowException(final long id) { + public JpaDistributionSet getOrElseThrowException(final long id) { return getById(id); } @Override @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public DistributionSet assignSoftwareModules(final long id, final Collection softwareModuleId) { - final JpaDistributionSet set = (JpaDistributionSet) getValid(id); + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) + public JpaDistributionSet assignSoftwareModules(final long id, final Collection softwareModuleId) { + final JpaDistributionSet set = getValid0(id); assertDistributionSetIsNotAssignedToTargets(id); assertSoftwareModuleQuota(id, softwareModuleId.size()); @@ -315,47 +207,44 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { modules.forEach(set::addModule); - return distributionSetRepository.save(set); + return jpaRepository.save(set); } @Override @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public DistributionSet unassignSoftwareModule(final long id, final long moduleId) { - final JpaDistributionSet set = (JpaDistributionSet) getValid(id); + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) + public JpaDistributionSet unassignSoftwareModule(final long id, final long moduleId) { + final JpaDistributionSet set = getValid0(id); assertDistributionSetIsNotAssignedToTargets(id); final JpaSoftwareModule module = findSoftwareModuleAndThrowExceptionIfNotFound(moduleId); set.removeModule(module); - return distributionSetRepository.save(set); + return jpaRepository.save(set); } @Override @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public List assignTag(final Collection ids, final long dsTagId) { + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) + public List assignTag(final Collection ids, final long dsTagId) { return updateTag(ids, dsTagId, (tag, distributionSet) -> { if (distributionSet.getTags().contains(tag)) { return distributionSet; } else { distributionSet.addTag(tag); - return distributionSetRepository.save(distributionSet); + return jpaRepository.save(distributionSet); } }); } @Override @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public List unassignTag(final Collection ids, final long dsTagId) { + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) + public List unassignTag(final Collection ids, final long dsTagId) { return updateTag(ids, dsTagId, (tag, distributionSet) -> { if (distributionSet.getTags().contains(tag)) { distributionSet.removeTag(tag); - return distributionSetRepository.save(distributionSet); + return jpaRepository.save(distributionSet); } else { return distributionSet; } @@ -364,10 +253,9 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { @Override @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) public void createMetadata(final long id, final Map md) { - final JpaDistributionSet distributionSet = (JpaDistributionSet) getValid(id); + final JpaDistributionSet distributionSet = getValid0(id); // get the modifiable metadata map final Map metadata = distributionSet.getMetadata(); @@ -380,7 +268,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { assertMetaDataQuota(id, metadata.size()); - distributionSetRepository.save(distributionSet); + jpaRepository.save(distributionSet); } @Override @@ -391,10 +279,9 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { @Override @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) public void updateMetadata(final long id, final String key, final String value) { - final JpaDistributionSet distributionSet = (JpaDistributionSet) getValid(id); + final JpaDistributionSet distributionSet = getValid0(id); // get the modifiable metadata map final Map metadata = distributionSet.getMetadata(); @@ -403,15 +290,14 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } metadata.put(key, value); - distributionSetRepository.save(distributionSet); + jpaRepository.save(distributionSet); } @Override @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) public void deleteMetadata(final long id, final String key) { - final JpaDistributionSet distributionSet = (JpaDistributionSet) getValid(id); + final JpaDistributionSet distributionSet = getValid0(id); // get the modifiable metadata map final Map metadata = distributionSet.getMetadata(); @@ -419,68 +305,62 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { throw new EntityNotFoundException("DistributionSet metadata", id + ":" + key); } - distributionSetRepository.save(distributionSet); + jpaRepository.save(distributionSet); } @Override @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) public void lock(final long id) { final JpaDistributionSet distributionSet = getById(id); if (!distributionSet.isLocked()) { lockSoftwareModules(distributionSet); distributionSet.lock(); - distributionSetRepository.save(distributionSet); + jpaRepository.save(distributionSet); } } @Override @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) public void unlock(final long id) { final JpaDistributionSet distributionSet = getById(id); if (distributionSet.isLocked()) { distributionSet.unlock(); - distributionSetRepository.save(distributionSet); + jpaRepository.save(distributionSet); } } @Override - public Optional findByAction(final long actionId) { + public Optional findByAction(final long actionId) { return actionRepository .findById(actionId) .map(action -> { if (!targetRepository.exists(TargetSpecifications.hasId(action.getTarget().getId()))) { throw new InsufficientPermissionException("Target not accessible (or not found)!"); } - return distributionSetRepository + return jpaRepository .findOne(DistributionSetSpecification.byIdFetch(action.getDistributionSet().getId())) .orElseThrow(() -> new InsufficientPermissionException("DistributionSet not accessible (or not found)!")); }) - .map(DistributionSet.class::cast) .or(() -> { throw new EntityNotFoundException(Action.class, actionId); }); } @Override - public Optional findByNameAndVersion(final String distributionName, final String version) { - return distributionSetRepository - .findOne(DistributionSetSpecification.equalsNameAndVersionIgnoreCase(distributionName, version)) - .map(DistributionSet.class::cast); - + public Optional findByNameAndVersion(final String distributionName, final String version) { + return jpaRepository.findOne(DistributionSetSpecification.equalsNameAndVersionIgnoreCase(distributionName, version)); } @Override - public DistributionSet getValidAndComplete(final long id) { - final DistributionSet distributionSet = getValid(id); + public JpaDistributionSet getValidAndComplete(final long id) { + final JpaDistributionSet distributionSet = getValid0(id); if (!distributionSet.isComplete()) { - throw new IncompleteDistributionSetException("Distribution set of type " - + distributionSet.getType().getKey() + " is incomplete: " + distributionSet.getId()); + throw new IncompleteDistributionSetException( + "Distribution set of type " + distributionSet.getType().getKey() + " is incomplete: " + distributionSet.getId()); } if (distributionSet.isDeleted()) { @@ -491,60 +371,49 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } @Override - public DistributionSet getValid(final long id) { - final DistributionSet distributionSet = getOrElseThrowException(id); - - if (!distributionSet.isValid()) { - throw new InvalidDistributionSetException("Distribution set of type " + distributionSet.getType().getKey() - + " is invalid: " + distributionSet.getId()); - } - - return distributionSet; + public JpaDistributionSet getValid(final long id) { + return getValid0(id); } @Override - public Slice findByCompleted(final Boolean complete, final Pageable pageReq) { + public Slice findByCompleted(final Boolean complete, final Pageable pageReq) { final List> specifications = buildSpecsByComplete(complete); - return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetRepository, specifications, pageReq); + return JpaManagementHelper.findAllWithoutCountBySpec(jpaRepository, specifications, pageReq); } @Override public long countByCompleted(final Boolean complete) { - final List> specifications = buildSpecsByComplete(complete); - - return JpaManagementHelper.countBySpec(distributionSetRepository, specifications); + return JpaManagementHelper.countBySpec(jpaRepository, buildSpecsByComplete(complete)); } @Override - public Slice findByDistributionSetFilter(final DistributionSetFilter distributionSetFilter, final Pageable pageable) { - final List> specList = buildDistributionSetSpecifications( - distributionSetFilter); - - return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetRepository, specList, pageable); + public Slice findByDistributionSetFilter(final DistributionSetFilter distributionSetFilter, final Pageable pageable) { + final List> specList = buildDistributionSetSpecifications(distributionSetFilter); + return JpaManagementHelper.findAllWithoutCountBySpec(jpaRepository, specList, pageable); } @Override public long countByDistributionSetFilter(@NotNull final DistributionSetFilter distributionSetFilter) { final List> specList = buildDistributionSetSpecifications(distributionSetFilter); - return JpaManagementHelper.countBySpec(distributionSetRepository, specList); + return JpaManagementHelper.countBySpec(jpaRepository, specList); } @Override - public Page findByTag(final long tagId, final Pageable pageable) { + public Page findByTag(final long tagId, final Pageable pageable) { assertDsTagExists(tagId); - - return JpaManagementHelper.findAllWithCountBySpec(distributionSetRepository, List.of( - DistributionSetSpecification.hasTag(tagId)), pageable); + return JpaManagementHelper.findAllWithCountBySpec(jpaRepository, List.of(DistributionSetSpecification.hasTag(tagId)), pageable); } @Override - public Page findByRsqlAndTag(final String rsql, final long tagId, final Pageable pageable) { + public Page findByRsqlAndTag(final String rsql, final long tagId, final Pageable pageable) { assertDsTagExists(tagId); - - return JpaManagementHelper.findAllWithCountBySpec(distributionSetRepository, List.of( - RsqlUtility.getInstance().buildRsqlSpecification(rsql, DistributionSetFields.class), - DistributionSetSpecification.hasTag(tagId), DistributionSetSpecification.isNotDeleted()), pageable); + return JpaManagementHelper.findAllWithCountBySpec( + jpaRepository, + List.of( + RsqlUtility.getInstance().buildRsqlSpecification(rsql, DistributionSetFields.class), + DistributionSetSpecification.hasTag(tagId), DistributionSetSpecification.isNotDeleted()), + pageable); } @Override @@ -552,37 +421,31 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { if (!distributionSetTypeManagement.exists(typeId)) { throw new EntityNotFoundException(DistributionSetType.class, typeId); } - - return distributionSetRepository.count(DistributionSetSpecification.byType(typeId)); + return jpaRepository.count(DistributionSetSpecification.byType(typeId)); } @Override public boolean isInUse(final long id) { assertDistributionSetExists(id); - return actionRepository.countByDistributionSetId(id) > 0; } @Override public List countRolloutsByStatusForDistributionSet(final Long id) { assertDistributionSetExists(id); - - return distributionSetRepository.countRolloutsByStatusForDistributionSet(id).stream().map(Statistic.class::cast).toList(); + return jpaRepository.countRolloutsByStatusForDistributionSet(id).stream().map(Statistic.class::cast).toList(); } @Override public List countActionsByStatusForDistributionSet(final Long id) { assertDistributionSetExists(id); - - return distributionSetRepository.countActionsByStatusForDistributionSet(id).stream() - .map(Statistic.class::cast).toList(); + return jpaRepository.countActionsByStatusForDistributionSet(id).stream().map(Statistic.class::cast).toList(); } @Override public Long countAutoAssignmentsForDistributionSet(final Long id) { assertDistributionSetExists(id); - - return distributionSetRepository.countAutoAssignmentsForDistributionSet(id); + return jpaRepository.countAutoAssignmentsForDistributionSet(id); } // check if it shall implicitly lock a distribution set @@ -619,40 +482,26 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { final DistributionSetFilter distributionSetFilter) { final List> specList = new ArrayList<>(10); - Specification spec; - if (distributionSetFilter.getIsComplete() != null) { - spec = DistributionSetSpecification.isCompleted(distributionSetFilter.getIsComplete()); - specList.add(spec); + specList.add(DistributionSetSpecification.isCompleted(distributionSetFilter.getIsComplete())); } - if (distributionSetFilter.getIsDeleted() != null) { - spec = DistributionSetSpecification.isDeleted(distributionSetFilter.getIsDeleted()); - specList.add(spec); + specList.add(DistributionSetSpecification.isDeleted(distributionSetFilter.getIsDeleted())); } - if (distributionSetFilter.getIsValid() != null) { - spec = DistributionSetSpecification.isValid(distributionSetFilter.getIsValid()); - specList.add(spec); + specList.add(DistributionSetSpecification.isValid(distributionSetFilter.getIsValid())); } - if (distributionSetFilter.getTypeId() != null) { - spec = DistributionSetSpecification.byType(distributionSetFilter.getTypeId()); - specList.add(spec); + specList.add(DistributionSetSpecification.byType(distributionSetFilter.getTypeId())); } - if (!ObjectUtils.isEmpty(distributionSetFilter.getSearchText())) { final String[] dsFilterNameAndVersionEntries = JpaManagementHelper .getFilterNameAndVersionEntries(distributionSetFilter.getSearchText().trim()); - spec = DistributionSetSpecification.likeNameAndVersion(dsFilterNameAndVersionEntries[0], - dsFilterNameAndVersionEntries[1]); - specList.add(spec); + specList.add(DistributionSetSpecification.likeNameAndVersion(dsFilterNameAndVersionEntries[0], dsFilterNameAndVersionEntries[1])); } - if (hasTagsFilterActive(distributionSetFilter)) { - spec = DistributionSetSpecification.hasTags(distributionSetFilter.getTagNames(), - distributionSetFilter.getSelectDSWithNoTag()); - specList.add(spec); + specList.add(DistributionSetSpecification.hasTags( + distributionSetFilter.getTagNames(), distributionSetFilter.getSelectDSWithNoTag())); } return specList; } @@ -660,7 +509,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { private static boolean hasTagsFilterActive(final DistributionSetFilter distributionSetFilter) { final boolean isNoTagActive = Boolean.TRUE.equals(distributionSetFilter.getSelectDSWithNoTag()); final boolean isAtLeastOneTagActive = !CollectionUtils.isEmpty(distributionSetFilter.getTagNames()); - return isNoTagActive || isAtLeastOneTagActive; } @@ -670,16 +518,25 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { return distributionSetIds.stream().filter(id -> !foundDistributionSetMap.containsKey(id)).toList(); } - private List updateTag( + private JpaDistributionSet getValid0(final long id) { + final JpaDistributionSet distributionSet = getById(id); + if (!distributionSet.isValid()) { + throw new InvalidDistributionSetException( + "Distribution set of type " + distributionSet.getType().getKey() + " is invalid: " + distributionSet.getId()); + } + return distributionSet; + } + + private List updateTag( final Collection dsIds, final long dsTagId, - final BiFunction updater) { + final BiFunction updater) { final DistributionSetTag tag = distributionSetTagManagement.get(dsTagId) .orElseThrow(() -> new EntityNotFoundException(DistributionSetTag.class, dsTagId)); final List allDs = dsIds.size() == 1 ? - distributionSetRepository.findById(dsIds.iterator().next()) + jpaRepository.findById(dsIds.iterator().next()) .map(List::of) .orElseGet(Collections::emptyList) : - distributionSetRepository.findAll(DistributionSetSpecification.byIdsFetch(dsIds)); + jpaRepository.findAll(DistributionSetSpecification.byIdsFetch(dsIds)); if (allDs.size() < dsIds.size()) { throw new EntityNotFoundException(DistributionSet.class, notFound(dsIds, allDs)); } @@ -716,13 +573,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { .orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, softwareModuleId)); } - private JpaDistributionSetCreate setDefaultTypeIfMissing(final JpaDistributionSetCreate create) { - if (create.getType() == null) { - create.type(systemManagement.getTenantMetadata().getDefaultDsType().getKey()); - } - return create; - } - private List> buildSpecsByComplete(final Boolean complete) { final List> specifications = new ArrayList<>(); specifications.add(DistributionSetSpecification.isNotDeleted()); @@ -749,15 +599,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } } - private List getDistributionSets(final Collection ids) { - final List foundDs = distributionSetRepository.findAllById(ids); - if (foundDs.size() != ids.size()) { - throw new EntityNotFoundException( - DistributionSet.class, ids, foundDs.stream().map(JpaDistributionSet::getId).toList()); - } - return foundDs; - } - private void lockSoftwareModules(final JpaDistributionSet distributionSet) { distributionSet.getModules().forEach(module -> { if (!module.isLocked()) { @@ -769,13 +610,13 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } private JpaDistributionSet getById(final long id) { - return distributionSetRepository + return jpaRepository .findById(id) .orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, id)); } private void assertDistributionSetExists(final long id) { - if (!distributionSetRepository.existsById(id)) { + if (!jpaRepository.existsById(id)) { throw new EntityNotFoundException(DistributionSet.class, id); } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetTagManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetTagManagement.java index c3533812c..a5709c34e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetTagManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetTagManagement.java @@ -9,173 +9,73 @@ */ package org.eclipse.hawkbit.repository.jpa.management; -import java.util.Collection; +import static org.eclipse.hawkbit.repository.jpa.configuration.Constants.TX_RT_DELAY; +import static org.eclipse.hawkbit.repository.jpa.configuration.Constants.TX_RT_MAX; + import java.util.Collections; -import java.util.List; import java.util.Optional; +import jakarta.persistence.EntityManager; + import org.eclipse.hawkbit.repository.DistributionSetTagFields; import org.eclipse.hawkbit.repository.DistributionSetTagManagement; -import org.eclipse.hawkbit.repository.TargetTagManagement; -import org.eclipse.hawkbit.repository.builder.GenericTagUpdate; -import org.eclipse.hawkbit.repository.builder.TagCreate; -import org.eclipse.hawkbit.repository.builder.TagUpdate; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper; -import org.eclipse.hawkbit.repository.jpa.acm.AccessController; -import org.eclipse.hawkbit.repository.jpa.builder.JpaTagCreate; -import org.eclipse.hawkbit.repository.jpa.configuration.Constants; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag; import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetRepository; import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetTagRepository; -import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility; import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetTagSpecifications; import org.eclipse.hawkbit.repository.jpa.specifications.TagSpecification; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetTag; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Slice; -import org.springframework.data.jpa.domain.Specification; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; +import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.annotation.Validated; -/** - * JPA implementation of {@link TargetTagManagement}. - */ -@Transactional(readOnly = true) -@Validated -public class JpaDistributionSetTagManagement implements DistributionSetTagManagement { +@Service +@ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "distribution-set-tag-management" }, matchIfMissing = true) +public class JpaDistributionSetTagManagement + extends AbstractJpaRepositoryManagement + implements DistributionSetTagManagement { - private final DistributionSetTagRepository distributionSetTagRepository; private final DistributionSetRepository distributionSetRepository; - public JpaDistributionSetTagManagement( + protected JpaDistributionSetTagManagement( final DistributionSetTagRepository distributionSetTagRepository, + final EntityManager entityManager, final DistributionSetRepository distributionSetRepository) { - this.distributionSetTagRepository = distributionSetTagRepository; + super(distributionSetTagRepository, entityManager); this.distributionSetRepository = distributionSetRepository; } @Override - @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public List create(final Collection dst) { - final List toCreate = dst.stream() - .map(JpaTagCreate.class::cast) - .map(JpaTagCreate::buildDistributionSetTag) - .toList(); - return Collections.unmodifiableList(distributionSetTagRepository.saveAll(AccessController.Operation.CREATE, toCreate)); + public Optional findByName(final String name) { + return jpaRepository.findByNameEquals(name); } @Override - @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public DistributionSetTag create(final TagCreate c) { - return distributionSetTagRepository.save(AccessController.Operation.CREATE, ((JpaTagCreate) c).buildDistributionSetTag()); - } - - @Override - @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public DistributionSetTag update(final TagUpdate u) { - final GenericTagUpdate update = (GenericTagUpdate) u; - final JpaDistributionSetTag tag = distributionSetTagRepository.findById(update.getId()) - .orElseThrow(() -> new EntityNotFoundException(DistributionSetTag.class, update.getId())); - - update.getName().ifPresent(tag::setName); - update.getDescription().ifPresent(tag::setDescription); - update.getColour().ifPresent(tag::setColour); - - return distributionSetTagRepository.save(tag); - } - - @Override - @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public void delete(final long id) { - distributionSetTagRepository.deleteById(id); - } - - @Override - @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public void delete(final Collection ids) { - final List setsFound = distributionSetTagRepository.findAllById(ids); - - if (setsFound.size() < ids.size()) { - throw new EntityNotFoundException( - DistributionSetTag.class, ids, - setsFound.stream().map(DistributionSetTag::getId).toList()); - } - - distributionSetTagRepository.deleteAll(setsFound); - } - - @Override - public Optional get(final long id) { - return distributionSetTagRepository.findById(id).map(DistributionSetTag.class::cast); - } - - @Override - public List get(final Collection ids) { - return Collections.unmodifiableList(distributionSetTagRepository.findAllById(ids)); - } - - @Override - public boolean exists(final long id) { - return distributionSetTagRepository.existsById(id); - } - - @Override - public long count() { - return distributionSetTagRepository.count(); - } - - - @Override - public Slice findAll(final Pageable pageable) { - return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetTagRepository, null, pageable); - } - - @Override - public Page findByRsql(final String rsql, final Pageable pageable) { - final Specification spec = RsqlUtility.getInstance().buildRsqlSpecification(rsql, DistributionSetTagFields.class); - return JpaManagementHelper.findAllWithCountBySpec(distributionSetTagRepository, Collections.singletonList(spec), pageable); - } - - @Override - public Optional findByName(final String name) { - return distributionSetTagRepository.findByNameEquals(name); - } - - @Override - public Page findByDistributionSet(final long distributionSetId, final Pageable pageable) { + public Page findByDistributionSet(final long distributionSetId, final Pageable pageable) { if (!distributionSetRepository.existsById(distributionSetId)) { throw new EntityNotFoundException(DistributionSet.class, distributionSetId); } - return JpaManagementHelper.findAllWithCountBySpec(distributionSetTagRepository, + return JpaManagementHelper.findAllWithCountBySpec(jpaRepository, Collections.singletonList(TagSpecification.ofDistributionSet(distributionSetId)), pageable ); } @Override @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) public void delete(final String tagName) { - final JpaDistributionSetTag dsTag = distributionSetTagRepository + final JpaDistributionSetTag dsTag = jpaRepository .findOne(DistributionSetTagSpecifications.byName(tagName)) .orElseThrow(() -> new EntityNotFoundException(DistributionSetTag.class, tagName)); - distributionSetTagRepository.delete(dsTag); + jpaRepository.delete(dsTag); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetTypeManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetTypeManagement.java index 40cdc4154..890ce43ef 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetTypeManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetTypeManagement.java @@ -9,29 +9,22 @@ */ package org.eclipse.hawkbit.repository.jpa.management; +import static org.eclipse.hawkbit.repository.jpa.configuration.Constants.TX_RT_DELAY; +import static org.eclipse.hawkbit.repository.jpa.configuration.Constants.TX_RT_MAX; + import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.Optional; -import java.util.Set; -import java.util.function.Function; -import java.util.function.LongFunction; -import java.util.stream.Collectors; -import java.util.stream.Stream; + +import jakarta.persistence.EntityManager; import org.eclipse.hawkbit.repository.DistributionSetTypeFields; import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; import org.eclipse.hawkbit.repository.QuotaManagement; -import org.eclipse.hawkbit.repository.builder.DistributionSetTypeCreate; -import org.eclipse.hawkbit.repository.builder.DistributionSetTypeUpdate; -import org.eclipse.hawkbit.repository.builder.GenericDistributionSetTypeUpdate; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException; -import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper; import org.eclipse.hawkbit.repository.jpa.acm.AccessController; -import org.eclipse.hawkbit.repository.jpa.builder.JpaDistributionSetTypeCreate; -import org.eclipse.hawkbit.repository.jpa.configuration.Constants; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetType; @@ -39,40 +32,35 @@ import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetRepository; import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetTypeRepository; import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleTypeRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetTypeRepository; -import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility; import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetTypeSpecification; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.dao.ConcurrencyFailureException; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Slice; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; +import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.CollectionUtils; -import org.springframework.validation.annotation.Validated; -/** - * JPA implementation of {@link DistributionSetTypeManagement}. - */ -@Transactional(readOnly = true) -@Validated -public class JpaDistributionSetTypeManagement implements DistributionSetTypeManagement { +@Service +@ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "distribution-set-type-management" }, matchIfMissing = true) +public class JpaDistributionSetTypeManagement + extends AbstractJpaRepositoryManagement + implements DistributionSetTypeManagement { - private final DistributionSetTypeRepository distributionSetTypeRepository; private final SoftwareModuleTypeRepository softwareModuleTypeRepository; private final DistributionSetRepository distributionSetRepository; private final TargetTypeRepository targetTypeRepository; private final QuotaManagement quotaManagement; - public JpaDistributionSetTypeManagement( + protected JpaDistributionSetTypeManagement( final DistributionSetTypeRepository distributionSetTypeRepository, + final EntityManager entityManager, final SoftwareModuleTypeRepository softwareModuleTypeRepository, final DistributionSetRepository distributionSetRepository, final TargetTypeRepository targetTypeRepository, final QuotaManagement quotaManagement) { - this.distributionSetTypeRepository = distributionSetTypeRepository; + super(distributionSetTypeRepository, entityManager); this.softwareModuleTypeRepository = softwareModuleTypeRepository; this.distributionSetRepository = distributionSetRepository; this.targetTypeRepository = targetTypeRepository; @@ -81,181 +69,62 @@ public class JpaDistributionSetTypeManagement implements DistributionSetTypeMana @Override @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public List create(final Collection types) { - final List typesToCreate = types.stream() - .map(JpaDistributionSetTypeCreate.class::cast) - .map(JpaDistributionSetTypeCreate::build).toList(); - return Collections.unmodifiableList( - distributionSetTypeRepository.saveAll(AccessController.Operation.CREATE, typesToCreate)); - } - - @Override - @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public DistributionSetType create(final DistributionSetTypeCreate c) { - final JpaDistributionSetType distributionSetType = ((JpaDistributionSetTypeCreate) c).build(); - return distributionSetTypeRepository.save(AccessController.Operation.CREATE, distributionSetType); - } - - @Override - @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public DistributionSetType update(final DistributionSetTypeUpdate u) { - final GenericDistributionSetTypeUpdate update = (GenericDistributionSetTypeUpdate) u; - final JpaDistributionSetType type = findDistributionSetTypeAndThrowExceptionIfNotFound(update.getId()); - update.getDescription().ifPresent(type::setDescription); - update.getColour().ifPresent(type::setColour); - - if (hasModuleChanges(update)) { - checkDistributionSetTypeNotAssigned(update.getId()); - - final Collection currentMandatorySmTypeIds = type.getMandatoryModuleTypes().stream() - .map(SoftwareModuleType::getId).collect(Collectors.toSet()); - final Collection currentOptionalSmTypeIds = type.getOptionalModuleTypes().stream() - .map(SoftwareModuleType::getId).collect(Collectors.toSet()); - final Collection currentSmTypeIds = Stream - .concat(currentMandatorySmTypeIds.stream(), currentOptionalSmTypeIds.stream()) - .collect(Collectors.toSet()); - - final Collection updatedMandatorySmTypeIds = update.getMandatory().orElse(currentMandatorySmTypeIds); - final Collection updatedOptionalSmTypeIds = update.getOptional().orElse(currentOptionalSmTypeIds); - final Collection updatedSmTypeIds = Stream - .concat(updatedMandatorySmTypeIds.stream(), updatedOptionalSmTypeIds.stream()) - .collect(Collectors.toSet()); - - addModuleTypes(currentMandatorySmTypeIds, updatedMandatorySmTypeIds, type::addMandatoryModuleType); - addModuleTypes(currentOptionalSmTypeIds, updatedOptionalSmTypeIds, type::addOptionalModuleType); - - removeModuleTypes(currentSmTypeIds, updatedSmTypeIds, type::removeModuleType); - } - - return distributionSetTypeRepository.save(type); - } - - @Override - @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) public void delete(final long id) { - final JpaDistributionSetType toDelete = distributionSetTypeRepository.findById(id) + final JpaDistributionSetType toDelete = jpaRepository.findById(id) .orElseThrow(() -> new EntityNotFoundException(DistributionSetType.class, id)); unassignDsTypeFromTargetTypes(id); if (distributionSetRepository.countByTypeId(id) > 0) { toDelete.setDeleted(true); - distributionSetTypeRepository.save(AccessController.Operation.DELETE, toDelete); + jpaRepository.save(AccessController.Operation.DELETE, toDelete); } else { - distributionSetTypeRepository.deleteById(id); + jpaRepository.deleteById(id); } } @Override - @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public void delete(final Collection ids) { - distributionSetTypeRepository.deleteAllById(ids); + public void delete0(final Collection ids) { + ids.forEach(this::unassignDsTypeFromTargetTypes); + super.delete0(ids); } @Override - public Optional get(final long id) { - return distributionSetTypeRepository.findById(id).map(DistributionSetType.class::cast); + public Optional findByKey(final String key) { + return jpaRepository.findOne(DistributionSetTypeSpecification.byKey(key)); } @Override - public List get(final Collection ids) { - return Collections.unmodifiableList(distributionSetTypeRepository.findAllById(ids)); - } - - @Override - public boolean exists(final long id) { - return distributionSetTypeRepository.existsById(id); - } - - @Override - public long count() { - return distributionSetTypeRepository.count(DistributionSetTypeSpecification.isNotDeleted()); - } - - @Override - public Slice findAll(final Pageable pageable) { - return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetTypeRepository, List.of( - DistributionSetTypeSpecification.isNotDeleted()), pageable); - } - - @Override - public Page findByRsql(final String rsql, final Pageable pageable) { - return JpaManagementHelper.findAllWithCountBySpec(distributionSetTypeRepository, List.of( - RsqlUtility.getInstance().buildRsqlSpecification(rsql, DistributionSetTypeFields.class), - DistributionSetTypeSpecification.isNotDeleted()), pageable); - } - - @Override - public Optional findByKey(final String key) { - return distributionSetTypeRepository.findOne(DistributionSetTypeSpecification.byKey(key)).map(DistributionSetType.class::cast); - } - - @Override - public Optional findByName(final String name) { - return distributionSetTypeRepository.findOne(DistributionSetTypeSpecification.byName(name)).map(DistributionSetType.class::cast); + public Optional findByName(final String name) { + return jpaRepository.findOne(DistributionSetTypeSpecification.byName(name)); } @Override @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public DistributionSetType assignOptionalSoftwareModuleTypes(final long id, final Collection softwareModulesTypeIds) { + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) + public JpaDistributionSetType assignOptionalSoftwareModuleTypes(final long id, final Collection softwareModulesTypeIds) { return assignSoftwareModuleTypes(id, softwareModulesTypeIds, false); } @Override @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public DistributionSetType assignMandatorySoftwareModuleTypes(final long id, final Collection softwareModuleTypeIds) { + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) + public JpaDistributionSetType assignMandatorySoftwareModuleTypes(final long id, final Collection softwareModuleTypeIds) { return assignSoftwareModuleTypes(id, softwareModuleTypeIds, true); } @Override @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public DistributionSetType unassignSoftwareModuleType(final long id, final long softwareModuleTypeId) { + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) + public JpaDistributionSetType unassignSoftwareModuleType(final long id, final long softwareModuleTypeId) { final JpaDistributionSetType type = findDistributionSetTypeAndThrowExceptionIfNotFound(id); checkDistributionSetTypeNotAssigned(id); - type.removeModuleType(softwareModuleTypeId); - return distributionSetTypeRepository.save(type); + type.removeModuleType(softwareModuleTypeRepository.getById(softwareModuleTypeId)); + return jpaRepository.save(type); } - private static void removeModuleTypes( - final Collection currentSmTypeIds, final Collection updatedSmTypeIds, - final LongFunction removeModuleTypeCallback) { - final Set smTypeIdsToRemove = currentSmTypeIds.stream().filter(id -> !updatedSmTypeIds.contains(id)) - .collect(Collectors.toSet()); - if (!CollectionUtils.isEmpty(smTypeIdsToRemove)) { - smTypeIdsToRemove.forEach(removeModuleTypeCallback::apply); - } - } - - private static boolean hasModuleChanges(final GenericDistributionSetTypeUpdate update) { - return update.getOptional().isPresent() || update.getMandatory().isPresent(); - } - - private void addModuleTypes( - final Collection currentSmTypeIds, final Collection updatedSmTypeIds, - final Function addModuleTypeCallback) { - final Set smTypeIdsToAdd = updatedSmTypeIds.stream().filter(id -> !currentSmTypeIds.contains(id)).collect(Collectors.toSet()); - if (!CollectionUtils.isEmpty(smTypeIdsToAdd)) { - softwareModuleTypeRepository.findAllById(smTypeIdsToAdd).forEach(addModuleTypeCallback::apply); - } - } - - private DistributionSetType assignSoftwareModuleTypes( + private JpaDistributionSetType assignSoftwareModuleTypes( final long dsTypeId, final Collection softwareModulesTypeIds, final boolean mandatory) { final Collection foundModules = softwareModuleTypeRepository.findAllById(softwareModulesTypeIds); if (foundModules.size() < softwareModulesTypeIds.size()) { @@ -270,7 +139,7 @@ public class JpaDistributionSetTypeManagement implements DistributionSetTypeMana foundModules.forEach(mandatory ? type::addMandatoryModuleType : type::addOptionalModuleType); - return distributionSetTypeRepository.save(type); + return jpaRepository.save(type); } /** @@ -284,7 +153,7 @@ public class JpaDistributionSetTypeManagement implements DistributionSetTypeMana private void assertSoftwareModuleTypeQuota(final long id, final int requested) { QuotaHelper.assertAssignmentQuota(id, requested, quotaManagement.getMaxSoftwareModuleTypesPerDistributionSetType(), SoftwareModuleType.class, - DistributionSetType.class, distributionSetTypeRepository::countSmTypesById); + DistributionSetType.class, jpaRepository::countSmTypesById); } private void unassignDsTypeFromTargetTypes(final long typeId) { @@ -295,8 +164,8 @@ public class JpaDistributionSetTypeManagement implements DistributionSetTypeMana }); } - private JpaDistributionSetType findDistributionSetTypeAndThrowExceptionIfNotFound(final Long setId) { - return (JpaDistributionSetType) get(setId).orElseThrow(() -> new EntityNotFoundException(DistributionSetType.class, setId)); + private JpaDistributionSetType findDistributionSetTypeAndThrowExceptionIfNotFound(final Long id) { + return jpaRepository.findById(id).orElseThrow(() -> new EntityNotFoundException(DistributionSetType.class, id)); } private void checkDistributionSetTypeNotAssigned(final Long id) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutGroupManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutGroupManagement.java index b95e70018..8a0d2a05e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutGroupManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutGroupManagement.java @@ -48,10 +48,12 @@ import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus; import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; +import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.validation.annotation.Validated; @@ -61,6 +63,8 @@ import org.springframework.validation.annotation.Validated; */ @Validated @Transactional(readOnly = true) +@Service +@ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "rollout-group-management" }, matchIfMissing = true) public class JpaRolloutGroupManagement implements RolloutGroupManagement { private final RolloutGroupRepository rolloutGroupRepository; @@ -71,7 +75,7 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement { private final RolloutStatusCache rolloutStatusCache; @SuppressWarnings("java:S107") - public JpaRolloutGroupManagement(final RolloutGroupRepository rolloutGroupRepository, + protected JpaRolloutGroupManagement(final RolloutGroupRepository rolloutGroupRepository, final RolloutRepository rolloutRepository, final ActionRepository actionRepository, final TargetRepository targetRepository, final EntityManager entityManager, final RolloutStatusCache rolloutStatusCache) { this.rolloutGroupRepository = rolloutGroupRepository; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java index d4c9a8f88..064f5a4df 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaRolloutManagement.java @@ -80,6 +80,7 @@ import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus; import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus; import org.eclipse.hawkbit.security.SystemSecurityContext; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -89,6 +90,7 @@ import org.springframework.data.jpa.domain.Specification; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.validation.annotation.Validated; @@ -99,6 +101,8 @@ import org.springframework.validation.annotation.Validated; @Slf4j @Validated @Transactional(readOnly = true) +@Service +@ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "rollout-management" }, matchIfMissing = true) public class JpaRolloutManagement implements RolloutManagement { private static final List ACTIVE_ROLLOUTS = List.of( @@ -123,8 +127,7 @@ public class JpaRolloutManagement implements RolloutManagement { private final ContextAware contextAware; private final RepositoryProperties repositoryProperties; - @SuppressWarnings("java:S107") - public JpaRolloutManagement( + protected JpaRolloutManagement( final RolloutRepository rolloutRepository, final RolloutGroupRepository rolloutGroupRepository, final RolloutApprovalStrategy rolloutApprovalStrategy, diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleManagement.java index 5f03dcbe7..d1d23306b 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleManagement.java @@ -9,10 +9,12 @@ */ package org.eclipse.hawkbit.repository.jpa.management; +import static org.eclipse.hawkbit.repository.jpa.configuration.Constants.TX_RT_DELAY; +import static org.eclipse.hawkbit.repository.jpa.configuration.Constants.TX_RT_MAX; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; @@ -21,25 +23,22 @@ import java.util.stream.Collectors; import jakarta.persistence.EntityManager; -import org.eclipse.hawkbit.repository.artifact.encryption.ArtifactEncryptionService; import org.eclipse.hawkbit.repository.ArtifactManagement; import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.RepositoryConstants; import org.eclipse.hawkbit.repository.SoftwareModuleFields; import org.eclipse.hawkbit.repository.SoftwareModuleManagement; +import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; +import org.eclipse.hawkbit.repository.artifact.encryption.ArtifactEncryptionService; 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.exception.LockedException; import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper; import org.eclipse.hawkbit.repository.jpa.acm.AccessController; -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.AbstractJpaBaseEntity_; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleMetadata; @@ -50,7 +49,6 @@ import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetRepository; import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleMetadataRepository; import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleRepository; import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleTypeRepository; -import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility; import org.eclipse.hawkbit.repository.jpa.specifications.SoftwareModuleSpecification; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.model.Artifact; @@ -58,8 +56,8 @@ 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.SoftwareModuleType; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.dao.ConcurrencyFailureException; -import org.springframework.data.domain.AuditorAware; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; @@ -67,200 +65,121 @@ import org.springframework.data.domain.Slice; import org.springframework.data.jpa.domain.Specification; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; +import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.ObjectUtils; -import org.springframework.validation.annotation.Validated; -/** - * JPA implementation of {@link SoftwareModuleManagement}. - */ -@Transactional(readOnly = true) -@Validated -public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { +@Service +@ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "software-module-management" }, matchIfMissing = true) +public class JpaSoftwareModuleManagement + extends AbstractJpaRepositoryManagement + implements SoftwareModuleManagement { protected static final String SOFTWARE_MODULE_METADATA = "SoftwareModuleMetadata"; - private final EntityManager entityManager; + + private final SoftwareModuleTypeManagement softwareModuleTypeManagement; private final DistributionSetRepository distributionSetRepository; - private final SoftwareModuleRepository softwareModuleRepository; private final SoftwareModuleMetadataRepository softwareModuleMetadataRepository; private final SoftwareModuleTypeRepository softwareModuleTypeRepository; - private final AuditorAware auditorProvider; private final ArtifactManagement artifactManagement; private final QuotaManagement quotaManagement; - @SuppressWarnings("java:S107") - public JpaSoftwareModuleManagement(final EntityManager entityManager, - final DistributionSetRepository distributionSetRepository, + protected JpaSoftwareModuleManagement( final SoftwareModuleRepository softwareModuleRepository, + final EntityManager entityManager, + final SoftwareModuleTypeManagement softwareModuleTypeManagement, + final DistributionSetRepository distributionSetRepository, final SoftwareModuleMetadataRepository softwareModuleMetadataRepository, - final SoftwareModuleTypeRepository softwareModuleTypeRepository, final AuditorAware auditorProvider, + final SoftwareModuleTypeRepository softwareModuleTypeRepository, final ArtifactManagement artifactManagement, final QuotaManagement quotaManagement) { - this.entityManager = entityManager; + super(softwareModuleRepository, entityManager); + this.softwareModuleTypeManagement = softwareModuleTypeManagement; this.distributionSetRepository = distributionSetRepository; - this.softwareModuleRepository = softwareModuleRepository; this.softwareModuleMetadataRepository = softwareModuleMetadataRepository; this.softwareModuleTypeRepository = softwareModuleTypeRepository; - this.auditorProvider = auditorProvider; this.artifactManagement = artifactManagement; this.quotaManagement = quotaManagement; } @Override - @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public List create(final Collection swModules) { - final List modulesToCreate = swModules.stream().map(JpaSoftwareModuleCreate.class::cast) - .map(JpaSoftwareModuleCreate::build).toList(); - - final List createdModules = Collections - .unmodifiableList(softwareModuleRepository.saveAll(AccessController.Operation.CREATE, modulesToCreate)); + public List create(final Collection create) { + final List createdModules = super.create(create); if (createdModules.stream().anyMatch(SoftwareModule::isEncrypted)) { + // flush sm creation in order to get ids entityManager.flush(); - createdModules.stream().filter(SoftwareModule::isEncrypted).map(SoftwareModule::getId) - .forEach(encryptedModuleId -> ArtifactEncryptionService.getInstance() - .addEncryptionSecrets(encryptedModuleId)); + createdModules.stream() + .filter(SoftwareModule::isEncrypted) + .map(SoftwareModule::getId) + .forEach(encryptedModuleId -> ArtifactEncryptionService.getInstance().addEncryptionSecrets(encryptedModuleId)); } + return createdModules; } @Override - @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public SoftwareModule create(final SoftwareModuleCreate c) { - final JpaSoftwareModuleCreate create = (JpaSoftwareModuleCreate) c; + public JpaSoftwareModule create(final Create create) { + final JpaSoftwareModule createdModule = super.create(create); - final JpaSoftwareModule sm = softwareModuleRepository.save(AccessController.Operation.CREATE, create.build()); - if (create.isEncrypted()) { - // flush sm creation in order to get an Id + if (createdModule.isEncrypted()) { + // flush sm creation in order to get an id entityManager.flush(); - ArtifactEncryptionService.getInstance().addEncryptionSecrets(sm.getId()); + ArtifactEncryptionService.getInstance().addEncryptionSecrets(createdModule.getId()); } - return sm; + return createdModule; } @Override - @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public SoftwareModule update(final SoftwareModuleUpdate u) { - final GenericSoftwareModuleUpdate update = (GenericSoftwareModuleUpdate) u; - - final JpaSoftwareModule module = softwareModuleRepository.findById(update.getId()) + public JpaSoftwareModule update(final Update update) { + final JpaSoftwareModule module = jpaRepository.findById(update.getId()) .orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, update.getId())); - update.getDescription().ifPresent(module::setDescription); - update.getVendor().ifPresent(module::setVendor); - // lock/unlock ONLY if locked flag is present! - if (Boolean.TRUE.equals(update.locked())) { + if (Boolean.TRUE.equals(update.getLocked())) { module.lock(); - } else if (Boolean.FALSE.equals(update.locked())) { + } else if (Boolean.FALSE.equals(update.getLocked())) { module.unlock(); } - return softwareModuleRepository.save(module); + return super.update(update, module); + } + + @Override + protected List softDelete(final Collection toDelete) { + return toDelete.stream() + .filter(swModule -> { + final List assignedTo = swModule.getAssignedTo(); + if (assignedTo != null) { + final List lockedDS = assignedTo.stream() + .filter(DistributionSet::isLocked) + .filter(ds -> !ds.isDeleted()) + .toList(); + if (!lockedDS.isEmpty()) { + final StringBuilder sb = new StringBuilder("Part of "); + if (lockedDS.size() == 1) { + sb.append("a locked distribution set: "); + } else { + sb.append(lockedDS.size()).append(" locked distribution sets: "); + } + for (final DistributionSet ds : lockedDS) { + sb.append(ds.getName()).append(":").append(ds.getVersion()).append(" (").append(ds.getId()).append("), "); + } + sb.delete(sb.length() - 2, sb.length()); + throw new LockedException(JpaSoftwareModule.class, swModule.getId(), "DELETE", sb.toString()); + } + } + final boolean isAssigned = !ObjectUtils.isEmpty(assignedTo); + // schedule delete binary data of artifacts for every soft or not soft deleted module + deleteGridFsArtifacts(swModule); + return isAssigned; + }) + .toList(); } @Override @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public void delete(final long id) { - delete0(List.of(id)); - } - - @Override - @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public void delete(final Collection ids) { - delete0(ids); - } - private void delete0(final Collection ids) { - final List swModulesToDelete = softwareModuleRepository.findAllById(ids); - if (swModulesToDelete.size() < ids.size()) { - throw new EntityNotFoundException(SoftwareModule.class, ids, - swModulesToDelete.stream().map(SoftwareModule::getId).toList()); - } - - final Set assignedModuleIds = new HashSet<>(); - swModulesToDelete.forEach(swModule -> { - // execute this count operation without access limitations since we have to - // ensure it's not assigned when deleting it. - if (distributionSetRepository.countByModulesId(swModule.getId()) <= 0) { - softwareModuleRepository.deleteById(swModule.getId()); - } else { - assignedModuleIds.add(swModule.getId()); - } - // schedule delete binary data of artifacts - deleteGridFsArtifacts(swModule); - }); - - if (!assignedModuleIds.isEmpty()) { - String currentUser = null; - if (auditorProvider != null) { - currentUser = auditorProvider.getCurrentAuditor().orElse(null); - } - - /* - TODO AC - could use single update query as before via entity manager directly (considers tenant!): - maybe it will be possible, via specification when migrate to Spring Boot 3 - "UPDATE JpaSoftwareModule b SET b.deleted = 1, b.lastModifiedAt = :lastModifiedAt, b.lastModifiedBy = :lastModifiedBy WHERE b.tenant = :tenant AND b.id IN :ids" - */ - final long timestamp = System.currentTimeMillis(); - final List toDelete = softwareModuleRepository.findAll( - AccessController.Operation.DELETE, softwareModuleRepository.byIdsSpec(assignedModuleIds)); - for (final JpaSoftwareModule softwareModule : toDelete) { - softwareModule.setDeleted(true); - softwareModule.setLastModifiedAt(timestamp); - softwareModule.setLastModifiedBy(currentUser); - } - softwareModuleRepository.saveAll(toDelete); - } - } - - @Override - public Optional get(final long id) { - return softwareModuleRepository.findById(id).map(SoftwareModule.class::cast); - } - - @Override - public List get(final Collection ids) { - return Collections.unmodifiableList(softwareModuleRepository.findAllById(ids)); - } - - @Override - public boolean exists(final long id) { - return softwareModuleRepository.existsById(id); - } - - @Override - public long count() { - return softwareModuleRepository.count(SoftwareModuleSpecification.isNotDeleted()); - } - - @Override - public Slice findAll(final Pageable pageable) { - return JpaManagementHelper.findAllWithoutCountBySpec(softwareModuleRepository, List.of( - SoftwareModuleSpecification.isNotDeleted(), - SoftwareModuleSpecification.fetchType()), pageable); - } - - @Override - public Page findByRsql(final String rsql, final Pageable pageable) { - return JpaManagementHelper.findAllWithCountBySpec(softwareModuleRepository, List.of( - RsqlUtility.getInstance().buildRsqlSpecification(rsql, SoftwareModuleFields.class), - SoftwareModuleSpecification.isNotDeleted()), pageable); - } - - @Override - @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) public void createMetadata(final Collection create) { // group by software module id to minimize database access create.stream() @@ -272,18 +191,16 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { // touch to update revision and last modified timestamp JpaManagementHelper.touch( - entityManager, softwareModuleRepository, - (JpaSoftwareModule) get(id).orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, id))); + entityManager, jpaRepository, jpaRepository.findById(id).orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, id))); createsForSoftwareModule.forEach(this::saveMetadata); }); } - @SuppressWarnings({"unchecked", "rawtypes"}) + @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public List getMetadata(final long id) { assertSoftwareModuleExists(id); - - return (List)softwareModuleMetadataRepository.findAll(metadataBySoftwareModuleIdSpec(id)); + return (List) softwareModuleMetadataRepository.findAll(metadataBySoftwareModuleIdSpec(id)); } @Override @@ -296,15 +213,13 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { @Override public Page findMetaDataBySoftwareModuleIdAndTargetVisible(final long id, final Pageable pageable) { assertSoftwareModuleExists(id); - return JpaManagementHelper.convertPage(softwareModuleMetadataRepository.findBySoftwareModuleIdAndTargetVisible( id, true, PageRequest.of(0, RepositoryConstants.MAX_META_DATA_COUNT)), pageable); } @Override @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) public SoftwareModuleMetadata updateMetadata(final SoftwareModuleMetadataCreate c) { final JpaSoftwareModuleMetadataCreate create = (JpaSoftwareModuleMetadataCreate) c; final Long id = create.getSoftwareModuleId(); @@ -314,15 +229,13 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { // touch to update revision and last modified timestamp JpaManagementHelper.touch( - entityManager, softwareModuleRepository, - (JpaSoftwareModule) get(id).orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, id))); + entityManager, jpaRepository, jpaRepository.findById(id).orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, id))); return saveMetadata(create); } @Override @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) public SoftwareModuleMetadata updateMetadata(final SoftwareModuleMetadataUpdate u) { final GenericSoftwareModuleMetadataUpdate update = (GenericSoftwareModuleMetadataUpdate) u; @@ -334,61 +247,59 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { update.getValue().ifPresent(metadata::setValue); update.isTargetVisible().ifPresent(metadata::setTargetVisible); - JpaManagementHelper.touch(entityManager, softwareModuleRepository, metadata.getSoftwareModule()); + JpaManagementHelper.touch(entityManager, jpaRepository, metadata.getSoftwareModule()); return softwareModuleMetadataRepository.save(metadata); } @Override @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) public void deleteMetadata(final long id, final String key) { final JpaSoftwareModuleMetadata metadata = (JpaSoftwareModuleMetadata) findMetadata(id, key) .orElseThrow(() -> new EntityNotFoundException(SOFTWARE_MODULE_METADATA, id + ":" + key)); - JpaManagementHelper.touch(entityManager, softwareModuleRepository, metadata.getSoftwareModule()); + JpaManagementHelper.touch(entityManager, jpaRepository, metadata.getSoftwareModule()); softwareModuleMetadataRepository.deleteById(metadata.getId()); } @Override @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) public void lock(final long id) { - final JpaSoftwareModule softwareModule = softwareModuleRepository + final JpaSoftwareModule softwareModule = jpaRepository .findById(id) .orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, id)); if (!softwareModule.isLocked()) { softwareModule.lock(); - softwareModuleRepository.save(softwareModule); + jpaRepository.save(softwareModule); } } @Override @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY)) public void unlock(final long id) { - final JpaSoftwareModule softwareModule = softwareModuleRepository + final JpaSoftwareModule softwareModule = jpaRepository .findById(id) .orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, id)); if (softwareModule.isLocked()) { softwareModule.unlock(); - softwareModuleRepository.save(softwareModule); + jpaRepository.save(softwareModule); } } @Override - public Page findByAssignedTo(final long distributionSetId, final Pageable pageable) { + public Page findByAssignedTo(final long distributionSetId, final Pageable pageable) { assertDistributionSetExists(distributionSetId); - return JpaManagementHelper.findAllWithCountBySpec(softwareModuleRepository, - Collections.singletonList(SoftwareModuleSpecification.byAssignedToDs(distributionSetId)), pageable - ); + return JpaManagementHelper.findAllWithCountBySpec( + jpaRepository, + Collections.singletonList(SoftwareModuleSpecification.byAssignedToDs(distributionSetId)), + pageable); } @Override - public Slice findByTextAndType(final String searchText, final Long typeId, final Pageable pageable) { + public Slice findByTextAndType(final String searchText, final Long typeId, final Pageable pageable) { final List> specList = new ArrayList<>(3); specList.add(SoftwareModuleSpecification.isNotDeleted()); @@ -403,30 +314,30 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { specList.add(SoftwareModuleSpecification.fetchType()); - return JpaManagementHelper.findAllWithoutCountBySpec(softwareModuleRepository, specList, pageable); + return JpaManagementHelper.findAllWithoutCountBySpec(jpaRepository, specList, pageable); } @Override - public Optional findByNameAndVersionAndType(final String name, final String version, - final long typeId) { + public Optional findByNameAndVersionAndType(final String name, final String version, final long typeId) { assertSoftwareModuleTypeExists(typeId); // TODO AC - Access is restricted. This could have problem with UI when access control is enabled. // Vaadin UI use this for validation. May need to be called via elevated access return JpaManagementHelper - .findOneBySpec(softwareModuleRepository, List.of( - SoftwareModuleSpecification.likeNameAndVersion(name, version), - SoftwareModuleSpecification.equalType(typeId), - SoftwareModuleSpecification.fetchType())) - .map(SoftwareModule.class::cast); + .findOneBySpec( + jpaRepository, + List.of( + SoftwareModuleSpecification.likeNameAndVersion(name, version), + SoftwareModuleSpecification.equalType(typeId), + SoftwareModuleSpecification.fetchType())); } @Override - public Slice findByType(final long typeId, final Pageable pageable) { + public Slice findByType(final long typeId, final Pageable pageable) { assertSoftwareModuleTypeExists(typeId); return JpaManagementHelper.findAllWithoutCountBySpec( - softwareModuleRepository, + jpaRepository, List.of( SoftwareModuleSpecification.equalType(typeId), SoftwareModuleSpecification.isNotDeleted()), pageable @@ -445,7 +356,7 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { public long countByAssignedTo(final long distributionSetId) { assertDistributionSetExists(distributionSetId); - return softwareModuleRepository.count(SoftwareModuleSpecification.byAssignedToDs(distributionSetId)); + return jpaRepository.count(SoftwareModuleSpecification.byAssignedToDs(distributionSetId)); } private static Specification metadataBySoftwareModuleIdSpec(final long id) { @@ -453,7 +364,7 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { } private void deleteGridFsArtifacts(final JpaSoftwareModule swModule) { - softwareModuleRepository.getAccessController().ifPresent(accessController -> + jpaRepository.getAccessController().ifPresent(accessController -> accessController.assertOperationAllowed(AccessController.Operation.DELETE, swModule)); final Set sha1Hashes = swModule.getArtifacts().stream().map(Artifact::getSha1Hash).collect(Collectors.toSet()); AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(() -> @@ -499,7 +410,7 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { } private void assertSoftwareModuleExists(final Long id) { - if (!softwareModuleRepository.existsById(id)) { + if (!jpaRepository.existsById(id)) { throw new EntityNotFoundException(SoftwareModule.class, id); } } @@ -515,4 +426,4 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { throw new EntityNotFoundException(DistributionSet.class, distributionSetId); } } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleTypeManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleTypeManagement.java index 9acb5fbad..a496260f8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleTypeManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSoftwareModuleTypeManagement.java @@ -10,166 +10,52 @@ package org.eclipse.hawkbit.repository.jpa.management; import java.util.Collection; -import java.util.Collections; -import java.util.List; import java.util.Optional; +import jakarta.persistence.EntityManager; + import org.eclipse.hawkbit.repository.SoftwareModuleTypeFields; import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; -import org.eclipse.hawkbit.repository.builder.GenericSoftwareModuleTypeUpdate; -import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeCreate; -import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeUpdate; -import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; -import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper; -import org.eclipse.hawkbit.repository.jpa.acm.AccessController; -import org.eclipse.hawkbit.repository.jpa.builder.JpaSoftwareModuleTypeCreate; -import org.eclipse.hawkbit.repository.jpa.configuration.Constants; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType; import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetTypeRepository; import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleRepository; import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleTypeRepository; -import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility; -import org.eclipse.hawkbit.repository.jpa.specifications.SoftwareModuleTypeSpecification; -import org.eclipse.hawkbit.repository.model.SoftwareModuleType; -import org.springframework.dao.ConcurrencyFailureException; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Slice; -import org.springframework.retry.annotation.Backoff; -import org.springframework.retry.annotation.Retryable; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.annotation.Validated; +import org.eclipse.hawkbit.repository.jpa.utils.ExceptionMapper; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; +import org.springframework.stereotype.Service; -/** - * JPA implementation of {@link SoftwareModuleTypeManagement}. - */ -@Transactional(readOnly = true) -@Validated -public class JpaSoftwareModuleTypeManagement implements SoftwareModuleTypeManagement { +@Service +@ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "software-module-type=management" }, matchIfMissing = true) +public class JpaSoftwareModuleTypeManagement + extends AbstractJpaRepositoryManagement + implements SoftwareModuleTypeManagement { private final DistributionSetTypeRepository distributionSetTypeRepository; - private final SoftwareModuleTypeRepository softwareModuleTypeRepository; private final SoftwareModuleRepository softwareModuleRepository; - public JpaSoftwareModuleTypeManagement( - final DistributionSetTypeRepository distributionSetTypeRepository, + protected JpaSoftwareModuleTypeManagement( final SoftwareModuleTypeRepository softwareModuleTypeRepository, + final EntityManager entityManager, + final DistributionSetTypeRepository distributionSetTypeRepository, final SoftwareModuleRepository softwareModuleRepository) { + super(softwareModuleTypeRepository, entityManager); this.distributionSetTypeRepository = distributionSetTypeRepository; - this.softwareModuleTypeRepository = softwareModuleTypeRepository; this.softwareModuleRepository = softwareModuleRepository; } @Override - @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public SoftwareModuleType create(final SoftwareModuleTypeCreate c) { - final JpaSoftwareModuleTypeCreate create = (JpaSoftwareModuleTypeCreate) c; - - return softwareModuleTypeRepository.save(AccessController.Operation.CREATE, create.build()); + public Optional findByKey(final String key) { + return jpaRepository.findByKey(key); } @Override - @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public SoftwareModuleType update(final SoftwareModuleTypeUpdate u) { - final GenericSoftwareModuleTypeUpdate update = (GenericSoftwareModuleTypeUpdate) u; - - final JpaSoftwareModuleType type = (JpaSoftwareModuleType) get(update.getId()) - .orElseThrow(() -> new EntityNotFoundException(SoftwareModuleType.class, update.getId())); - - update.getDescription().ifPresent(type::setDescription); - update.getColour().ifPresent(type::setColour); - - return softwareModuleTypeRepository.save(type); + public Optional findByName(final String name) { + return jpaRepository.findByName(name); } @Override - @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public void delete(final long id) { - final JpaSoftwareModuleType toDelete = softwareModuleTypeRepository.findById(id) - .orElseThrow(() -> new EntityNotFoundException(SoftwareModuleType.class, id)); - - delete(toDelete); + protected Collection softDelete(final Collection toDelete) { + return toDelete.stream().filter(smt -> + softwareModuleRepository.countByType(smt) > 0 || distributionSetTypeRepository.countByElementsSmType(smt) > 0).toList(); } - - @Override - @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public void delete(final Collection ids) { - softwareModuleTypeRepository - .findAll(AccessController.Operation.DELETE, softwareModuleTypeRepository.byIdsSpec(ids)) - .forEach(this::delete); - } - - @Override - public Optional get(final long id) { - return softwareModuleTypeRepository.findById(id).map(SoftwareModuleType.class::cast); - } - - @Override - public List get(final Collection ids) { - return Collections.unmodifiableList(softwareModuleTypeRepository.findAllById(ids)); - } - - @Override - public boolean exists(final long id) { - return softwareModuleTypeRepository.existsById(id); - } - - @Override - public long count() { - return softwareModuleTypeRepository.count(SoftwareModuleTypeSpecification.isNotDeleted()); - } - - @Override - public Slice findAll(final Pageable pageable) { - return JpaManagementHelper.findAllWithoutCountBySpec(softwareModuleTypeRepository, - List.of(SoftwareModuleTypeSpecification.isNotDeleted()), pageable - ); - } - - @Override - public Page findByRsql(final String rsql, final Pageable pageable) { - return JpaManagementHelper.findAllWithCountBySpec(softwareModuleTypeRepository, List.of( - RsqlUtility.getInstance().buildRsqlSpecification(rsql, SoftwareModuleTypeFields.class), - SoftwareModuleTypeSpecification.isNotDeleted()), pageable - ); - } - - @Override - public Optional findByKey(final String key) { - return softwareModuleTypeRepository.findByKey(key); - } - - @Override - public Optional findByName(final String name) { - return softwareModuleTypeRepository.findByName(name); - } - - @Override - @Transactional - @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, - backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public List create(final Collection c) { - final List creates = c.stream().map(JpaSoftwareModuleTypeCreate.class::cast) - .map(JpaSoftwareModuleTypeCreate::build).toList(); - return Collections.unmodifiableList( - softwareModuleTypeRepository.saveAll(AccessController.Operation.CREATE, creates)); - } - - private void delete(JpaSoftwareModuleType toDelete) { - if (softwareModuleRepository.countByType(toDelete) > 0 - || distributionSetTypeRepository.countByElementsSmType(toDelete) > 0) { - toDelete.setDeleted(true); - softwareModuleTypeRepository.save(AccessController.Operation.DELETE, toDelete); - } else { - softwareModuleTypeRepository.delete(toDelete); - } - } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSystemManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSystemManagement.java index 56336852d..f3106ccdd 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSystemManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSystemManagement.java @@ -9,17 +9,18 @@ */ package org.eclipse.hawkbit.repository.jpa.management; +import java.util.Set; import java.util.function.Consumer; import jakarta.persistence.EntityManager; import lombok.extern.slf4j.Slf4j; -import org.eclipse.hawkbit.repository.artifact.ArtifactRepository; import org.eclipse.hawkbit.cache.TenancyCacheManager; import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.RolloutStatusCache; import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.TenantStatsManagement; +import org.eclipse.hawkbit.repository.artifact.ArtifactRepository; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.jpa.CurrentTenantCacheKeyGenerator; import org.eclipse.hawkbit.repository.jpa.SystemManagementCacheKeyGenerator; @@ -48,6 +49,7 @@ import org.eclipse.hawkbit.repository.report.model.SystemUsageReportWithTenants; import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.tenancy.TenantAware; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.dao.ConcurrencyFailureException; @@ -58,6 +60,7 @@ import org.springframework.lang.Nullable; import org.springframework.orm.jpa.vendor.Database; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; +import org.springframework.stereotype.Service; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @@ -69,6 +72,8 @@ import org.springframework.validation.annotation.Validated; @Slf4j @Transactional(readOnly = true) @Validated +@Service +@ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "system-management" }, matchIfMissing = true) public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, SystemManagement { private static final int MAX_TENANTS_QUERY = 1000; @@ -102,7 +107,7 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst private ArtifactRepository artifactRepository; @SuppressWarnings("squid:S00107") - public JpaSystemManagement( + protected JpaSystemManagement( final TargetRepository targetRepository, final TargetTypeRepository targetTypeRepository, final TargetTagRepository targetTagRepository, final TargetFilterQueryRepository targetFilterQueryRepository, final SoftwareModuleRepository softwareModuleRepository, final SoftwareModuleTypeRepository softwareModuleTypeRepository, @@ -193,6 +198,7 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst public void forEachTenant(final Consumer consumer) { forEachTenant0(consumer); } + private void forEachTenant0(final Consumer consumer) { Page tenants; Pageable query = PageRequest.of(0, MAX_TENANTS_QUERY); @@ -320,18 +326,19 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst distributionSetTypeRepository .save(new JpaDistributionSetType(org.eclipse.hawkbit.repository.Constants.DST_DEFAULT_OS_ONLY_KEY, org.eclipse.hawkbit.repository.Constants.DST_DEFAULT_OS_ONLY_NAME, - "Default type with Firmware/OS only.").addMandatoryModuleType(os)); + "Default type with Firmware/OS only.").setMandatoryModuleTypes(Set.of(os))); distributionSetTypeRepository .save(new JpaDistributionSetType(org.eclipse.hawkbit.repository.Constants.DST_DEFAULT_APP_ONLY_KEY, org.eclipse.hawkbit.repository.Constants.DST_DEFAULT_APP_ONLY_NAME, - "Default type with app(s) only.").addMandatoryModuleType(app)); + "Default type with app(s) only.").setMandatoryModuleTypes(Set.of(app))); return distributionSetTypeRepository .save(new JpaDistributionSetType(org.eclipse.hawkbit.repository.Constants.DST_DEFAULT_OS_WITH_APPS_KEY, org.eclipse.hawkbit.repository.Constants.DST_DEFAULT_OS_WITH_APPS_NAME, - "Default type with Firmware/OS and optional app(s).").addMandatoryModuleType(os) - .addOptionalModuleType(app)); + "Default type with Firmware/OS and optional app(s).") + .setMandatoryModuleTypes(Set.of(os)) + .setOptionalModuleTypes(Set.of(app))); } private TenantMetaData createTenantMetadata0(final String tenant) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetFilterQueryManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetFilterQueryManagement.java index 4468bbab3..3d0bbfc1b 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetFilterQueryManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetFilterQueryManagement.java @@ -52,6 +52,7 @@ import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.utils.TenantConfigHelper; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.data.domain.AuditorAware; import org.springframework.data.domain.Page; @@ -60,6 +61,7 @@ import org.springframework.data.domain.Slice; import org.springframework.data.jpa.domain.Specification; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; +import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.ObjectUtils; import org.springframework.validation.annotation.Validated; @@ -70,11 +72,13 @@ import org.springframework.validation.annotation.Validated; @Slf4j @Transactional(readOnly = true) @Validated -public class JpaTargetFilterQueryManagement implements TargetFilterQueryManagement { +@Service +@ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "target-filter-management" }, matchIfMissing = true) +class JpaTargetFilterQueryManagement implements TargetFilterQueryManagement { private final TargetFilterQueryRepository targetFilterQueryRepository; private final TargetManagement targetManagement; - private final DistributionSetManagement distributionSetManagement; + private final DistributionSetManagement distributionSetManagement; private final QuotaManagement quotaManagement; private final TenantConfigurationManagement tenantConfigurationManagement; private final RepositoryProperties repositoryProperties; @@ -82,10 +86,9 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme private final ContextAware contextAware; private final AuditorAware auditorAware; - @SuppressWarnings("java:S107") - public JpaTargetFilterQueryManagement( + protected JpaTargetFilterQueryManagement( final TargetFilterQueryRepository targetFilterQueryRepository, - final TargetManagement targetManagement, final DistributionSetManagement distributionSetManagement, + final TargetManagement targetManagement, final DistributionSetManagement distributionSetManagement, final QuotaManagement quotaManagement, final TenantConfigurationManagement tenantConfigurationManagement, final RepositoryProperties repositoryProperties, final SystemSecurityContext systemSecurityContext, final ContextAware contextAware, final AuditorAware auditorAware) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetManagement.java index ac1ded544..0c2cc4e32 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetManagement.java @@ -77,6 +77,7 @@ import org.eclipse.hawkbit.repository.model.TargetType; import org.eclipse.hawkbit.repository.model.TargetTypeAssignmentResult; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.tenancy.TenantAware; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -84,6 +85,7 @@ import org.springframework.data.domain.Slice; import org.springframework.data.jpa.domain.Specification; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; +import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.ObjectUtils; import org.springframework.validation.annotation.Validated; @@ -93,10 +95,12 @@ import org.springframework.validation.annotation.Validated; */ @Transactional(readOnly = true) @Validated +@Service +@ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "target-management" }, matchIfMissing = true) public class JpaTargetManagement implements TargetManagement { private final EntityManager entityManager; - private final DistributionSetManagement distributionSetManagement; + private final JpaDistributionSetManagement distributionSetManagement; private final QuotaManagement quotaManagement; private final TargetRepository targetRepository; private final TargetTypeRepository targetTypeRepository; @@ -106,8 +110,8 @@ public class JpaTargetManagement implements TargetManagement { private final TenantAware tenantAware; @SuppressWarnings("java:S107") - public JpaTargetManagement(final EntityManager entityManager, - final DistributionSetManagement distributionSetManagement, final QuotaManagement quotaManagement, + protected JpaTargetManagement(final EntityManager entityManager, + final JpaDistributionSetManagement distributionSetManagement, final QuotaManagement quotaManagement, final TargetRepository targetRepository, final TargetTypeRepository targetTypeRepository, final RolloutGroupRepository rolloutGroupRepository, final TargetFilterQueryRepository targetFilterQueryRepository, diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTagManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTagManagement.java index 8ae119f84..855fdf914 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTagManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTagManagement.java @@ -28,12 +28,15 @@ import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaNamedEntity_; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag; import org.eclipse.hawkbit.repository.jpa.repository.TargetTagRepository; import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility; +import org.eclipse.hawkbit.repository.model.Tag; import org.eclipse.hawkbit.repository.model.TargetTag; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; +import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -42,11 +45,13 @@ import org.springframework.validation.annotation.Validated; */ @Transactional(readOnly = true) @Validated +@Service +@ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "target-tag-management" }, matchIfMissing = true) public class JpaTargetTagManagement implements TargetTagManagement { private final TargetTagRepository targetTagRepository; - public JpaTargetTagManagement(final TargetTagRepository targetTagRepository) { + protected JpaTargetTagManagement(final TargetTagRepository targetTagRepository) { this.targetTagRepository = targetTagRepository;; } @@ -69,7 +74,7 @@ public class JpaTargetTagManagement implements TargetTagManagement { @Transactional @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) - public List create(final Collection tt) { + public List create(final Collection> tt) { final List targetTagList = tt.stream().map(JpaTagCreate.class::cast) .map(JpaTagCreate::buildTargetTag).toList(); return Collections.unmodifiableList( diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTypeManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTypeManagement.java index 0334d2ce4..ef88b4179 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTypeManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetTypeManagement.java @@ -38,12 +38,14 @@ import org.eclipse.hawkbit.repository.jpa.specifications.TargetTypeSpecification import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.TargetType; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; +import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -52,6 +54,8 @@ import org.springframework.validation.annotation.Validated; */ @Transactional(readOnly = true) @Validated +@Service +@ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "target-type-management" }, matchIfMissing = true) public class JpaTargetTypeManagement implements TargetTypeManagement { private final TargetTypeRepository targetTypeRepository; @@ -60,13 +64,7 @@ public class JpaTargetTypeManagement implements TargetTypeManagement { private final QuotaManagement quotaManagement; - /** - * Constructor - * - * @param targetTypeRepository Target type repository - * @param targetRepository Target repository - */ - public JpaTargetTypeManagement(final TargetTypeRepository targetTypeRepository, + protected JpaTargetTypeManagement(final TargetTypeRepository targetTypeRepository, final TargetRepository targetRepository, final DistributionSetTypeRepository distributionSetTypeRepository, final QuotaManagement quotaManagement) { this.targetTypeRepository = targetTypeRepository; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java index 1741c0ef3..1c1a0971b 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java @@ -53,6 +53,7 @@ import org.eclipse.hawkbit.tenancy.configuration.PollingTime; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CacheEvict; @@ -65,6 +66,7 @@ import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; +import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.ObjectUtils; import org.springframework.validation.annotation.Validated; @@ -75,6 +77,8 @@ import org.springframework.validation.annotation.Validated; @Slf4j @Transactional(readOnly = true) @Validated +@Service +@ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "tenant-configuration-management" }, matchIfMissing = true) public class JpaTenantConfigurationManagement implements TenantConfigurationManagement { private static final ConfigurableConversionService CONVERSION_SERVICE = new DefaultConversionService(); @@ -87,7 +91,7 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana private ServiceMatcher serviceMatcher; - public JpaTenantConfigurationManagement( + protected JpaTenantConfigurationManagement( final TenantConfigurationRepository tenantConfigurationRepository, final TenantConfigurationProperties tenantConfigurationProperties, final CacheManager cacheManager, final AfterTransactionCommitExecutor afterCommitExecutor, diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantStatsManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantStatsManagement.java index ca270de88..00282d3e5 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantStatsManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantStatsManagement.java @@ -15,6 +15,8 @@ import org.eclipse.hawkbit.repository.jpa.repository.LocalArtifactRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository; import org.eclipse.hawkbit.repository.report.model.TenantUsage; import org.eclipse.hawkbit.tenancy.TenantAware; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; +import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -23,6 +25,8 @@ import org.springframework.validation.annotation.Validated; * Management service for statistics of a single tenant. */ @Validated +@Service +@ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "tenant-stats-management" }, matchIfMissing = true) public class JpaTenantStatsManagement implements TenantStatsManagement { private final TargetRepository targetRepository; @@ -30,7 +34,7 @@ public class JpaTenantStatsManagement implements TenantStatsManagement { private final ActionRepository actionRepository; private final TenantAware tenantAware; - public JpaTenantStatsManagement( + protected JpaTenantStatsManagement( final TargetRepository targetRepository, final LocalArtifactRepository artifactRepository, final ActionRepository actionRepository, final TenantAware tenantAware) { this.targetRepository = targetRepository; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OfflineDsAssignmentStrategy.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OfflineDsAssignmentStrategy.java index 07dbb5b99..30f560ead 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OfflineDsAssignmentStrategy.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OfflineDsAssignmentStrategy.java @@ -40,10 +40,9 @@ import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TargetWithActionType; /** - * AbstractDsAssignmentStrategy for offline assignments, i.e. not managed by - * hawkBit. + * AbstractDsAssignmentStrategy for offline assignments, i.e. not managed by hawkBit. */ -public class OfflineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { +class OfflineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { OfflineDsAssignmentStrategy( final TargetRepository targetRepository, diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OnlineDsAssignmentStrategy.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OnlineDsAssignmentStrategy.java index 2e8f4beba..5a84532ef 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OnlineDsAssignmentStrategy.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/OnlineDsAssignmentStrategy.java @@ -48,7 +48,7 @@ import org.springframework.util.CollectionUtils; /** * AbstractDsAssignmentStrategy for online assignments, i.e. managed by hawkBit. */ -public class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { +class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { OnlineDsAssignmentStrategy(final TargetRepository targetRepository, final AfterTransactionCommitExecutor afterCommit, diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/DistributionSetTypeElement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/DistributionSetTypeElement.java index 4ac21d9ee..d0ba09076 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/DistributionSetTypeElement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/DistributionSetTypeElement.java @@ -11,6 +11,7 @@ package org.eclipse.hawkbit.repository.jpa.model; import java.io.Serial; import java.io.Serializable; +import java.util.Objects; import jakarta.persistence.Column; import jakarta.persistence.ConstraintMode; @@ -85,28 +86,13 @@ public class DistributionSetTypeElement implements Serializable { @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (key == null ? 0 : key.hashCode()); - return result; + return Objects.hash(key, mandatory); } @Override public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final DistributionSetTypeElement other = (DistributionSetTypeElement) obj; - if (key == null) { - return other.key == null; - } else { - return key.equals(other.key); - } + return obj instanceof DistributionSetTypeElement distributionSetTypeElement && + Objects.equals(key, distributionSetTypeElement.key) && + Objects.equals(mandatory, distributionSetTypeElement.mandatory); } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java index 414dcadec..f3b0923f4 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java @@ -137,35 +137,22 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen @Column(name = "required_migration_step") private boolean requiredMigrationStep; - public JpaDistributionSet( - final String name, final String version, final String description, - final DistributionSetType type, final Collection moduleList, - final boolean requiredMigrationStep) { - super(name, version, description); - - this.type = type; - // modules shall be set before type.checkComplete call - if (moduleList != null) { - moduleList.forEach(this::addModule); - } - if (this.type != null) { - complete = this.type.checkComplete(this); - } - - this.valid = true; - this.requiredMigrationStep = requiredMigrationStep; - } - - public JpaDistributionSet(final String name, final String version, final String description, - final DistributionSetType type, final Collection moduleList) { - this(name, version, description, type, moduleList, false); - } - @Override public Set getModules() { return Collections.unmodifiableSet(modules); } + @SuppressWarnings("java:S1144") // used via reflection copy utils + private JpaDistributionSet setModules(final Set modules) { + if (modules == null) { + return this; // do not change + } + + modules.forEach(this::addModule); // skip if already present + this.modules.stream().filter(module -> !modules.contains(module)).toList().forEach(this::removeModule); + return this; + } + public void addModule(final SoftwareModule softwareModule) { if (isLocked()) { throw new LockedException(JpaDistributionSet.class, getId(), "ADD_SOFTWARE_MODULE"); @@ -175,13 +162,11 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen final Optional found = modules.stream() .filter(module -> module.getId().equals(softwareModule.getId())).findAny(); - if (found.isPresent()) { return; } final long already = modules.stream().filter(module -> module.getType().getKey().equals(softwareModule.getType().getKey())).count(); - if (already >= softwareModule.getType().getMaxAssignments()) { modules.stream().filter(module -> module.getType().getKey().equals(softwareModule.getType().getKey())) .findAny().ifPresent(modules::remove); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSetType.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSetType.java index 2dd501f2f..da46d3e20 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSetType.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSetType.java @@ -44,7 +44,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleType; @Table(name = "sp_distribution_set_type", indexes = { @Index(name = "sp_idx_distribution_set_type_01", columnList = "tenant,deleted"), @Index(name = "sp_idx_distribution_set_type_prim", columnList = "tenant,id") }, uniqueConstraints = { - @UniqueConstraint(columnNames = { "tenant", "type_key"}, name = "uk_sp_distribution_set_type_type_key"), + @UniqueConstraint(columnNames = { "tenant", "type_key" }, name = "uk_sp_distribution_set_type_type_key"), @UniqueConstraint(columnNames = { "tenant", "name" }, name = "uk_sp_distribution_set_type_name") }) // exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for sub entities @SuppressWarnings("squid:S2160") @@ -88,6 +88,30 @@ public class JpaDistributionSetType extends AbstractJpaTypeEntity implements Dis .collect(Collectors.toSet()); } + public JpaDistributionSetType setMandatoryModuleTypes(final Set smType) { + return replaceOrAddModuleTypes(smType, true, true); + } + + public JpaDistributionSetType setOptionalModuleTypes(final Set smType) { + return replaceOrAddModuleTypes(smType, false, true); + } + + public JpaDistributionSetType addMandatoryModuleType(final SoftwareModuleType smType) { + return replaceOrAddModuleTypes(Set.of(smType), true, false); + } + + public JpaDistributionSetType addOptionalModuleType(final SoftwareModuleType smType) { + return replaceOrAddModuleTypes(Set.of(smType), false, false); + } + + public JpaDistributionSetType removeModuleType(final SoftwareModuleType smType) { + elements.stream() + .filter(element -> smType.getId().equals(element.getSmType().getId())) + .toList() // collect to a list to avoid ConcurrentModificationException + .forEach(element -> elements.remove(element)); + return this; + } + @Override public boolean checkComplete(final DistributionSet distributionSet) { final List smTypes = distributionSet.getModules().stream() @@ -97,23 +121,6 @@ public class JpaDistributionSetType extends AbstractJpaTypeEntity implements Dis return !smTypes.isEmpty() && new HashSet<>(smTypes).containsAll(getMandatoryModuleTypes()); } - public JpaDistributionSetType addOptionalModuleType(final SoftwareModuleType smType) { - return setModuleType(smType, false); - } - - public JpaDistributionSetType addMandatoryModuleType(final SoftwareModuleType smType) { - return setModuleType(smType, true); - } - - public JpaDistributionSetType removeModuleType(final Long smTypeId) { - // we search by id (standard equals compares also revision) - elements.stream() - .filter(element -> element.getSmType().getId().equals(smTypeId)) - .findAny() - .ifPresent(elements::remove); - return this; - } - @Override public String toString() { return "DistributionSetType [key=" + getKey() + ", isDeleted()=" + isDeleted() + ", getId()=" + getId() + "]"; @@ -135,20 +142,30 @@ public class JpaDistributionSetType extends AbstractJpaTypeEntity implements Dis .publishEvent(new DistributionSetTypeDeletedEvent(getTenant(), getId(), getClass())); } - private JpaDistributionSetType setModuleType(final SoftwareModuleType smType, final boolean mandatory) { + private JpaDistributionSetType replaceOrAddModuleTypes(final Set smTypes, final boolean mandatory, final boolean replace) { + if (smTypes == null) { + return this; // do not change + } + if (elements.isEmpty()) { - elements.add(new DistributionSetTypeElement(this, (JpaSoftwareModuleType) smType, mandatory)); + smTypes.forEach(smType -> elements.add(new DistributionSetTypeElement(this, (JpaSoftwareModuleType) smType, mandatory))); return this; } - // check if this was in the list before - elements.stream() - .filter(element -> element.getSmType().getKey().equals(smType.getKey())) - .findAny() - .ifPresentOrElse( - element -> element.setMandatory(mandatory), - () -> elements.add(new DistributionSetTypeElement(this, (JpaSoftwareModuleType) smType, mandatory))); + smTypes.stream() + .filter(smType -> !elements.contains(new DistributionSetTypeElement(this, (JpaSoftwareModuleType) smType, mandatory))) + .collect(Collectors.toSet()) + .forEach(smType -> elements.add(new DistributionSetTypeElement(this, (JpaSoftwareModuleType) smType, mandatory))); + if (replace) { + final Set smTypeIds = smTypes.stream() + .map(SoftwareModuleType::getId) + .collect(Collectors.toSet()); + elements.stream() + .filter(element -> element.isMandatory() == mandatory && !smTypeIds.contains(element.getSmType().getId())) + .collect(Collectors.toSet()) + .forEach(element -> elements.remove(element)); + } return this; } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModule.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModule.java index 59cecee0b..0043d7514 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModule.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaSoftwareModule.java @@ -112,7 +112,6 @@ public class JpaSoftwareModule extends AbstractJpaNamedVersionedEntity implement private boolean deleted; @ToString.Exclude - @Getter(AccessLevel.NONE) @ManyToMany(mappedBy = "modules", targetEntity = JpaDistributionSet.class, fetch = FetchType.LAZY) private List assignedTo; @@ -174,29 +173,6 @@ public class JpaSoftwareModule extends AbstractJpaNamedVersionedEntity implement locked = false; } - public void setDeleted(final boolean deleted) { - if (assignedTo != null) { - final List lockedDS = assignedTo.stream() - .filter(DistributionSet::isLocked) - .filter(ds -> !ds.isDeleted()) - .toList(); - if (!lockedDS.isEmpty()) { - final StringBuilder sb = new StringBuilder("Part of "); - if (lockedDS.size() == 1) { - sb.append("a locked distribution set: "); - } else { - sb.append(lockedDS.size()).append(" locked distribution sets: "); - } - for (final DistributionSet ds : lockedDS) { - sb.append(ds.getName()).append(":").append(ds.getVersion()).append(" (").append(ds.getId()).append("), "); - } - sb.delete(sb.length() - 2, sb.length()); - throw new LockedException(JpaSoftwareModule.class, getId(), "DELETE", sb.toString()); - } - } - this.deleted = deleted; - } - @Override public void fireCreateEvent() { EventPublisherHolder.getInstance().getEventPublisher().publishEvent(new SoftwareModuleCreatedEvent(this)); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/BaseEntityRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/BaseEntityRepository.java index a1f046d49..f6b262602 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/BaseEntityRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/BaseEntityRepository.java @@ -18,8 +18,8 @@ import jakarta.persistence.EntityManager; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.jpa.acm.AccessController; +import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity; import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_; -import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaTenantAwareBaseEntity; import org.eclipse.hawkbit.repository.model.BaseEntity; import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity; import org.springframework.data.jpa.domain.Specification; @@ -37,7 +37,7 @@ import org.springframework.transaction.annotation.Transactional; */ @NoRepositoryBean @Transactional(readOnly = true) -public interface BaseEntityRepository +public interface BaseEntityRepository extends PagingAndSortingRepository, CrudRepository, JpaSpecificationExecutor, JpaSpecificationEntityGraphExecutor, NoCountSliceRepository, ACMRepository { @@ -118,11 +118,11 @@ public interface BaseEntityRepository Specification byIdSpec(final Long id) { + default Specification byIdSpec(final Long id) { return (root, query, cb) -> cb.equal(root.get(AbstractJpaBaseEntity_.id), id); } - default Specification byIdsSpec(final Iterable ids) { + default Specification byIdsSpec(final Iterable ids) { final Collection collection; if (ids instanceof Collection idCollection) { collection = idCollection; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/BaseEntityRepositoryACM.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/BaseEntityRepositoryACM.java index 042d96563..2ec072ada 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/BaseEntityRepositoryACM.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/BaseEntityRepositoryACM.java @@ -25,7 +25,7 @@ import lombok.extern.slf4j.Slf4j; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; import org.eclipse.hawkbit.repository.jpa.acm.AccessController; -import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaTenantAwareBaseEntity; +import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; @@ -35,7 +35,7 @@ import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; @Slf4j -public class BaseEntityRepositoryACM implements BaseEntityRepository { +public class BaseEntityRepositoryACM implements BaseEntityRepository { private static final String SPEC_MUST_NOT_BE_NULL = "Specification must not be null"; private static final String APPENDED_ACCESS_RULES_SPEC_OF_NON_NULL_SPEC_MUST_NOT_BE_NULL = @@ -337,7 +337,7 @@ public class BaseEntityRepositoryACM } @SuppressWarnings("unchecked") - static > R of( + static > R of( final R repository, @NonNull final AccessController accessController) { Objects.requireNonNull(repository); Objects.requireNonNull(accessController); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/DistributionSetTagRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/DistributionSetTagRepository.java index 9f79071bc..e3a1d6f3d 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/DistributionSetTagRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/DistributionSetTagRepository.java @@ -36,7 +36,7 @@ public interface DistributionSetTagRepository * @param tagName to filter on * @return the {@link DistributionSetTag} if found, otherwise null */ - Optional findByNameEquals(String tagName); + Optional findByNameEquals(String tagName); /** * Returns all instances of the type. diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/HawkbitBaseRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/HawkbitBaseRepository.java index 33c38b37c..b879cba7a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/HawkbitBaseRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/HawkbitBaseRepository.java @@ -19,7 +19,6 @@ import jakarta.persistence.NoResultException; import jakarta.persistence.TypedQuery; import jakarta.transaction.Transactional; -import org.eclipse.hawkbit.repository.BaseRepositoryTypeProvider; import org.eclipse.hawkbit.repository.jpa.acm.AccessController; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -175,16 +174,4 @@ public class HawkbitBaseRepository extends SimpleJpa final List content = query.getResultList(); return new PageImpl<>(content, pageable, content.size()); } - - /** - * Simple implementation of {@link BaseRepositoryTypeProvider} leveraging our - * {@link HawkbitBaseRepository} for all current use cases - */ - public static class RepositoryTypeProvider implements BaseRepositoryTypeProvider { - - @Override - public Class getBaseRepositoryType(final Class repositoryType) { - return HawkbitBaseRepository.class; - } - } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/SoftwareModuleTypeRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/SoftwareModuleTypeRepository.java index 1c6ec02f7..deea8c419 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/SoftwareModuleTypeRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/SoftwareModuleTypeRepository.java @@ -31,13 +31,13 @@ public interface SoftwareModuleTypeRepository extends BaseEntityRepository findByKey(String key); + Optional findByKey(String key); /** * @param name to search for * @return all {@link SoftwareModuleType}s in the repository with given {@link SoftwareModuleType#getName()} */ - Optional findByName(String name); + Optional findByName(String name); /** * Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety reasons (this is a "delete everything" query diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/DistributionSetCreatedEventTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/DistributionSetCreatedEventTest.java index 5cb5f9de5..70a08fd7a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/DistributionSetCreatedEventTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/DistributionSetCreatedEventTest.java @@ -9,6 +9,7 @@ */ package org.eclipse.hawkbit.repository.event.remote.entity; +import org.eclipse.hawkbit.repository.DistributionSetManagement.Create; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.junit.jupiter.api.Test; @@ -31,6 +32,9 @@ class DistributionSetCreatedEventTest extends AbstractRemoteEntityEventTest { protected Rollout createEntity() { testdataFactory.createTarget("12345"); final SoftwareModule module = softwareModuleManagement.create( - entityFactory.softwareModule().create().name("swm").version("2").description("desc").type("os")); + SoftwareModuleManagement.Create.builder() + .type(softwareModuleTypeManagement.findByKey("os").orElseThrow()) + .name("swm").version("2").description("desc") + .build()); final DistributionSet ds = distributionSetManagement - .create(entityFactory.distributionSet().create().name("complete").version("2").description("complete") - .type("os").modules(Collections.singletonList(module.getId()))); + .create(DistributionSetManagement.Create.builder() + .type(distributionSetTypeManagement.findByKey("os").orElseThrow()) + .name("complete").version("2").description("complete") + .modules(Set.of(module)) + .build()); return rolloutManagement.create( entityFactory.rollout().create().name("exampleRollout").targetFilterQuery("controllerId==*").distributionSetId(ds), diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/RolloutGroupEventTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/RolloutGroupEventTest.java index c69242760..8c11aac79 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/RolloutGroupEventTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/event/remote/entity/RolloutGroupEventTest.java @@ -11,9 +11,11 @@ package org.eclipse.hawkbit.repository.event.remote.entity; import static org.assertj.core.api.Assertions.assertThat; -import java.util.List; +import java.util.Set; import java.util.UUID; +import org.eclipse.hawkbit.repository.DistributionSetManagement; +import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.RolloutGroup; @@ -79,12 +81,16 @@ class RolloutGroupEventTest extends AbstractRemoteEntityEventTest protected RolloutGroup createEntity() { testdataFactory.createTarget(UUID.randomUUID().toString()); final SoftwareModule module = softwareModuleManagement.create( - entityFactory.softwareModule().create().name("swm").version("2").description("desc").type("os")); + SoftwareModuleManagement.Create.builder() + .type(softwareModuleTypeManagement.findByKey("os").orElseThrow()) + .name("swm").version("2").description("desc") + .build()); final DistributionSet ds = distributionSetManagement - .create(entityFactory.distributionSet().create() - .name("complete").version("2") - .description("complete").type("os") - .modules(List.of(module.getId()))); + .create(DistributionSetManagement.Create.builder() + .type(distributionSetTypeManagement.findByKey("os").orElseThrow()) + .name("complete").version("2").description("complete") + .modules(Set.of(module)) + .build()); final Rollout entity = rolloutManagement.create( entityFactory.rollout().create().name("exampleRollout").targetFilterQuery("controllerId==*").distributionSetId(ds), diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java index f2812856d..95a0d08d7 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java @@ -176,16 +176,14 @@ public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest targets.stream().map(Target::getControllerId).toList(), tag.getId()); } - protected List assignTag(final Collection sets, + protected List assignTag(final Collection sets, final DistributionSetTag tag) { - return distributionSetManagement.assignTag( - sets.stream().map(DistributionSet::getId).toList(), tag.getId()); + return distributionSetManagement.assignTag(sets.stream().map(DistributionSet::getId).toList(), tag.getId()); } - protected List unassignTag(final Collection sets, - final DistributionSetTag tag) { - return distributionSetManagement.unassignTag( - sets.stream().map(DistributionSet::getId).toList(), tag.getId()); + protected List unassignTag( + final Collection sets, final DistributionSetTag tag) { + return distributionSetManagement.unassignTag(sets.stream().map(DistributionSet::getId).toList(), tag.getId()); } protected TargetTypeAssignmentResult initiateTypeAssignment(final Collection targets, final TargetType type) { @@ -278,7 +276,7 @@ public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest /** * Asserts that the given callable succeeds. - * + *

* Note: This method will assume that EntityNotFoundException is OK, as security tests use dummy (non-existing) IDs. * It matters to either callable succeeds without any exception or at most EntityNotFoundException. * All other cases will be considered as an error. @@ -288,7 +286,7 @@ public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest private void assertPermissionWorks(final Callable callable) { try { callable.call(); - } catch (Throwable th) { + } catch (final Throwable th) { if (th instanceof EntityNotFoundException) { log.info("Expected (at most) EntityNotFoundException catch: {}", th.getMessage()); } else { @@ -298,8 +296,7 @@ public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest } protected void finishAction(final Action action) { - controllerManagement - .addUpdateActionStatus(entityFactory.actionStatus().create(action.getId()).status(Action.Status.FINISHED)); + controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(action.getId()).status(Action.Status.FINISHED)); } protected Set getTargetTags(final String controllerId) { @@ -313,4 +310,4 @@ public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest private JpaRollout refresh(final Rollout rollout) { return rolloutRepository.findById(rollout.getId()).get(); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractRepositoryManagementSecurityTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractRepositoryManagementSecurityTest.java index 8d36046cf..095aa5188 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractRepositoryManagementSecurityTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractRepositoryManagementSecurityTest.java @@ -12,11 +12,13 @@ package org.eclipse.hawkbit.repository.jpa; import java.util.List; import org.eclipse.hawkbit.im.authentication.SpPermission; +import org.eclipse.hawkbit.repository.Identifiable; import org.eclipse.hawkbit.repository.RepositoryManagement; +import org.eclipse.hawkbit.repository.model.BaseEntity; import org.junit.jupiter.api.Test; import org.springframework.data.domain.Pageable; -public abstract class AbstractRepositoryManagementSecurityTest extends AbstractJpaIntegrationTest { +public abstract class AbstractRepositoryManagementSecurityTest> extends AbstractJpaIntegrationTest { /** * @return the repository management to test with @@ -127,5 +129,4 @@ public abstract class AbstractRepositoryManagementSecurityTest extends void findByRsqlPermissionCheck() { assertPermissions(() -> getRepositoryManagement().findByRsql("(name==*)", Pageable.ofSize(1)), List.of(SpPermission.READ_REPOSITORY)); } - -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/DistributionSetAccessControllerTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/DistributionSetAccessControllerTest.java index 2f47ce7a6..95c67d447 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/DistributionSetAccessControllerTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/acm/DistributionSetAccessControllerTest.java @@ -24,6 +24,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import org.eclipse.hawkbit.repository.DistributionSetTagManagement; import org.eclipse.hawkbit.repository.Identifiable; import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; @@ -184,8 +185,10 @@ class DistributionSetAccessControllerTest extends AbstractJpaIntegrationTest { final DistributionSet permitted = testdataFactory.createDistributionSet(); final DistributionSet readOnly = testdataFactory.createDistributionSet(); final DistributionSet hidden = testdataFactory.createDistributionSet(); - final Long dsTagId = distributionSetTagManagement.create(entityFactory.tag().create().name("dsTag")).getId(); - final Long dsTag2Id = distributionSetTagManagement.create(entityFactory.tag().create().name("dsTag2")).getId(); + final Long dsTagId = distributionSetTagManagement.create( + DistributionSetTagManagement.Create.builder().name("dsTag").build()).getId(); + final Long dsTag2Id = distributionSetTagManagement.create( + DistributionSetTagManagement.Create.builder().name("dsTag2").build()).getId(); // perform tag assignment before setting access rules distributionSetManagement.assignTag(Arrays.asList(permitted.getId(), readOnly.getId(), hidden.getId()), dsTagId); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerIntTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerIntTest.java index 642bcb994..893ca9b83 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerIntTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerIntTest.java @@ -21,6 +21,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import org.eclipse.hawkbit.repository.DeploymentManagement; +import org.eclipse.hawkbit.repository.DistributionSetManagement.Create; import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate; import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; @@ -251,8 +252,10 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest { void checkAutoAssignWithFailures() { // incomplete distribution set that will be assigned - final DistributionSet setF = distributionSetManagement.create(entityFactory.distributionSet().create() - .name("dsA").version("1").type(testdataFactory.findOrCreateDefaultTestDsType())); + final DistributionSet setF = distributionSetManagement.create(Create.builder() + .type(testdataFactory.findOrCreateDefaultTestDsType()) + .name("dsA").version("1") + .build()); final DistributionSet setA = testdataFactory.createDistributionSet("dsA"); final DistributionSet setB = testdataFactory.createDistributionSet("dsB"); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/event/RepositoryEntityEventTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/event/RepositoryEntityEventTest.java index 5a4dab49d..959939244 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/event/RepositoryEntityEventTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/event/RepositoryEntityEventTest.java @@ -16,6 +16,7 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import org.assertj.core.api.Assertions; +import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.event.TenantAwareEvent; import org.eclipse.hawkbit.repository.event.remote.DistributionSetDeletedEvent; import org.eclipse.hawkbit.repository.event.remote.RolloutDeletedEvent; @@ -211,7 +212,7 @@ class RepositoryEntityEventTest extends AbstractJpaIntegrationTest { void softwareModuleUpdateEventIsPublished() throws InterruptedException { final SoftwareModule softwareModule = testdataFactory.createSoftwareModuleApp(); softwareModuleManagement - .update(entityFactory.softwareModule().update(softwareModule.getId()).description("New")); + .update(SoftwareModuleManagement.Update.builder().id(softwareModule.getId()).description("New").build()); final SoftwareModuleUpdatedEvent softwareModuleUpdatedEvent = eventListener .waitForEvent(SoftwareModuleUpdatedEvent.class); @@ -267,5 +268,4 @@ class RepositoryEntityEventTest extends AbstractJpaIntegrationTest { return null; } } - -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementTest.java index 097b0f92d..caa02be83 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/ControllerManagementTest.java @@ -660,9 +660,9 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest { // create two artifacts with identical SHA1 hash final Artifact artifact = artifactManagement.create(new ArtifactUpload(new ByteArrayInputStream(random), - ds.findFirstModuleByType(osType).get().getId(), "file1", false, artifactSize)); + findFirstModuleByType(ds, osType).orElseThrow().getId(), "file1", false, artifactSize)); final Artifact artifact2 = artifactManagement.create(new ArtifactUpload(new ByteArrayInputStream(random), - ds2.findFirstModuleByType(osType).get().getId(), "file1", false, artifactSize)); + findFirstModuleByType(ds2, osType).orElseThrow().getId(), "file1", false, artifactSize)); assertThat(artifact.getSha1Hash()).isEqualTo(artifact2.getSha1Hash()); assertThat( diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DeploymentManagementSecurityTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DeploymentManagementSecurityTest.java index 219cd6df9..5531cb044 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DeploymentManagementSecurityTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DeploymentManagementSecurityTest.java @@ -15,6 +15,7 @@ import java.util.Set; import org.eclipse.hawkbit.im.authentication.SpPermission; import org.eclipse.hawkbit.im.authentication.SpRole; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; +import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.DeploymentRequest; import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation; @@ -291,8 +292,8 @@ class DeploymentManagementSecurityTest extends AbstractJpaIntegrationTest { @Test void cancelActionsForDistributionSetPermissionsCheck() { assertPermissions(() -> { - deploymentManagement.cancelActionsForDistributionSet(DistributionSetInvalidation.CancelationType.FORCE, - entityFactory.distributionSet().create().build()); + deploymentManagement.cancelActionsForDistributionSet( + DistributionSetInvalidation.CancelationType.FORCE, new JpaDistributionSet()); return null; }, List.of(SpPermission.UPDATE_TARGET)); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DeploymentManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DeploymentManagementTest.java index 722352c53..97ca327b6 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DeploymentManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DeploymentManagementTest.java @@ -33,6 +33,8 @@ import lombok.Getter; import org.assertj.core.api.Assertions; import org.eclipse.hawkbit.repository.ActionStatusFields; import org.eclipse.hawkbit.repository.DeploymentManagement; +import org.eclipse.hawkbit.repository.DistributionSetManagement; +import org.eclipse.hawkbit.repository.DistributionSetTagManagement; import org.eclipse.hawkbit.repository.event.remote.CancelTargetAssignmentEvent; import org.eclipse.hawkbit.repository.event.remote.MultiActionAssignEvent; import org.eclipse.hawkbit.repository.event.remote.MultiActionCancelEvent; @@ -129,7 +131,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { } /** - * Verifies that management get access react as specified on calls for non existing entities by means + * Verifies that management get access react as specified on calls for non existing entities by means * of Optional not present. */ @Test @@ -140,8 +142,8 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { } /** - * Verifies that management queries react as specified on calls for non existing entities - * by means of throwing EntityNotFoundException. + * Verifies that management queries react as specified on calls for non existing entities + * by means of throwing EntityNotFoundException. */ @Test @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1) }) @@ -298,7 +300,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { // not exists assignDS.add(100_000L); - final Long tagId = distributionSetTagManagement.create(entityFactory.tag().create().name("Tag1")).getId(); + final Long tagId = distributionSetTagManagement.create(DistributionSetTagManagement.Create.builder().name("Tag1").build()).getId(); assertThatExceptionOfType(EntityNotFoundException.class) .isThrownBy(() -> distributionSetManagement.assignTag(assignDS, tagId)) @@ -321,7 +323,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { @Expect(type = SoftwareModuleCreatedEvent.class, count = 6), @Expect(type = DistributionSetUpdatedEvent.class, count = 2), // implicit lock @Expect(type = SoftwareModuleUpdatedEvent.class, count = 6) }) - // implicit lock }) + // implicit lock void multiAssigmentHistoryOverMultiplePagesResultsInTwoActiveAction() { final DistributionSet cancelDs = testdataFactory.createDistributionSet("Canceled DS", "1.0", Collections.emptyList()); final DistributionSet cancelDs2 = testdataFactory.createDistributionSet("Canceled DS", "1.2", Collections.emptyList()); @@ -336,7 +338,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { } /** - * Cancels multiple active actions on a target. Expected behaviour is that with two active + * Cancels multiple active actions on a target. Expected behaviour is that with two active * After canceling the first one also the target goes back to IN_SYNC as no open action is left. */ @Test @@ -384,7 +386,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { } /** - * Cancels multiple active actions on a target. Expected behaviour is that with two active + * Cancels multiple active actions on a target. Expected behaviour is that with two active * also the target goes back to IN_SYNC as no open action is left. */ @Test @@ -497,7 +499,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { } /** - * Simple offline deployment of a distribution set to a list of targets. Verifies that offline assigment + * Simple offline deployment of a distribution set to a list of targets. Verifies that offline assigment * is correctly executed for targets that do not have a running update already. Those are ignored. */ @Test @@ -848,9 +850,9 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { .contains("Assignment initiated by user 'bumlux'") .contains(""" Assignment automatically confirmed by initiator 'not_bumlux'.\s - + Auto confirmation activated by system user: 'bumlux'\s - + Remark: my personal remark"""); } else { // assignment never required confirmation, auto-confirmation will not be @@ -1141,8 +1143,12 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { final SoftwareModule ah = testdataFactory.createSoftwareModuleApp(); final SoftwareModule os = testdataFactory.createSoftwareModuleOs(); - final DistributionSet incomplete = distributionSetManagement.create(entityFactory.distributionSet().create() - .name("incomplete").version("v1").type(standardDsType).modules(Collections.singletonList(ah.getId()))); + final DistributionSet incomplete = distributionSetManagement.create( + DistributionSetManagement.Create.builder() + .type(standardDsType) + .name("incomplete").version("v1") + .modules(Set.of(ah)) + .build()); assertThatExceptionOfType(IncompleteDistributionSetException.class) .as("expected IncompleteDistributionSetException") @@ -1156,7 +1162,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { } /** - * Multiple deployments or distribution set to target assignment test. Expected behaviour is that a new deployment + * Multiple deployments or distribution set to target assignment test. Expected behaviour is that a new deployment * overides unfinished old one which are canceled as part of the operation. */ @Test @@ -1222,7 +1228,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { } /** - * Multiple deployments or distribution set to target assignment test including finished response + * Multiple deployments or distribution set to target assignment test including finished response * IN_SYNC status and installed DS is set to the assigned DS entry. */ @Test @@ -1317,12 +1323,11 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { * or {@link Target#getInstalledDistributionSet()} */ /** - * Deletes distribution set. Expected behaviour is that a soft delete is performed + * Deletes distribution set. Expected behaviour is that a soft delete is performed * if the DS is assigned to a target and a hard delete if the DS is not in use at all. */ @Test void deleteDistributionSet() { - final PageRequest pageRequest = PageRequest.of(0, 100, Direction.ASC, "id"); final String undeployedTargetPrefix = "undep-T"; @@ -1351,7 +1356,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { } // verify that deleted attribute is used correctly - List allFoundDS = distributionSetManagement.findByCompleted(true, PAGE).getContent(); + List allFoundDS = distributionSetManagement.findByCompleted(true, PAGE).getContent(); assertThat(allFoundDS).as("no ds should be founded").isEmpty(); assertThat(distributionSetRepository.findAll(SpecificationsBuilder.combineWithAnd(Arrays @@ -1359,7 +1364,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { PAGE).getContent()).as("wrong size of founded ds").hasSize(noOfDistributionSets); IntStream.range(0, deploymentResult.getDistributionSets().size()).forEach(i -> testdataFactory.sendUpdateActionStatusToTargets( - deploymentResult.getDeployedTargets(), Status.FINISHED, Collections.singletonList("blabla alles gut"))); + deploymentResult.getDeployedTargets(), Status.FINISHED, Collections.singletonList("blabla alles gut"))); // try to delete again distributionSetManagement.delete(deploymentResult.getDistributionSetIDs()); @@ -1391,7 +1396,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { deployedTargetPrefix, noOfDeployedTargets, noOfDistributionSets, "myTestDS"); IntStream.range(0, deploymentResult.getDistributionSets().size()).forEach(i -> testdataFactory.sendUpdateActionStatusToTargets( - deploymentResult.getDeployedTargets(), Status.FINISHED, Collections.singletonList("blabla alles gut"))); + deploymentResult.getDeployedTargets(), Status.FINISHED, Collections.singletonList("blabla alles gut"))); assertThat(targetManagement.count()).as("size of targets is wrong").isNotZero(); assertThat(actionStatusRepository.count()).as("size of action status is wrong").isNotZero(); @@ -1479,7 +1484,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest { /** * The test verifies that the DS itself is not changed because of an target assignment - * which is a relationship but not a changed on the entity itself.. + * which is a relationship but not a changed on the entity itself.. */ @Test void checkThatDsRevisionsIsNotChangedWithTargetAssignment() { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetManagementSecurityTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetManagementSecurityTest.java index 6c1bc933f..c5aaa66be 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetManagementSecurityTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetManagementSecurityTest.java @@ -13,12 +13,12 @@ import java.util.List; import java.util.Map; import org.eclipse.hawkbit.im.authentication.SpPermission; -import org.eclipse.hawkbit.repository.RepositoryManagement; -import org.eclipse.hawkbit.repository.builder.DistributionSetCreate; -import org.eclipse.hawkbit.repository.builder.DistributionSetUpdate; +import org.eclipse.hawkbit.repository.DistributionSetManagement; +import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; import org.eclipse.hawkbit.repository.jpa.AbstractRepositoryManagementSecurityTest; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetFilter; +import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.junit.jupiter.api.Test; /** @@ -26,22 +26,22 @@ import org.junit.jupiter.api.Test; * Story: SecurityTests DistributionSetManagement */ class DistributionSetManagementSecurityTest - extends AbstractRepositoryManagementSecurityTest { + extends AbstractRepositoryManagementSecurityTest { @Override - protected RepositoryManagement getRepositoryManagement() { + protected DistributionSetManagement getRepositoryManagement() { return distributionSetManagement; } @Override - protected DistributionSetCreate getCreateObject() { - return entityFactory.distributionSet().create().name("name").version("1.0.0").type("type"); + protected DistributionSetManagement.Create getCreateObject() { + return DistributionSetManagement.Create.builder().name("name").version("1.0.0").type(defaultDsType()).build(); } @Override - protected DistributionSetUpdate getUpdateObject() { - return entityFactory.distributionSet().update(0L).name("a new name") - .description("a new description").version("a new version").requiredMigrationStep(true); + protected DistributionSetManagement.Update getUpdateObject() { + return DistributionSetManagement.Update.builder().id(0L).name("a new name") + .description("a new description").version("a new version").requiredMigrationStep(true).build(); } /** @@ -87,7 +87,7 @@ class DistributionSetManagementSecurityTest * Tests ManagementAPI PreAuthorized method with correct and insufficient permissions. */ @Test - void getMetadataPermissiosCheck() { + void getMetadataPermissionsCheck() { assertPermissions(() -> distributionSetManagement.getMetadata(1L), List.of(SpPermission.READ_REPOSITORY)); } @@ -97,7 +97,7 @@ class DistributionSetManagementSecurityTest @Test void updateMetadataPermissionsCheck() { assertPermissions(() -> { - distributionSetManagement.updateMetadata(1L,"key", "value"); + distributionSetManagement.updateMetadata(1L, "key", "value"); return null; }, List.of(SpPermission.UPDATE_REPOSITORY)); @@ -287,9 +287,12 @@ class DistributionSetManagementSecurityTest */ @Test void invalidatePermissionsCheck() { - distributionSetTypeManagement.create(entityFactory.distributionSetType().create().key("type").name("name")); + final DistributionSetType dsType = distributionSetTypeManagement.create(DistributionSetTypeManagement.Create.builder() + .key("type").name("name").build()); + final DistributionSet ds = distributionSetManagement.create(DistributionSetManagement.Create.builder() + .type(dsType).name("test").version("1.0.0").build()); assertPermissions(() -> { - distributionSetManagement.invalidate(entityFactory.distributionSet().create().name("name").version("1.0").type("type").build()); + ((DistributionSetManagement) distributionSetManagement).invalidate(ds); return null; }, List.of(SpPermission.UPDATE_REPOSITORY, SpPermission.READ_REPOSITORY)); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetManagementTest.java index f67a732e8..bf020cf66 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetManagementTest.java @@ -19,6 +19,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; @@ -30,9 +31,10 @@ import jakarta.validation.ConstraintViolationException; import org.assertj.core.api.Condition; import org.eclipse.hawkbit.repository.DistributionSetManagement; +import org.eclipse.hawkbit.repository.DistributionSetTagManagement; +import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; import org.eclipse.hawkbit.repository.RepositoryProperties; -import org.eclipse.hawkbit.repository.builder.DistributionSetCreate; -import org.eclipse.hawkbit.repository.builder.DistributionSetUpdate; +import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetTagCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetUpdatedEvent; @@ -96,7 +98,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { } /** - * Verifies that management queries react as specified on calls for non existing entities by means of + * Verifies that management queries react as specified on calls for non existing entities by means of * throwing EntityNotFoundException. */ @Test @@ -133,9 +135,6 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { verifyThrownExceptionBy(() -> distributionSetManagement.unassignTag(singletonList(NOT_EXIST_IDL), dsTag.getId()), "DistributionSet"); - verifyThrownExceptionBy(() -> distributionSetManagement.create( - entityFactory.distributionSet().create().name("xxx").type(NOT_EXIST_ID)), "DistributionSetType"); - verifyThrownExceptionBy(() -> distributionSetManagement.createMetadata(NOT_EXIST_IDL, Map.of("123", "123")), "DistributionSet"); verifyThrownExceptionBy(() -> distributionSetManagement.delete(singletonList(NOT_EXIST_IDL)), "DistributionSet"); @@ -154,10 +153,11 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { .hasMessageContaining("DistributionSet"); verifyThrownExceptionBy( - () -> distributionSetManagement.update(entityFactory.distributionSet().update(NOT_EXIST_IDL)), "DistributionSet"); + () -> distributionSetManagement.update(DistributionSetManagement.Update.builder().id(NOT_EXIST_IDL).build()), + "DistributionSet"); - verifyThrownExceptionBy(() -> distributionSetManagement.updateMetadata(NOT_EXIST_IDL,"xxx", "xxx"), "DistributionSet"); - verifyThrownExceptionBy(() -> distributionSetManagement.updateMetadata(set.getId(),NOT_EXIST_ID, "xxx"), "DistributionSet"); + verifyThrownExceptionBy(() -> distributionSetManagement.updateMetadata(NOT_EXIST_IDL, "xxx", "xxx"), "DistributionSet"); + verifyThrownExceptionBy(() -> distributionSetManagement.updateMetadata(set.getId(), NOT_EXIST_ID, "xxx"), "DistributionSet"); verifyThrownExceptionBy(() -> distributionSetManagement.getOrElseThrowException(NOT_EXIST_IDL), "DistributionSet"); @@ -199,7 +199,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { @Test void createDistributionSetWithImplicitType() { final DistributionSet set = distributionSetManagement - .create(entityFactory.distributionSet().create().name("newtypesoft").version("1")); + .create(DistributionSetManagement.Create.builder().type(defaultDsType()).name("newtypesoft").version("1").build()); assertThat(set.getType()) .as("Type should be equal to default type of tenant") @@ -212,7 +212,8 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { */ @Test void createDistributionSetWithDuplicateNameAndVersionFails() { - final DistributionSetCreate distributionSetCreate = entityFactory.distributionSet().create().name("newtypesoft").version("1"); + final DistributionSetManagement.Create distributionSetCreate = + DistributionSetManagement.Create.builder().type(defaultDsType()).name("newtypesoft").version("1").build(); distributionSetManagement.create(distributionSetCreate); assertThatExceptionOfType(EntityAlreadyExistsException.class).isThrownBy(() -> distributionSetManagement.create(distributionSetCreate)); @@ -223,14 +224,14 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { */ @Test void createMultipleDistributionSetsWithImplicitType() { - final List creates = new ArrayList<>(10); + final List creates = new ArrayList<>(10); for (int i = 0; i < 10; i++) { - creates.add(entityFactory.distributionSet().create().name("newtypesoft" + i).version("1" + i)); + creates.add(DistributionSetManagement.Create.builder().type(defaultDsType()).name("newtypesoft" + i).version("1" + i).build()); } assertThat(distributionSetManagement.create(creates)) .as("Type should be equal to default type of tenant") - .are(new Condition<>() { + .are(new Condition() { @Override public boolean matches(final DistributionSet value) { @@ -308,9 +309,10 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { assignDS.add(testdataFactory.createDistributionSet("DS" + i, "1.0", Collections.emptyList()).getId()); } - final DistributionSetTag tag = distributionSetTagManagement.create(entityFactory.tag().create().name(TAG1_NAME)); + final DistributionSetTag tag = distributionSetTagManagement.create( + DistributionSetTagManagement.Create.builder().name(TAG1_NAME).build()); - final List assignedDS = distributionSetManagement.assignTag(assignDS, tag.getId()); + final List assignedDS = distributionSetManagement.assignTag(assignDS, tag.getId()); assertThat(assignedDS).as("assigned ds has wrong size").hasSize(4); assignedDS.stream().map(JpaDistributionSet.class::cast).forEach(ds -> assertThat(ds.getTags()) .as("ds has wrong tag size") @@ -362,7 +364,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { .isInstanceOf(EntityReadOnlyException.class); // not allowed as it is assigned now - final Long appId = getOrThrow(ds.findFirstModuleByType(appType)).getId(); + final Long appId = getOrThrow(findFirstModuleByType(ds, appType)).getId(); assertThatThrownBy(() -> distributionSetManagement.unassignSoftwareModule(dsId, appId)) .isInstanceOf(EntityReadOnlyException.class); } @@ -373,17 +375,22 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { @Test void updateDistributionSetUnsupportedModuleFails() { final Long setId = distributionSetManagement.create( - entityFactory.distributionSet().create() + DistributionSetManagement.Create.builder() .type(distributionSetTypeManagement.create( - entityFactory.distributionSetType().create() + DistributionSetTypeManagement.Create.builder() .key("test") .name("test") - .mandatory(singletonList(osType.getId()))).getKey()) + .mandatoryModuleTypes(Set.of(osType)) + .build())) .name("agent-hub2") - .version("1.0.5")).getId(); + .version("1.0.5") + .build()).getId(); final Set moduleId = Set.of(softwareModuleManagement.create( - entityFactory.softwareModule().create().name("agent-hub2").version("1.0.5").type(appType.getKey())).getId()); + SoftwareModuleManagement.Create.builder() + .type(appType) + .name("agent-hub2").version("1.0.5") + .build()).getId()); // update data assertThatThrownBy(() -> distributionSetManagement.assignSoftwareModules(setId, moduleId)) @@ -403,17 +410,17 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { // legal update of module addition distributionSetManagement.assignSoftwareModules(ds.getId(), Set.of(os.getId())); ds = getOrThrow(distributionSetManagement.getWithDetails(ds.getId())); - assertThat(getOrThrow(ds.findFirstModuleByType(osType))).isEqualTo(os); + assertThat(getOrThrow(findFirstModuleByType(ds, osType))).isEqualTo(os); // legal update of module removal distributionSetManagement.unassignSoftwareModule(ds.getId(), - getOrThrow(ds.findFirstModuleByType(appType)).getId()); + getOrThrow(findFirstModuleByType(ds, appType)).getId()); ds = getOrThrow(distributionSetManagement.getWithDetails(ds.getId())); - assertThat(ds.findFirstModuleByType(appType)).isNotPresent(); + assertThat(findFirstModuleByType(ds, appType)).isNotPresent(); // Update description - distributionSetManagement.update(entityFactory.distributionSet().update(ds.getId()).name("a new name") - .description("a new description").version("a new version").requiredMigrationStep(true)); + distributionSetManagement.update(DistributionSetManagement.Update.builder().id(ds.getId()).name("a new name") + .description("a new description").version("a new version").requiredMigrationStep(true).build()); ds = getOrThrow(distributionSetManagement.getWithDetails(ds.getId())); assertThat(ds.getDescription()).isEqualTo("a new description"); assertThat(ds.getName()).isEqualTo("a new name"); @@ -428,7 +435,8 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { void updateInvalidDistributionSet() { final DistributionSet distributionSet = testdataFactory.createAndInvalidateDistributionSet(); - final DistributionSetUpdate update = entityFactory.distributionSet().update(distributionSet.getId()).name("new_name"); + final DistributionSetManagement.Update update = + DistributionSetManagement.Update.builder().id(distributionSet.getId()).name("new_name").build(); assertThatExceptionOfType(InvalidDistributionSetException.class) .as("Invalid distributionSet should throw an exception").isThrownBy(() -> distributionSetManagement.update(update)); } @@ -548,22 +556,23 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { @Test void searchDistributionSetsOnFilters() { DistributionSetTag dsTagA = distributionSetTagManagement - .create(entityFactory.tag().create().name("DistributionSetTag-A")); + .create(DistributionSetTagManagement.Create.builder().name("DistributionSetTag-A").build()); final DistributionSetTag dsTagB = distributionSetTagManagement - .create(entityFactory.tag().create().name("DistributionSetTag-B")); + .create(DistributionSetTagManagement.Create.builder().name("DistributionSetTag-B").build()); final DistributionSetTag dsTagC = distributionSetTagManagement - .create(entityFactory.tag().create().name("DistributionSetTag-C")); - distributionSetTagManagement.create(entityFactory.tag().create().name("DistributionSetTag-D")); + .create(DistributionSetTagManagement.Create.builder().name("DistributionSetTag-C").build()); + distributionSetTagManagement.create(DistributionSetTagManagement.Create.builder().name("DistributionSetTag-D").build()); - List dsGroup1 = testdataFactory.createDistributionSets("", 5); + List dsGroup1 = testdataFactory.createDistributionSets("", 5); final String dsGroup2Prefix = "test"; - List dsGroup2 = testdataFactory.createDistributionSets(dsGroup2Prefix, 5); + List dsGroup2 = testdataFactory.createDistributionSets(dsGroup2Prefix, 5); DistributionSet dsDeleted = testdataFactory.createDistributionSet("testDeleted"); - final DistributionSet dsInComplete = distributionSetManagement.create(entityFactory.distributionSet().create() - .name("notcomplete").version("1").type(standardDsType.getKey())); + final DistributionSet dsInComplete = distributionSetManagement.create( + DistributionSetManagement.Create.builder() + .name("notcomplete").version("1").type(standardDsType).build()); DistributionSetType newType = distributionSetTypeManagement - .create(entityFactory.distributionSetType().create().key("foo").name("bar").description("test")); + .create(DistributionSetTypeManagement.Create.builder().key("foo").name("bar").description("test").build()); distributionSetTypeManagement.assignMandatorySoftwareModuleTypes(newType.getId(), singletonList(osType.getId())); @@ -571,8 +580,11 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { Arrays.asList(appType.getId(), runtimeType.getId())); final DistributionSet dsNewType = distributionSetManagement.create( - entityFactory.distributionSet().create().name("newtype").version("1").type(newType.getKey()).modules( - dsDeleted.getModules().stream().map(SoftwareModule::getId).toList())); + DistributionSetManagement.Create.builder() + .type(newType) + .name("newtype").version("1") + .modules(new HashSet<>(dsDeleted.getModules())) + .build()); assignDistributionSet(dsDeleted, testdataFactory.createTargets(5)); distributionSetManagement.delete(dsDeleted.getId()); @@ -585,10 +597,10 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { dsGroup2 = assignTag(dsGroup2, dsTagA); dsTagA = getOrThrow(distributionSetTagRepository.findByNameEquals(dsTagA.getName())); - final List allDistributionSets = Stream + final List allDistributionSets = Stream .of(dsGroup1, dsGroup2, Arrays.asList(dsDeleted, dsInComplete, dsNewType)).flatMap(Collection::stream) .toList(); - final List dsGroup1WithGroup2 = Stream.of(dsGroup1, dsGroup2).flatMap(Collection::stream) + final List dsGroup1WithGroup2 = Stream.of(dsGroup1, dsGroup2).flatMap(Collection::stream) .toList(); final int sizeOfAllDistributionSets = allDistributionSets.size(); @@ -604,8 +616,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { validateDeletedAndCompleted(dsGroup1WithGroup2, dsNewType, dsDeleted); validateDeletedAndCompletedAndType(dsGroup1WithGroup2, dsDeleted, newType, dsNewType); validateDeletedAndCompletedAndTypeAndSearchText(dsGroup2, newType, dsGroup2Prefix); - validateDeletedAndCompletedAndTypeAndSearchText(dsGroup1WithGroup2, dsDeleted, dsInComplete, dsNewType, newType, - ":1"); + validateDeletedAndCompletedAndTypeAndSearchText(dsGroup1WithGroup2, dsDeleted, dsInComplete, dsNewType, newType, ":1"); validateDeletedAndCompletedAndTypeAndSearchTextAndTag(dsGroup2, dsTagA, dsGroup2Prefix); } @@ -729,21 +740,22 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { /** * Test implicit locks for a DS and skip tags. */ + @SuppressWarnings("rawtypes") @Test void isImplicitLockApplicableForDistributionSet() { - final JpaDistributionSetManagement distributionSetManagement = (JpaDistributionSetManagement) this.distributionSetManagement; + final JpaDistributionSetManagement distributionSetManagement = (JpaDistributionSetManagement) (DistributionSetManagement) this.distributionSetManagement; final DistributionSet distributionSet = testdataFactory.createDistributionSet("ds-non-skip"); // assert that implicit lock is applicable for non skip tags assertThat(distributionSetManagement.isImplicitLockApplicable(distributionSet)).isTrue(); assertThat(repositoryProperties.getSkipImplicitLockForTags().size()).isNotZero(); - final List skipTags = distributionSetTagManagement.create( + final List skipTags = distributionSetTagManagement.create( repositoryProperties.getSkipImplicitLockForTags().stream() .map(String::toLowerCase) // remove same in case-insensitive terms tags // in of case-insensitive db's it will end up as same names and constraint violation (?) .distinct() - .map(skipTag -> entityFactory.tag().create().name(skipTag)) + .map(skipTag -> (DistributionSetTagManagement.Create)DistributionSetTagManagement.Create.builder().name(skipTag).build()) .toList()); // assert that implicit lock locks for every skip tag skipTags.forEach(skipTag -> { @@ -829,7 +841,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { } /** - * Deletes a DS that is in use by either target assignment or rollout. Expected behaviour is a soft delete on the database, i.e. only marked as + * Deletes a DS that is in use by either target assignment or rollout. Expected behaviour is a soft delete on the database, i.e. only marked as * deleted, kept as reference but unavailable for future use.. */ @Test @@ -874,7 +886,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { testdataFactory.createDistributionSet("test" + i); } - final List foundDs = distributionSetManagement.get(searchIds); + final List foundDs = distributionSetManagement.get(searchIds); assertThat(foundDs).hasSize(3); @@ -1006,91 +1018,92 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { } private void createAndUpdateDistributionSetWithInvalidDescription(final DistributionSet set) { - final DistributionSetCreate distributionSetCreate = - entityFactory.distributionSet().create().name("a").version("a").description(randomString(513)); + final DistributionSetManagement.Create distributionSetCreate = + DistributionSetManagement.Create.builder().name("a").version("a").description(randomString(513)).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("entity with too long description should not be created") .isThrownBy(() -> distributionSetManagement.create(distributionSetCreate)); - final DistributionSetCreate distributionSetCreate2 = - entityFactory.distributionSet().create().name("a").version("a").description(INVALID_TEXT_HTML); + final DistributionSetManagement.Create distributionSetCreate2 = + DistributionSetManagement.Create.builder().name("a").version("a").description(INVALID_TEXT_HTML).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("entity with invalid description should not be created") .isThrownBy(() -> distributionSetManagement.create(distributionSetCreate2)); - final DistributionSetUpdate distributionSetUpdate = - entityFactory.distributionSet().update(set.getId()).description(randomString(513)); + final DistributionSetManagement.Update distributionSetUpdate = + DistributionSetManagement.Update.builder().id(set.getId()).description(randomString(513)).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("entity with too long description should not be updated") .isThrownBy(() -> distributionSetManagement.update(distributionSetUpdate)); - final DistributionSetUpdate distributionSetUpdate2 = entityFactory.distributionSet().update(set.getId()).description(INVALID_TEXT_HTML); + final DistributionSetManagement.Update distributionSetUpdate2 = + DistributionSetManagement.Update.builder().id(set.getId()).description(INVALID_TEXT_HTML).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("entity with invalid characters should not be updated") .isThrownBy(() -> distributionSetManagement.update(distributionSetUpdate2)); } private void createAndUpdateDistributionSetWithInvalidName(final DistributionSet set) { - final DistributionSetCreate distributionSetCreate = entityFactory.distributionSet().create() - .version("a").name(randomString(NamedEntity.NAME_MAX_SIZE + 1)); + final DistributionSetManagement.Create distributionSetCreate = DistributionSetManagement.Create.builder() + .version("a").name(randomString(NamedEntity.NAME_MAX_SIZE + 1)).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("entity with too long name should not be created") .isThrownBy(() -> distributionSetManagement.create(distributionSetCreate)); - final DistributionSetCreate distributionSetCreate2 = entityFactory.distributionSet().create().version("a").name(""); + final DistributionSetManagement.Create distributionSetCreate2 = DistributionSetManagement.Create.builder().version("a").name("").build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("entity with too short name should not be created") .isThrownBy(() -> distributionSetManagement.create(distributionSetCreate2)); - final DistributionSetCreate distributionSetCreate3 = entityFactory.distributionSet().create().version("a").name(INVALID_TEXT_HTML); + final DistributionSetManagement.Create distributionSetCreate3 = DistributionSetManagement.Create.builder().version("a").name(INVALID_TEXT_HTML).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("entity with invalid characters in name should not be created") .isThrownBy(() -> distributionSetManagement.create(distributionSetCreate3)); - final DistributionSetUpdate distributionSetUpdate = entityFactory.distributionSet().update(set.getId()) - .name(randomString(NamedEntity.NAME_MAX_SIZE + 1)); + final DistributionSetManagement.Update distributionSetUpdate = DistributionSetManagement.Update.builder().id(set.getId()) + .name(randomString(NamedEntity.NAME_MAX_SIZE + 1)).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("entity with too long name should not be updated") .isThrownBy(() -> distributionSetManagement.update(distributionSetUpdate)); - final DistributionSetUpdate distributionSetUpdate2 = entityFactory.distributionSet().update(set.getId()).name(INVALID_TEXT_HTML); + final DistributionSetManagement.Update distributionSetUpdate2 = DistributionSetManagement.Update.builder().id(set.getId()).name(INVALID_TEXT_HTML).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("entity with invalid characters should not be updated") .isThrownBy(() -> distributionSetManagement.update(distributionSetUpdate2)); - final DistributionSetUpdate distributionSetUpdate3 = entityFactory.distributionSet().update(set.getId()).name(""); + final DistributionSetManagement.Update distributionSetUpdate3 = DistributionSetManagement.Update.builder().id(set.getId()).name("").build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("entity with too short name should not be updated") .isThrownBy(() -> distributionSetManagement.update(distributionSetUpdate3)); } private void createAndUpdateDistributionSetWithInvalidVersion(final DistributionSet set) { - final DistributionSetCreate distributionSetCreate = entityFactory.distributionSet().create() - .name("a").version(randomString(NamedVersionedEntity.VERSION_MAX_SIZE + 1)); + final DistributionSetManagement.Create distributionSetCreate = DistributionSetManagement.Create.builder() + .name("a").version(randomString(NamedVersionedEntity.VERSION_MAX_SIZE + 1)).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("entity with too long version should not be created") .isThrownBy(() -> distributionSetManagement.create(distributionSetCreate)); - final DistributionSetCreate distributionSetCreate2 = entityFactory.distributionSet().create().name("a").version(""); + final DistributionSetManagement.Create distributionSetCreate2 = DistributionSetManagement.Create.builder().name("a").version("").build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("entity with too short version should not be created") .isThrownBy(() -> distributionSetManagement.create(distributionSetCreate2)); - final DistributionSetUpdate distributionSetUpdate = entityFactory.distributionSet().update(set.getId()) - .version(randomString(NamedVersionedEntity.VERSION_MAX_SIZE + 1)); + final DistributionSetManagement.Update distributionSetUpdate = DistributionSetManagement.Update.builder().id(set.getId()) + .version(randomString(NamedVersionedEntity.VERSION_MAX_SIZE + 1)).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("entity with too long version should not be updated") .isThrownBy(() -> distributionSetManagement.update(distributionSetUpdate)); - final DistributionSetUpdate distributionSetUpdate2 = entityFactory.distributionSet().update(set.getId()).version(""); + final DistributionSetManagement.Update distributionSetUpdate2 = DistributionSetManagement.Update.builder().id(set.getId()).version("").build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("entity with too short version should not be updated") .isThrownBy(() -> distributionSetManagement.update(distributionSetUpdate2)); } - private void validateFindAll(final List expectedDistributionsets) { + private void validateFindAll(final List expectedDistributionSets) { - assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder(), expectedDistributionsets); + assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder(), expectedDistributionSets); } private void validateDeleted(final DistributionSet deletedDistributionSet, final int notDeletedSize) { @@ -1119,51 +1132,44 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { DistributionSetFilter.builder().typeId(standardDsType.getId()), standardDsTypeSize, dsNewType); } - private void validateSearchText(final List allDistributionSets, final String dsNamePrefix) { - - final List withTestNamePrefix = allDistributionSets.stream() + private void validateSearchText(final List allDistributionSets, final String dsNamePrefix) { + final List withTestNamePrefix = allDistributionSets.stream() .filter(ds -> ds.getName().startsWith(dsNamePrefix)).toList(); assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().searchText(dsNamePrefix), withTestNamePrefix); - final List withTestNameExact = withTestNamePrefix.stream() + final List withTestNameExact = withTestNamePrefix.stream() .filter(ds -> ds.getName().equals(dsNamePrefix)).toList(); assertThatFilterContainsOnlyGivenDistributionSets( DistributionSetFilter.builder().searchText(dsNamePrefix + ":"), withTestNameExact); - final List withTestNameExactAndVersionPrefix = withTestNameExact.stream() + final List withTestNameExactAndVersionPrefix = withTestNameExact.stream() .filter(ds -> ds.getVersion().startsWith("1")).toList(); assertThatFilterContainsOnlyGivenDistributionSets( DistributionSetFilter.builder().searchText(dsNamePrefix + ":1"), withTestNameExactAndVersionPrefix); - final List dsWithExactNameAndVersion = withTestNameExactAndVersionPrefix.stream() + final List dsWithExactNameAndVersion = withTestNameExactAndVersionPrefix.stream() .filter(ds -> ds.getVersion().equals("1.0.0")).toList(); assertThat(dsWithExactNameAndVersion).hasSize(1); assertThatFilterContainsOnlyGivenDistributionSets( DistributionSetFilter.builder().searchText(dsNamePrefix + ":1.0.0"), dsWithExactNameAndVersion); - final List withVersionPrefix = allDistributionSets.stream() + final List withVersionPrefix = allDistributionSets.stream() .filter(ds -> ds.getVersion().startsWith("1.0.")).toList(); assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().searchText(":1.0."), withVersionPrefix); - final List withVersionExact = withVersionPrefix.stream() + final List withVersionExact = withVersionPrefix.stream() .filter(ds -> ds.getVersion().equals("1.0.0")).toList(); - assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().searchText(":1.0.0"), - withVersionExact); - - assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().searchText(":"), - allDistributionSets); - - assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().searchText(" : "), - allDistributionSets); + assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().searchText(":1.0.0"), withVersionExact); + assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().searchText(":"), allDistributionSets); + assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().searchText(" : "), allDistributionSets); } private void validateTags(final DistributionSetTag dsTagA, final DistributionSetTag dsTagB, - final DistributionSetTag dsTagC, final List dsWithTagA, - final List dsWithTagB) { - + final DistributionSetTag dsTagC, final List dsWithTagA, + final List dsWithTagB) { assertThatFilterContainsOnlyGivenDistributionSets( DistributionSetFilter.builder().tagNames(singletonList(dsTagA.getName())), dsWithTagA); @@ -1182,7 +1188,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { DistributionSetFilter.builder().tagNames(singletonList(dsTagC.getName()))); } - private void validateDeletedAndCompleted(final List completedStandardType, + private void validateDeletedAndCompleted(final List completedStandardType, final DistributionSet dsNewType, final DistributionSet dsDeleted) { final List completedNotDeleted = new ArrayList<>(completedStandardType); @@ -1199,7 +1205,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { DistributionSetFilter.builder().isComplete(Boolean.FALSE).isDeleted(Boolean.TRUE)); } - private void validateDeletedAndCompletedAndType(final List deletedAndCompletedAndStandardType, + private void validateDeletedAndCompletedAndType(final List deletedAndCompletedAndStandardType, final DistributionSet dsDeleted, final DistributionSetType newType, final DistributionSet dsNewType) { assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().isDeleted(Boolean.FALSE) .isComplete(Boolean.TRUE).typeId(standardDsType.getId()), deletedAndCompletedAndStandardType); @@ -1213,9 +1219,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { } private void validateDeletedAndCompletedAndTypeAndSearchText( - final List completedAndStandardTypeAndSearchText, final DistributionSetType newType, - final String text) { - + final List completedAndStandardTypeAndSearchText, final DistributionSetType newType, final String text) { assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().isDeleted(Boolean.FALSE) .isComplete(Boolean.TRUE).typeId(standardDsType.getId()).searchText(text), completedAndStandardTypeAndSearchText); @@ -1232,7 +1236,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { } private void validateDeletedAndCompletedAndTypeAndSearchText( - final List completedAndNotDeletedStandardTypeAndFilterString, + final List completedAndNotDeletedStandardTypeAndFilterString, final DistributionSet dsDeleted, final DistributionSet dsInComplete, final DistributionSet dsNewType, final DistributionSetType newType, final String filterString) { @@ -1263,9 +1267,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { } private void validateDeletedAndCompletedAndTypeAndSearchTextAndTag( - final List completedAndStandartTypeAndSearchTextAndTagA, final DistributionSetTag dsTagA, - final String text) { - + final List completedAndStandartTypeAndSearchTextAndTagA, final DistributionSetTag dsTagA, final String text) { assertThatFilterContainsOnlyGivenDistributionSets( DistributionSetFilter.builder().isComplete(Boolean.TRUE).typeId(standardDsType.getId()) .searchText(text).tagNames(singletonList(dsTagA.getName())), @@ -1282,9 +1284,9 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { } private void assertThatFilterContainsOnlyGivenDistributionSets(final DistributionSetFilterBuilder filterBuilder, - final List distributionSets) { + final List distributionSets) { final int expectedDsSize = distributionSets.size(); - assertThat(distributionSetManagement.findByDistributionSetFilter(filterBuilder.build(), PAGE).getContent()) + assertThat(((DistributionSetManagement)distributionSetManagement).findByDistributionSetFilter(filterBuilder.build(), PAGE).getContent()) .hasSize(expectedDsSize).containsOnly(distributionSets.toArray(new DistributionSet[expectedDsSize])); } @@ -1295,7 +1297,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest { private void assertThatFilterHasSizeAndDoesNotContainDistributionSet( final DistributionSetFilterBuilder filterBuilder, final int size, final DistributionSet ds) { - assertThat(distributionSetManagement.findByDistributionSetFilter(filterBuilder.build(), PAGE).getContent()) + assertThat(((DistributionSetManagement)distributionSetManagement).findByDistributionSetFilter(filterBuilder.build(), PAGE).getContent()) .hasSize(size).doesNotContain(ds); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetTagManagementSecurityTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetTagManagementSecurityTest.java index f74be68ab..1c7c0ee08 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetTagManagementSecurityTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetTagManagementSecurityTest.java @@ -13,9 +13,8 @@ import java.util.List; import java.util.Random; import org.eclipse.hawkbit.im.authentication.SpPermission; +import org.eclipse.hawkbit.repository.DistributionSetTagManagement; import org.eclipse.hawkbit.repository.RepositoryManagement; -import org.eclipse.hawkbit.repository.builder.TagCreate; -import org.eclipse.hawkbit.repository.builder.TagUpdate; import org.eclipse.hawkbit.repository.jpa.AbstractRepositoryManagementSecurityTest; import org.eclipse.hawkbit.repository.model.DistributionSetTag; import org.junit.jupiter.api.Test; @@ -25,21 +24,22 @@ import org.springframework.data.domain.Pageable; * Feature: SecurityTests - DistributionSetTagManagement
* Story: SecurityTests DistributionSetTagManagement */ -class DistributionSetTagManagementSecurityTest extends AbstractRepositoryManagementSecurityTest { +class DistributionSetTagManagementSecurityTest + extends AbstractRepositoryManagementSecurityTest { @Override - protected RepositoryManagement getRepositoryManagement() { + protected RepositoryManagement getRepositoryManagement() { return distributionSetTagManagement; } @Override - protected TagCreate getCreateObject() { - return entityFactory.tag().create().name(String.format("tag-%d", new Random().nextInt())); + protected DistributionSetTagManagement.Create getCreateObject() { + return DistributionSetTagManagement.Create.builder().name(String.format("tag-%d", new Random().nextInt())).build(); } @Override - protected TagUpdate getUpdateObject() { - return entityFactory.tag().update(1L).name("tag"); + protected DistributionSetTagManagement.Update getUpdateObject() { + return DistributionSetTagManagement.Update.builder().id(1L).name("tag").build(); } /** diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetTagManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetTagManagementTest.java index c3705e0f2..0dd1d7012 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetTagManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetTagManagementTest.java @@ -22,8 +22,6 @@ import java.util.Random; import java.util.stream.Stream; import org.eclipse.hawkbit.repository.DistributionSetTagManagement; -import org.eclipse.hawkbit.repository.builder.TagCreate; -import org.eclipse.hawkbit.repository.builder.TagUpdate; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetTagUpdatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.TargetTagUpdatedEvent; @@ -60,7 +58,7 @@ class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest { } /** - * Verifies that management queries react as specified on calls for non existing entities by means of throwing + * Verifies that management queries react as specified on calls for non existing entities by means of throwing * EntityNotFoundException. */ @Test @@ -69,10 +67,9 @@ class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest { @Expect(type = TargetTagUpdatedEvent.class, count = 0) }) void entityQueriesReferringToNotExistingEntitiesThrowsException() { verifyThrownExceptionBy(() -> distributionSetTagManagement.delete(NOT_EXIST_ID), "DistributionSetTag"); - verifyThrownExceptionBy(() -> distributionSetTagManagement.findByDistributionSet(NOT_EXIST_IDL, PAGE), - "DistributionSet"); - verifyThrownExceptionBy(() -> distributionSetTagManagement.update(entityFactory.tag().update(NOT_EXIST_IDL)), - "DistributionSetTag"); + verifyThrownExceptionBy(() -> distributionSetTagManagement.findByDistributionSet(NOT_EXIST_IDL, PAGE), "DistributionSet"); + verifyThrownExceptionBy(() -> distributionSetTagManagement.update( + DistributionSetTagManagement.Update.builder().id(NOT_EXIST_IDL).build()), "DistributionSetTag"); } /** @@ -88,11 +85,11 @@ class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest { final Collection dsBCs = testdataFactory.createDistributionSets("DS-BC", 13); final Collection dsABCs = testdataFactory.createDistributionSets("DS-ABC", 9); - final DistributionSetTag tagA = distributionSetTagManagement.create(entityFactory.tag().create().name("A")); - final DistributionSetTag tagB = distributionSetTagManagement.create(entityFactory.tag().create().name("B")); - final DistributionSetTag tagC = distributionSetTagManagement.create(entityFactory.tag().create().name("C")); - final DistributionSetTag tagX = distributionSetTagManagement.create(entityFactory.tag().create().name("X")); - final DistributionSetTag tagY = distributionSetTagManagement.create(entityFactory.tag().create().name("Y")); + final DistributionSetTag tagA = distributionSetTagManagement.create(DistributionSetTagManagement.Create.builder().name("A").build()); + final DistributionSetTag tagB = distributionSetTagManagement.create(DistributionSetTagManagement.Create.builder().name("B").build()); + final DistributionSetTag tagC = distributionSetTagManagement.create(DistributionSetTagManagement.Create.builder().name("C").build()); + final DistributionSetTag tagX = distributionSetTagManagement.create(DistributionSetTagManagement.Create.builder().name("X").build()); + final DistributionSetTag tagY = distributionSetTagManagement.create(DistributionSetTagManagement.Create.builder().name("Y").build()); assignTag(dsAs, tagA); assignTag(dsBs, tagB); @@ -148,13 +145,13 @@ class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest { final Collection groupB = testdataFactory.createDistributionSets("unassigned", 20); final DistributionSetTag tag = distributionSetTagManagement - .create(entityFactory.tag().create().name("tag1").description("tagdesc1")); + .create(DistributionSetTagManagement.Create.builder().name("tag1").description("tagdesc1").build()); // toggle A only -> A is now assigned - List result = assignTag(groupA, tag); + List result = assignTag(groupA, tag); assertThat(result) .hasSize(20) - .containsAll(distributionSetManagement.get(groupA.stream().map(DistributionSet::getId).toList())); + .containsAll((Collection) distributionSetManagement.get(groupA.stream().map(DistributionSet::getId).toList())); assertThat( distributionSetManagement.findByTag(tag.getId(), Pageable.unpaged()).getContent().stream() .map(DistributionSet::getId) @@ -165,7 +162,7 @@ class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest { final Collection groupAB = concat(groupA, groupB); // toggle A+B -> A is still assigned and B is assigned as well result = assignTag(groupAB, tag); - assertThat(result) + assertThat((List) result) .hasSize(40) .containsAll(distributionSetManagement.get(groupAB.stream().map(DistributionSet::getId).toList())); assertThat( @@ -177,7 +174,7 @@ class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest { result = unassignTag(concat(groupA, groupB), tag); assertThat(result) .hasSize(40) - .containsAll(distributionSetManagement.get(concat(groupB, groupA).stream().map(DistributionSet::getId).toList())); + .containsAll((List) distributionSetManagement.get(concat(groupB, groupA).stream().map(DistributionSet::getId).toList())); assertThat(distributionSetManagement.findByTag(tag.getId(), Pageable.unpaged()).getContent()).isEmpty(); } @@ -187,7 +184,8 @@ class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest { @Test void failOnMissingDs() { final Collection group = testdataFactory.createDistributionSets(5).stream().map(DistributionSet::getId).toList(); - final DistributionSetTag tag = distributionSetTagManagement.create(entityFactory.tag().create().name("tag1").description("tagdesc1")); + final DistributionSetTag tag = distributionSetTagManagement.create( + DistributionSetTagManagement.Create.builder().name("tag1").description("tagdesc1").build()); final List missing = new ArrayList<>(); for (int i = 0; i < 5; i++) { while (true) { @@ -217,7 +215,7 @@ class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest { @Test void createDistributionSetTag() { final Tag tag = distributionSetTagManagement - .create(entityFactory.tag().create().name("kai1").description("kai2").colour("colour")); + .create(DistributionSetTagManagement.Create.builder().name("kai1").description("kai2").colour("colour").build()); assertThat(distributionSetTagRepository.findByNameEquals("kai1").get().getDescription()).as("wrong tag found") .isEqualTo("kai2"); @@ -261,7 +259,7 @@ class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest { */ @Test void failedDuplicateDsTagNameException() { - final TagCreate tag = entityFactory.tag().create().name("A"); + final DistributionSetTagManagement.Create tag = DistributionSetTagManagement.Create.builder().name("A").build(); distributionSetTagManagement.create(tag); assertThatExceptionOfType(EntityAlreadyExistsException.class).as("should not have worked as tag already exists") @@ -273,10 +271,10 @@ class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest { */ @Test void failedDuplicateDsTagNameExceptionAfterUpdate() { - distributionSetTagManagement.create(entityFactory.tag().create().name("A")); - final DistributionSetTag tag = distributionSetTagManagement.create(entityFactory.tag().create().name("B")); + distributionSetTagManagement.create(DistributionSetTagManagement.Create.builder().name("A").build()); + final DistributionSetTag tag = distributionSetTagManagement.create(DistributionSetTagManagement.Create.builder().name("B").build()); - final TagUpdate tagUpdate = entityFactory.tag().update(tag.getId()).name("A"); + final DistributionSetTagManagement.Update tagUpdate = DistributionSetTagManagement.Update.builder().id(tag.getId()).name("A").build(); assertThatExceptionOfType(EntityAlreadyExistsException.class).as("should not have worked as tag already exists") .isThrownBy(() -> distributionSetTagManagement.update(tagUpdate)); } @@ -291,7 +289,7 @@ class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest { // change data final DistributionSetTag savedAssigned = tags.iterator().next(); // persist - distributionSetTagManagement.update(entityFactory.tag().update(savedAssigned.getId()).name("test123")); + distributionSetTagManagement.update(DistributionSetTagManagement.Update.builder().id(savedAssigned.getId()).name("test123").build()); // check data assertThat(distributionSetTagManagement.findAll(PAGE).getContent()).as("Wrong size of ds tags") .hasSize(tags.size()); @@ -337,7 +335,7 @@ class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest { tags.forEach(tag -> assignTag(sets, tag)); - return distributionSetTagManagement.findAll(PAGE).getContent(); + return distributionSetTagManagement.findAll(PAGE).getContent().stream().map(DistributionSetTag.class::cast).toList(); } private DistributionSetFilter.DistributionSetFilterBuilder getDistributionSetFilterBuilder() { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetTypeManagementSecurityTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetTypeManagementSecurityTest.java index e03dd60a4..6dc7e5da2 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetTypeManagementSecurityTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetTypeManagementSecurityTest.java @@ -13,9 +13,8 @@ import java.util.List; import java.util.Random; import org.eclipse.hawkbit.im.authentication.SpPermission; +import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; import org.eclipse.hawkbit.repository.RepositoryManagement; -import org.eclipse.hawkbit.repository.builder.DistributionSetTypeCreate; -import org.eclipse.hawkbit.repository.builder.DistributionSetTypeUpdate; import org.eclipse.hawkbit.repository.jpa.AbstractRepositoryManagementSecurityTest; import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.junit.jupiter.api.Test; @@ -25,21 +24,21 @@ import org.junit.jupiter.api.Test; * Story: SecurityTests DistributionSetTypeManagement */ class DistributionSetTypeManagementSecurityTest - extends AbstractRepositoryManagementSecurityTest { + extends AbstractRepositoryManagementSecurityTest { @Override - protected RepositoryManagement getRepositoryManagement() { + protected RepositoryManagement getRepositoryManagement() { return distributionSetTypeManagement; } @Override - protected DistributionSetTypeCreate getCreateObject() { - return entityFactory.distributionSetType().create().key(String.format("key-%d", new Random().nextInt())).name(String.format("name-%d", new Random().nextInt())); + protected DistributionSetTypeManagement.Create getCreateObject() { + return DistributionSetTypeManagement.Create.builder().key(String.format("key-%d", new Random().nextInt())).name(String.format("name-%d", new Random().nextInt())).build(); } @Override - protected DistributionSetTypeUpdate getUpdateObject() { - return entityFactory.distributionSetType().update(1L).description("description"); + protected DistributionSetTypeManagement.Update getUpdateObject() { + return DistributionSetTypeManagement.Update.builder().id(1L).description("description").build(); } /** @@ -83,4 +82,4 @@ class DistributionSetTypeManagementSecurityTest void unassignSoftwareModuleTypePermissionsCheck() { assertPermissions(() -> distributionSetTypeManagement.unassignSoftwareModuleType(1L, 1L), List.of(SpPermission.UPDATE_REPOSITORY)); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetTypeManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetTypeManagementTest.java index 392be06e3..216678e39 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetTypeManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetTypeManagementTest.java @@ -22,9 +22,8 @@ import java.util.Set; import jakarta.validation.ConstraintViolationException; import org.eclipse.hawkbit.repository.DistributionSetManagement; -import org.eclipse.hawkbit.repository.builder.DistributionSetCreate; -import org.eclipse.hawkbit.repository.builder.DistributionSetUpdate; -import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeCreate; +import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; +import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetTypeCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetUpdatedEvent; @@ -90,8 +89,8 @@ class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTest { verifyThrownExceptionBy(() -> distributionSetTypeManagement.delete(NOT_EXIST_IDL), "DistributionSetType"); verifyThrownExceptionBy( - () -> distributionSetTypeManagement.update(entityFactory.distributionSetType().update(NOT_EXIST_IDL)), - "DistributionSet"); + () -> distributionSetTypeManagement.update(DistributionSetTypeManagement.Update.builder().id(NOT_EXIST_IDL).build()), + "DistributionSetType"); } /** @@ -116,7 +115,7 @@ class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTest { @Test void updateUnassignedDistributionSetTypeModules() { final DistributionSetType updatableType = distributionSetTypeManagement - .create(entityFactory.distributionSetType().create().key("updatableType").name("to be deleted")); + .create(DistributionSetTypeManagement.Create.builder().key("updatableType").name("to be deleted").build()); assertThat(distributionSetTypeManagement.findByKey("updatableType").get().getMandatoryModuleTypes()).isEmpty(); // add OS @@ -146,14 +145,14 @@ class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTest { // create software module types final List moduleTypeIds = new ArrayList<>(); for (int i = 0; i < quota + 1; ++i) { - final SoftwareModuleTypeCreate smCreate = entityFactory.softwareModuleType().create().name("smType_" + i) - .description("smType_" + i).maxAssignments(1).colour("blue").key("smType_" + i); + final SoftwareModuleTypeManagement.Create smCreate = SoftwareModuleTypeManagement.Create.builder().name("smType_" + i) + .description("smType_" + i).maxAssignments(1).colour("blue").key("smType_" + i).build(); moduleTypeIds.add(softwareModuleTypeManagement.create(smCreate).getId()); } // assign all types at once final DistributionSetType dsType1 = distributionSetTypeManagement - .create(entityFactory.distributionSetType().create().key("dst1").name("dst1")); + .create(DistributionSetTypeManagement.Create.builder().key("dst1").name("dst1").build()); final Long dsType1Id = dsType1.getId(); assertThatExceptionOfType(AssignmentQuotaExceededException.class) .isThrownBy(() -> distributionSetTypeManagement.assignMandatorySoftwareModuleTypes(dsType1Id, moduleTypeIds)); @@ -162,7 +161,7 @@ class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTest { // assign as many mandatory modules as possible final DistributionSetType dsType2 = distributionSetTypeManagement - .create(entityFactory.distributionSetType().create().key("dst2").name("dst2")); + .create(DistributionSetTypeManagement.Create.builder().key("dst2").name("dst2").build()); final Long dsType2Id = dsType2.getId(); distributionSetTypeManagement.assignMandatorySoftwareModuleTypes(dsType2Id, moduleTypeIds.subList(0, quota)); @@ -175,7 +174,7 @@ class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTest { // assign as many optional modules as possible final DistributionSetType dsType3 = distributionSetTypeManagement - .create(entityFactory.distributionSetType().create().key("dst3").name("dst3")); + .create(DistributionSetTypeManagement.Create.builder().key("dst3").name("dst3").build()); final Long dsType3Id = dsType3.getId(); distributionSetTypeManagement.assignOptionalSoftwareModuleTypes(dsType3Id, moduleTypeIds.subList(0, quota)); assertThat(distributionSetTypeManagement.get(dsType3Id)).isNotEmpty(); @@ -194,11 +193,10 @@ class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTest { final DistributionSetType nonUpdatableType = createDistributionSetTypeUsedByDs(); distributionSetTypeManagement.update( - entityFactory.distributionSetType().update(nonUpdatableType.getId()).description("a new description")); + DistributionSetTypeManagement.Update.builder().id(nonUpdatableType.getId()).description("a new description").build()); - assertThat(distributionSetTypeManagement.findByKey("updatableType").get().getDescription()) - .isEqualTo("a new description"); - assertThat(distributionSetTypeManagement.findByKey("updatableType").get().getColour()).isEqualTo("test123"); + assertThat(distributionSetTypeManagement.findByKey("updatableType").orElseThrow().getDescription()).isEqualTo("a new description"); + assertThat(distributionSetTypeManagement.findByKey("updatableType").orElseThrow().getColour()).isEqualTo("test123"); } /** @@ -219,13 +217,13 @@ class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTest { @Test void removeModuleToAssignedDistributionSetTypeFails() { DistributionSetType nonUpdatableType = distributionSetTypeManagement - .create(entityFactory.distributionSetType().create().key("updatableType").name("to be deleted")); + .create(DistributionSetTypeManagement.Create.builder().key("updatableType").name("to be deleted").build()); assertThat(distributionSetTypeManagement.findByKey("updatableType").get().getMandatoryModuleTypes()).isEmpty(); final Long osTypeId = osType.getId(); nonUpdatableType = distributionSetTypeManagement.assignMandatorySoftwareModuleTypes(nonUpdatableType.getId(), Set.of(osTypeId)); distributionSetManagement.create( - entityFactory.distributionSet().create().name("newtypesoft").version("1").type(nonUpdatableType.getKey())); + DistributionSetManagement.Create.builder().type(nonUpdatableType).name("newtypesoft").version("1").build()); final Long typeId = nonUpdatableType.getId(); assertThatThrownBy(() -> distributionSetTypeManagement.unassignSoftwareModuleType(typeId, osTypeId)) @@ -238,7 +236,7 @@ class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTest { @Test void deleteUnassignedDistributionSetType() { final JpaDistributionSetType hardDelete = (JpaDistributionSetType) distributionSetTypeManagement - .create(entityFactory.distributionSetType().create().key("delete").name("to be deleted")); + .create(DistributionSetTypeManagement.Create.builder().key("delete").name("to be deleted").build()); assertThat(distributionSetTypeRepository.findAll()).contains(hardDelete); distributionSetTypeManagement.delete(hardDelete.getId()); @@ -253,16 +251,16 @@ class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTest { void deleteAssignedDistributionSetType() { final int existing = (int) distributionSetTypeManagement.count(); final JpaDistributionSetType toBeDeleted = (JpaDistributionSetType) distributionSetTypeManagement - .create(entityFactory.distributionSetType().create().key("softdeleted").name("to be deleted")); + .create(DistributionSetTypeManagement.Create.builder().key("softdeleted").name("to be deleted").build()); assertThat(distributionSetTypeRepository.findAll()).contains(toBeDeleted); distributionSetManagement.create( - entityFactory.distributionSet().create().name("softdeleted").version("1").type(toBeDeleted.getKey())); + DistributionSetManagement.Create.builder().type(toBeDeleted).name("softdeleted").version("1").build()); distributionSetTypeManagement.delete(toBeDeleted.getId()); - final Optional softdeleted = distributionSetTypeManagement.findByKey("softdeleted"); - assertThat(softdeleted).isPresent(); - assertThat(softdeleted.get().isDeleted()).isTrue(); + final Optional softDeleted = distributionSetTypeManagement.findByKey("softdeleted"); + assertThat(softDeleted).isPresent(); + assertThat(softDeleted.get().isDeleted()).isTrue(); assertThat(distributionSetTypeManagement.findAll(PAGE)).hasSize(existing); assertThat(distributionSetTypeManagement.findByRsql("name==*", PAGE)).hasSize(existing); assertThat(distributionSetTypeManagement.count()).isEqualTo(existing); @@ -273,9 +271,8 @@ class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTest { */ @Test void shouldFailWhenDistributionSetHasNoSoftwareModulesAssigned() { - final JpaDistributionSetType jpaDistributionSetType = (JpaDistributionSetType) distributionSetTypeManagement - .create(entityFactory.distributionSetType().create().key("newType").name("new Type")); + .create(DistributionSetTypeManagement.Create.builder().key("newType").name("new Type").build()); final List softwareModules = new ArrayList<>(); @@ -286,103 +283,113 @@ class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTest { } private void createAndUpdateDistributionSetWithInvalidDescription(final DistributionSet set) { - final DistributionSetCreate distributionSetCreate = entityFactory.distributionSet().create() - .name("a").version("a").description(randomString(513)); + final DistributionSetManagement.Create distributionSetCreate = DistributionSetManagement.Create.builder() + .name("a").version("a").description(randomString(513)).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("set with too long description should not be created") .isThrownBy(() -> distributionSetManagement.create(distributionSetCreate)); - final DistributionSetCreate distributionSetCreate2 = entityFactory.distributionSet().create() - .name("a").version("a").description(INVALID_TEXT_HTML); + final DistributionSetManagement.Create distributionSetCreate2 = DistributionSetManagement.Create.builder() + .name("a").version("a").description(INVALID_TEXT_HTML).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("set invalid description text should not be created") .isThrownBy(() -> distributionSetManagement.create(distributionSetCreate2)); - final DistributionSetUpdate distributionSetUpdate = entityFactory.distributionSet().update(set.getId()) - .description(randomString(513)); + final DistributionSetManagement.Update distributionSetUpdate = DistributionSetManagement.Update.builder().id(set.getId()) + .description(randomString(513)).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("set with too long description should not be updated") .isThrownBy(() -> distributionSetManagement.update(distributionSetUpdate)); - final DistributionSetUpdate distributionSetUpdate2 = entityFactory.distributionSet().update(set.getId()).description(INVALID_TEXT_HTML); + final DistributionSetManagement.Update distributionSetUpdate2 = DistributionSetManagement.Update.builder().id(set.getId()).description(INVALID_TEXT_HTML).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("set with invalid description should not be updated") .isThrownBy(() -> distributionSetManagement.update(distributionSetUpdate2)); } private void createAndUpdateDistributionSetWithInvalidName(final DistributionSet set) { - final DistributionSetCreate distributionSetCreate = entityFactory.distributionSet().create() - .version("a").name(randomString(NamedEntity.NAME_MAX_SIZE + 1)); + final DistributionSetManagement.Create distributionSetCreate = DistributionSetManagement.Create.builder() + .version("a").name(randomString(NamedEntity.NAME_MAX_SIZE + 1)).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("set with too long name should not be created") .isThrownBy(() -> distributionSetManagement.create(distributionSetCreate)); - final DistributionSetCreate distributionSetCreate2 = entityFactory.distributionSet().create().version("a").name(INVALID_TEXT_HTML); + final DistributionSetManagement.Create distributionSetCreate2 = + DistributionSetManagement.Create.builder().version("a").name(INVALID_TEXT_HTML).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("set with invalid name should not be created") .isThrownBy(() -> distributionSetManagement.create(distributionSetCreate2)); - final DistributionSetCreate distributionSetCreate3 = entityFactory.distributionSet().create().version("a").name(""); + final DistributionSetManagement.Create distributionSetCreate3 = + DistributionSetManagement.Create.builder().version("a").name("").build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("set with too short name should not be created") .isThrownBy(() -> distributionSetManagement.create(distributionSetCreate3)); - final DistributionSetCreate distributionSetCreate4 = entityFactory.distributionSet().create().version("a").name(null); + final DistributionSetManagement.Create distributionSetCreate4 = + DistributionSetManagement.Create.builder().version("a").name(null).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("set with null name should not be created") .isThrownBy(() -> distributionSetManagement.create(distributionSetCreate4)); - final DistributionSetUpdate distributionSetUpdate = entityFactory.distributionSet().update(set.getId()) - .name(randomString(NamedEntity.NAME_MAX_SIZE + 1)); + final DistributionSetManagement.Update distributionSetUpdate = DistributionSetManagement.Update.builder().id(set.getId()) + .name(randomString(NamedEntity.NAME_MAX_SIZE + 1)).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("set with too long name should not be updated") .isThrownBy(() -> distributionSetManagement.update(distributionSetUpdate)); - final DistributionSetUpdate distributionSetUpdate2 = entityFactory.distributionSet().update(set.getId()).name(INVALID_TEXT_HTML); + final DistributionSetManagement.Update distributionSetUpdate2 = + DistributionSetManagement.Update.builder().id(set.getId()).name(INVALID_TEXT_HTML).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("set with invalid name should not be updated") .isThrownBy(() -> distributionSetManagement.update(distributionSetUpdate2)); - final DistributionSetUpdate distributionSetUpdate3 = entityFactory.distributionSet().update(set.getId()).name(""); + final DistributionSetManagement.Update distributionSetUpdate3 = + DistributionSetManagement.Update.builder().id(set.getId()).name("").build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("set with too short name should not be updated") .isThrownBy(() -> distributionSetManagement.update(distributionSetUpdate3)); } private void createAndUpdateDistributionSetWithInvalidVersion(final DistributionSet set) { - final DistributionSetCreate distributionSetCreate = entityFactory.distributionSet().create() - .name("a").version(randomString(NamedVersionedEntity.VERSION_MAX_SIZE + 1)); + final DistributionSetManagement.Create distributionSetCreate = DistributionSetManagement.Create.builder() + .name("a").version(randomString(NamedVersionedEntity.VERSION_MAX_SIZE + 1)).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("set with too long version should not be created") .isThrownBy(() -> distributionSetManagement.create(distributionSetCreate)); - final DistributionSetCreate distributionSetCreate2 = entityFactory.distributionSet().create().name("a").version(INVALID_TEXT_HTML); + final DistributionSetManagement.Create distributionSetCreate2 = + DistributionSetManagement.Create.builder().name("a").version(INVALID_TEXT_HTML).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("set with invalid version should not be created") .isThrownBy(() -> distributionSetManagement.create(distributionSetCreate2)); - final DistributionSetCreate distributionSetCreate3 = entityFactory.distributionSet().create().name("a").version(""); + final DistributionSetManagement.Create distributionSetCreate3 = + DistributionSetManagement.Create.builder().name("a").version("").build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("set with too short version should not be created") .isThrownBy(() -> distributionSetManagement.create(distributionSetCreate3)); - final DistributionSetCreate distributionSetCreate4 = entityFactory.distributionSet().create().name("a").version(null); + final DistributionSetManagement.Create distributionSetCreate4 = + DistributionSetManagement.Create.builder().name("a").version(null).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("set with null version should not be created") .isThrownBy(() -> distributionSetManagement.create(distributionSetCreate4)); - final DistributionSetUpdate distributionSetUpdate = entityFactory.distributionSet().update(set.getId()) - .version(randomString(NamedVersionedEntity.VERSION_MAX_SIZE + 1)); + final DistributionSetManagement.Update distributionSetUpdate = DistributionSetManagement.Update.builder().id(set.getId()) + .version(randomString(NamedVersionedEntity.VERSION_MAX_SIZE + 1)).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("set with too long version should not be updated") .isThrownBy(() -> distributionSetManagement.update(distributionSetUpdate)); - final DistributionSetUpdate distributionSetUpdate2 = entityFactory.distributionSet().update(set.getId()).version(INVALID_TEXT_HTML); + final DistributionSetManagement.Update distributionSetUpdate2 = + DistributionSetManagement.Update.builder().id(set.getId()).version(INVALID_TEXT_HTML).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("set with invalid version should not be updated") .isThrownBy(() -> distributionSetManagement.update(distributionSetUpdate2)); - final DistributionSetUpdate distributionSetUpdate3 = entityFactory.distributionSet().update(set.getId()).version(""); + final DistributionSetManagement.Update distributionSetUpdate3 = + DistributionSetManagement.Update.builder().id(set.getId()).version("").build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("set with too short version should not be updated") .isThrownBy(() -> distributionSetManagement.update(distributionSetUpdate3)); @@ -390,10 +397,12 @@ class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTest { private DistributionSetType createDistributionSetTypeUsedByDs() { final DistributionSetType nonUpdatableType = distributionSetTypeManagement.create( - entityFactory.distributionSetType().create().key("updatableType").name("to be deleted").colour("test123")); - assertThat(distributionSetTypeManagement.findByKey("updatableType").get().getMandatoryModuleTypes()).isEmpty(); - distributionSetManagement.create(entityFactory.distributionSet().create() - .name("newtypesoft").version("1").type(nonUpdatableType.getKey())); + DistributionSetTypeManagement.Create.builder().key("updatableType").name("to be deleted").colour("test123").build()); + assertThat(distributionSetTypeManagement.findByKey("updatableType").orElseThrow().getMandatoryModuleTypes()).isEmpty(); + distributionSetManagement.create(DistributionSetManagement.Create.builder() + .type(nonUpdatableType) + .name("newtypesoft").version("1") + .build()); return nonUpdatableType; } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementSecurityTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementSecurityTest.java index 70546f46c..9c9a1166a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementSecurityTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/RolloutManagementSecurityTest.java @@ -15,8 +15,8 @@ import jakarta.validation.ConstraintDeclarationException; import lombok.extern.slf4j.Slf4j; import org.eclipse.hawkbit.im.authentication.SpPermission; -import org.eclipse.hawkbit.repository.builder.DistributionSetCreate; -import org.eclipse.hawkbit.repository.builder.DistributionSetTypeCreate; +import org.eclipse.hawkbit.repository.DistributionSetManagement; +import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; import org.eclipse.hawkbit.repository.builder.DynamicRolloutGroupTemplate; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -25,11 +25,11 @@ import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder; import org.eclipse.hawkbit.repository.test.util.WithUser; import org.junit.jupiter.api.Test; -@Slf4j /** * Feature: SecurityTests - RolloutManagement
* Story: SecurityTests RolloutManagement */ +@Slf4j class RolloutManagementSecurityTest extends AbstractJpaIntegrationTest { /** @@ -101,9 +101,10 @@ class RolloutManagementSecurityTest extends AbstractJpaIntegrationTest { */ @Test void cancelRolloutsForDistributionSetPermissionsCheck() { - final DistributionSetTypeCreate key = entityFactory.distributionSetType().create().name("type").key("type"); + final DistributionSetTypeManagement.Create key = DistributionSetTypeManagement.Create.builder().name("type").key("type").build(); distributionSetTypeManagement.create(key); - final DistributionSetCreate dsCreate = entityFactory.distributionSet().create().name("name").version("1.0.0").type("type"); + final DistributionSetManagement.Create dsCreate = + DistributionSetManagement.Create.builder().type(defaultDsType()).name("name").version("1.0.0").build(); final DistributionSet ds = distributionSetManagement.create(dsCreate); assertPermissions(() -> { rolloutManagement.cancelRolloutsForDistributionSet(ds); @@ -251,4 +252,4 @@ class RolloutManagementSecurityTest extends AbstractJpaIntegrationTest { void findByRolloutWithDetailedStatusPermissionsCheck() { assertPermissions(() -> rolloutGroupManagement.findByRolloutWithDetailedStatus(1L, PAGE), List.of(SpPermission.READ_ROLLOUT)); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareManagementSecurityTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareManagementSecurityTest.java index f85a0d470..f270244ca 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareManagementSecurityTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareManagementSecurityTest.java @@ -13,8 +13,7 @@ import java.util.List; import org.eclipse.hawkbit.im.authentication.SpPermission; import org.eclipse.hawkbit.repository.RepositoryManagement; -import org.eclipse.hawkbit.repository.builder.SoftwareModuleCreate; -import org.eclipse.hawkbit.repository.builder.SoftwareModuleUpdate; +import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.jpa.AbstractRepositoryManagementSecurityTest; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.junit.jupiter.api.Test; @@ -24,21 +23,21 @@ import org.junit.jupiter.api.Test; * Story: SecurityTests SoftwareManagement */ class SoftwareManagementSecurityTest - extends AbstractRepositoryManagementSecurityTest { + extends AbstractRepositoryManagementSecurityTest { @Override - protected RepositoryManagement getRepositoryManagement() { + protected RepositoryManagement getRepositoryManagement() { return softwareModuleManagement; } @Override - protected SoftwareModuleCreate getCreateObject() { - return entityFactory.softwareModule().create().name("name").version("version").type("type"); + protected SoftwareModuleManagement.Create getCreateObject() { + return SoftwareModuleManagement.Create.builder().type(getASmType()).name("name").version("version").build(); } @Override - protected SoftwareModuleUpdate getUpdateObject() { - return entityFactory.softwareModule().update(1L).locked(true); + protected SoftwareModuleManagement.Update getUpdateObject() { + return SoftwareModuleManagement.Update.builder().id(1L).locked(true).build(); } /** @@ -170,5 +169,4 @@ class SoftwareManagementSecurityTest assertPermissions(() -> softwareModuleManagement.findMetaDataBySoftwareModuleIdsAndTargetVisible(List.of(1L)), List.of(SpPermission.READ_REPOSITORY)); } - -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleManagementTest.java index d16ae2b1f..3133e460d 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleManagementTest.java @@ -22,6 +22,10 @@ import java.util.List; import java.util.Optional; import java.util.Set; +import jakarta.validation.ConstraintViolationException; + +import org.eclipse.hawkbit.repository.DistributionSetManagement; +import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataCreate; import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; @@ -61,7 +65,7 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { private static final PageRequest PAGE_REQUEST_100 = PageRequest.of(0, 100); /** - * Verifies that management get access reacts as specified on calls for non existing entities by means + * Verifies that management get access reacts as specified on calls for non existing entities by means * of Optional not present. */ @Test @@ -79,20 +83,19 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { } /** - * Verifies that management queries react as specfied on calls for non existing entities - * by means of throwing EntityNotFoundException. + * Verifies that management queries react as specfied on calls for non existing entities + * by means of throwing EntityNotFoundException. */ @Test @ExpectEvents({ @Expect(type = SoftwareModuleCreatedEvent.class, count = 1) }) void entityQueriesReferringToNotExistingEntitiesThrowsException() { final SoftwareModule module = testdataFactory.createSoftwareModuleApp(); - verifyThrownExceptionBy( - () -> softwareModuleManagement.create(Collections - .singletonList(entityFactory.softwareModule().create().name("xxx").type(NOT_EXIST_ID))), "SoftwareModuleType"); - verifyThrownExceptionBy( - () -> softwareModuleManagement - .create(entityFactory.softwareModule().create().name("xxx").type(NOT_EXIST_ID)), "SoftwareModuleType"); + final SoftwareModuleManagement.Create noType = SoftwareModuleManagement.Create.builder().name("xxx").type(null).build(); + final List noTypeList = List.of(noType); + assertThatExceptionOfType(ConstraintViolationException.class) + .isThrownBy(() -> softwareModuleManagement.create(noTypeList)); + assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(() -> softwareModuleManagement.create(noType)); verifyThrownExceptionBy( () -> softwareModuleManagement.updateMetadata( @@ -122,7 +125,8 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { verifyThrownExceptionBy(() -> softwareModuleManagement.getMetadata(NOT_EXIST_IDL), "SoftwareModule"); verifyThrownExceptionBy(() -> softwareModuleManagement.findByType(NOT_EXIST_IDL, PAGE), "SoftwareModule"); - verifyThrownExceptionBy(() -> softwareModuleManagement.update(entityFactory.softwareModule().update(NOT_EXIST_IDL)), "SoftwareModule"); + verifyThrownExceptionBy(() -> softwareModuleManagement.update(SoftwareModuleManagement.Update.builder().id(NOT_EXIST_IDL).build()), + "SoftwareModule"); } /** @@ -133,7 +137,7 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { final SoftwareModule ah = testdataFactory.createSoftwareModuleOs(); final SoftwareModule updated = softwareModuleManagement - .update(entityFactory.softwareModule().update(ah.getId())); + .update(SoftwareModuleManagement.Update.builder().id(ah.getId()).build()); assertThat(updated.getOptLockRevision()) .as("Expected version number of updated entity to be equal to created version") @@ -148,7 +152,7 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { final SoftwareModule ah = testdataFactory.createSoftwareModuleOs(); final SoftwareModule updated = softwareModuleManagement - .update(entityFactory.softwareModule().update(ah.getId()).description("changed").vendor("changed")); + .update(SoftwareModuleManagement.Update.builder().id(ah.getId()).description("changed").vendor("changed").build()); assertThat(updated.getOptLockRevision()) .as("Expected version number of updated entitity is") @@ -174,17 +178,20 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { @Test void findSoftwareModuleByFilters() { final SoftwareModule ah = softwareModuleManagement - .create(entityFactory.softwareModule().create().type(appType).name("agent-hub").version("1.0.1")); + .create(SoftwareModuleManagement.Create.builder().type(appType).name("agent-hub").version("1.0.1").build()); final SoftwareModule jvm = softwareModuleManagement - .create(entityFactory.softwareModule().create().type(runtimeType).name("oracle-jre").version("1.7.2")); + .create(SoftwareModuleManagement.Create.builder().type(runtimeType).name("oracle-jre").version("1.7.2").build()); final SoftwareModule os = softwareModuleManagement - .create(entityFactory.softwareModule().create().type(osType).name("poky").version("3.0.2")); + .create(SoftwareModuleManagement.Create.builder().type(osType).name("poky").version("3.0.2").build()); final SoftwareModule ah2 = softwareModuleManagement - .create(entityFactory.softwareModule().create().type(appType).name("agent-hub").version("1.0.2")); + .create(SoftwareModuleManagement.Create.builder().type(appType).name("agent-hub").version("1.0.2").build()); JpaDistributionSet ds = (JpaDistributionSet) distributionSetManagement - .create(entityFactory.distributionSet().create().name("ds-1").version("1.0.1").type(standardDsType) - .modules(Arrays.asList(os.getId(), jvm.getId(), ah2.getId()))); + .create(DistributionSetManagement.Create.builder() + .type(standardDsType) + .name("ds-1").version("1.0.1") + .modules(Set.of(os, jvm, ah2)) + .build()); final JpaTarget target = (JpaTarget) testdataFactory.createTarget(); ds = (JpaDistributionSet) assignSet(target, ds).getDistributionSet(); @@ -217,10 +224,7 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { */ @Test void findSoftwareModulesById() { - - final List modules = Arrays.asList(testdataFactory.createSoftwareModuleOs().getId(), - testdataFactory.createSoftwareModuleApp().getId(), 624355263L); - + final List modules = List.of(testdataFactory.createSoftwareModuleOs().getId(), testdataFactory.createSoftwareModuleApp().getId()); assertThat(softwareModuleManagement.get(modules)).hasSize(2); } @@ -236,7 +240,7 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { softwareModuleManagement.delete(testdataFactory.createSoftwareModuleOs("deleted").getId()); testdataFactory.createSoftwareModuleApp(); - assertThat(softwareModuleManagement.findByType(osType.getId(), PAGE).getContent()) + assertThat((List) softwareModuleManagement.findByType(osType.getId(), PAGE).getContent()) .as("Expected to find the following number of modules:").hasSize(2).as("with the following elements") .contains(two, one); } @@ -497,8 +501,9 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { // one soft deleted final SoftwareModule deleted = testdataFactory.createSoftwareModuleApp(); - final DistributionSet set = distributionSetManagement.create(entityFactory.distributionSet().create() - .name("set").version("1").modules(Arrays.asList(one.getId(), deleted.getId()))); + final DistributionSet set = distributionSetManagement.create(DistributionSetManagement.Create.builder() + .type(defaultDsType()) + .name("set").version("1").modules(Set.of(one, deleted)).build()); softwareModuleManagement.delete(deleted.getId()); assertThat(softwareModuleManagement.findByAssignedTo(set.getId(), PAGE).getContent()) @@ -825,7 +830,7 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { final List modules = distributionSet.getModules().stream().toList(); assertThat(modules).hasSizeGreaterThan(1); - // try delete while DS is not locked + // try to delete while DS is not locked softwareModuleManagement.delete(modules.get(0).getId()); distributionSetManagement.lock(distributionSet.getId()); @@ -833,7 +838,7 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { distributionSetManagement.get(distributionSet.getId()).map(DistributionSet::isLocked).orElse(false)) .isTrue(); - // try delete SM of a locked DS + // try to delete SM of a locked DS final Long moduleId = modules.get(1).getId(); assertThatExceptionOfType(LockedException.class) .as("Attempt to delete a software module of a locked DS should throw an exception") @@ -865,8 +870,8 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { final long countSoftwareModule = softwareModuleRepository.count(); // create SoftwareModule - SoftwareModule softwareModule = softwareModuleManagement.create(entityFactory.softwareModule().create() - .type(type).name(name).version(version).description("description of artifact " + name)); + SoftwareModule softwareModule = softwareModuleManagement.create(SoftwareModuleManagement.Create.builder() + .type(type).name(name).version(version).description("description of artifact " + name).build()); final int artifactSize = 5 * 1024; for (int i = 0; i < numberArtifacts; i++) { @@ -904,4 +909,4 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest { .isNull(); } } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleTypeManagementSecurityTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleTypeManagementSecurityTest.java index 97b6824a9..c37f6db00 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleTypeManagementSecurityTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleTypeManagementSecurityTest.java @@ -14,8 +14,7 @@ import java.util.Random; import org.eclipse.hawkbit.im.authentication.SpPermission; import org.eclipse.hawkbit.repository.RepositoryManagement; -import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeCreate; -import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeUpdate; +import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; import org.eclipse.hawkbit.repository.jpa.AbstractRepositoryManagementSecurityTest; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.junit.jupiter.api.Test; @@ -25,21 +24,21 @@ import org.junit.jupiter.api.Test; * Story: SecurityTests SoftwareModuleTypeManagement */ class SoftwareModuleTypeManagementSecurityTest - extends AbstractRepositoryManagementSecurityTest { + extends AbstractRepositoryManagementSecurityTest { @Override - protected RepositoryManagement getRepositoryManagement() { + protected RepositoryManagement getRepositoryManagement() { return softwareModuleTypeManagement; } @Override - protected SoftwareModuleTypeCreate getCreateObject() { - return entityFactory.softwareModuleType().create().key(String.format("key-%d", new Random().nextInt())).name(String.format("name-%d", new Random().nextInt())); + protected SoftwareModuleTypeManagement.Create getCreateObject() { + return SoftwareModuleTypeManagement.Create.builder().key(String.format("key-%d", new Random().nextInt())).name(String.format("name-%d", new Random().nextInt())).build(); } @Override - protected SoftwareModuleTypeUpdate getUpdateObject() { - return entityFactory.softwareModuleType().update(1L).description("description"); + protected SoftwareModuleTypeManagement.Update getUpdateObject() { + return SoftwareModuleTypeManagement.Update.builder().id(1L).description("description").build(); } /** @@ -57,5 +56,4 @@ class SoftwareModuleTypeManagementSecurityTest void getByNamePermissionsCheck() { assertPermissions(() -> softwareModuleTypeManagement.findByName("name"), List.of(SpPermission.READ_REPOSITORY)); } - -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleTypeManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleTypeManagementTest.java index 355a4ab1c..bfe8d971e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleTypeManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SoftwareModuleTypeManagementTest.java @@ -17,7 +17,8 @@ import java.util.List; import jakarta.validation.ConstraintViolationException; -import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeCreate; +import org.eclipse.hawkbit.repository.SoftwareModuleManagement; +import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; @@ -26,6 +27,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.test.matcher.Expect; import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents; import org.junit.jupiter.api.Test; +import org.springframework.data.domain.Slice; /** * Feature: Component Tests - Repository
@@ -34,7 +36,7 @@ import org.junit.jupiter.api.Test; class SoftwareModuleTypeManagementTest extends AbstractJpaIntegrationTest { /** - * Verifies that management get access reacts as specfied on calls for non existing entities by means + * Verifies that management get access reacts as specfied on calls for non existing entities by means * of Optional not present. */ @Test @@ -47,8 +49,8 @@ class SoftwareModuleTypeManagementTest extends AbstractJpaIntegrationTest { } /** - * Verifies that management queries react as specfied on calls for non existing entities - * by means of throwing EntityNotFoundException. + * Verifies that management queries react as specfied on calls for non existing entities + * by means of throwing EntityNotFoundException. */ @Test @ExpectEvents({ @Expect(type = SoftwareModuleCreatedEvent.class, count = 0) }) @@ -56,7 +58,7 @@ class SoftwareModuleTypeManagementTest extends AbstractJpaIntegrationTest { verifyThrownExceptionBy(() -> softwareModuleTypeManagement.delete(NOT_EXIST_IDL), "SoftwareModuleType"); verifyThrownExceptionBy( - () -> softwareModuleTypeManagement.update(entityFactory.softwareModuleType().update(NOT_EXIST_IDL)), + () -> softwareModuleTypeManagement.update(SoftwareModuleTypeManagement.Update.builder().id(NOT_EXIST_IDL).build()), "SoftwareModuleType"); } @@ -66,10 +68,10 @@ class SoftwareModuleTypeManagementTest extends AbstractJpaIntegrationTest { @Test void updateNothingResultsInUnchangedRepositoryForType() { final SoftwareModuleType created = softwareModuleTypeManagement - .create(entityFactory.softwareModuleType().create().key("test-key").name("test-name")); + .create(SoftwareModuleTypeManagement.Create.builder().key("test-key").name("test-name").build()); final SoftwareModuleType updated = softwareModuleTypeManagement - .update(entityFactory.softwareModuleType().update(created.getId())); + .update(SoftwareModuleTypeManagement.Update.builder().id(created.getId()).build()); assertThat(updated.getOptLockRevision()) .as("Expected version number of updated entitity to be equal to created version") @@ -82,10 +84,10 @@ class SoftwareModuleTypeManagementTest extends AbstractJpaIntegrationTest { @Test void updateSoftwareModuleTypeFieldsToNewValue() { final SoftwareModuleType created = softwareModuleTypeManagement - .create(entityFactory.softwareModuleType().create().key("test-key").name("test-name")); + .create(SoftwareModuleTypeManagement.Create.builder().key("test-key").name("test-name").build()); final SoftwareModuleType updated = softwareModuleTypeManagement.update( - entityFactory.softwareModuleType().update(created.getId()).description("changed").colour("changed")); + SoftwareModuleTypeManagement.Update.builder().id(created.getId()).description("changed").colour("changed").build()); assertThat(updated.getOptLockRevision()).as("Expected version number of updated entities is") .isEqualTo(created.getOptLockRevision() + 1); @@ -98,9 +100,9 @@ class SoftwareModuleTypeManagementTest extends AbstractJpaIntegrationTest { */ @Test void createModuleTypesCallFailsForExistingTypes() { - final List created = Arrays.asList( - entityFactory.softwareModuleType().create().key("test-key").name("test-name"), - entityFactory.softwareModuleType().create().key("test-key2").name("test-name2")); + final List created = Arrays.asList( + SoftwareModuleTypeManagement.Create.builder().key("test-key").name("test-name").build(), + SoftwareModuleTypeManagement.Create.builder().key("test-key2").name("test-name2").build()); softwareModuleTypeManagement.create(created); assertThatExceptionOfType(EntityAlreadyExistsException.class) .as("should not have worked as module type already exists") @@ -112,32 +114,30 @@ class SoftwareModuleTypeManagementTest extends AbstractJpaIntegrationTest { */ @Test void deleteAssignedAndUnassignedSoftwareModuleTypes() { - assertThat(softwareModuleTypeManagement.findAll(PAGE)).hasSize(3).contains(osType, runtimeType, appType); + assertThat((Slice) softwareModuleTypeManagement.findAll(PAGE)).hasSize(3).contains(osType, runtimeType, appType); SoftwareModuleType type = softwareModuleTypeManagement - .create(entityFactory.softwareModuleType().create().key("bundle").name("OSGi Bundle")); + .create(SoftwareModuleTypeManagement.Create.builder().key("bundle").name("OSGi Bundle").build()); - assertThat(softwareModuleTypeManagement.findAll(PAGE)).hasSize(4).contains(osType, runtimeType, appType, type); + assertThat((Slice) softwareModuleTypeManagement.findAll(PAGE)).hasSize(4).contains(osType, runtimeType, appType, type); // delete unassigned softwareModuleTypeManagement.delete(type.getId()); - assertThat(softwareModuleTypeManagement.findAll(PAGE)).hasSize(3).contains(osType, runtimeType, appType); - assertThat(softwareModuleTypeRepository.findAll()).hasSize(3).contains((JpaSoftwareModuleType) osType, - (JpaSoftwareModuleType) runtimeType, (JpaSoftwareModuleType) appType); + assertThat((Slice) softwareModuleTypeManagement.findAll(PAGE)).hasSize(3).contains(osType, runtimeType, appType); + assertThat((List) softwareModuleTypeRepository.findAll()).hasSize(3).contains(osType, runtimeType, appType); type = softwareModuleTypeManagement - .create(entityFactory.softwareModuleType().create().key("bundle2").name("OSGi Bundle2")); + .create(SoftwareModuleTypeManagement.Create.builder().key("bundle2").name("OSGi Bundle2").build()); - assertThat(softwareModuleTypeManagement.findAll(PAGE)).hasSize(4).contains(osType, runtimeType, appType, type); + assertThat((Slice) softwareModuleTypeManagement.findAll(PAGE)).hasSize(4).contains(osType, runtimeType, appType, type); softwareModuleManagement - .create(entityFactory.softwareModule().create().type(type).name("Test SM").version("1.0")); + .create(SoftwareModuleManagement.Create.builder().type(type).name("Test SM").version("1.0").build()); // delete assigned softwareModuleTypeManagement.delete(type.getId()); - assertThat(softwareModuleTypeManagement.findAll(PAGE)).hasSize(3).contains(osType, runtimeType, appType); - assertThat(softwareModuleTypeManagement.findByRsql("name==*", PAGE)).hasSize(3).contains(osType, runtimeType, - appType); + assertThat((Slice) softwareModuleTypeManagement.findAll(PAGE)).hasSize(3).contains(osType, runtimeType, appType); + assertThat((Slice) softwareModuleTypeManagement.findByRsql("name==*", PAGE)).hasSize(3).contains(osType, runtimeType, appType); assertThat(softwareModuleTypeManagement.count()).isEqualTo(3); assertThat(softwareModuleTypeRepository.findAll()).hasSize(4).contains((JpaSoftwareModuleType) osType, @@ -152,11 +152,12 @@ class SoftwareModuleTypeManagementTest extends AbstractJpaIntegrationTest { void findSoftwareModuleTypeByName() { testdataFactory.createSoftwareModuleOs(); final SoftwareModuleType found = softwareModuleTypeManagement - .create(entityFactory.softwareModuleType().create().key("thetype").name("thename")); + .create(SoftwareModuleTypeManagement.Create.builder().key("thetype").name("thename").build()); softwareModuleTypeManagement - .create(entityFactory.softwareModuleType().create().key("thetype2").name("anothername")); + .create(SoftwareModuleTypeManagement.Create.builder().key("thetype2").name("anothername").build()); - assertThat(softwareModuleTypeManagement.findByName("thename")).as("Type with given name").contains(found); + assertThat((((SoftwareModuleTypeManagement) softwareModuleTypeManagement)).findByName("thename")).as( + "Type with given name").contains(found); } /** @@ -164,12 +165,11 @@ class SoftwareModuleTypeManagementTest extends AbstractJpaIntegrationTest { */ @Test void createSoftwareModuleTypeFailsWithExistingEntity() { - final SoftwareModuleTypeCreate create = entityFactory.softwareModuleType().create().key("thetype").name("thename"); + final SoftwareModuleTypeManagement.Create create = SoftwareModuleTypeManagement.Create.builder().key("thetype").name("thename").build(); softwareModuleTypeManagement.create(create); assertThatExceptionOfType(EntityAlreadyExistsException.class) .as("should not have worked as module type already exists") - .isThrownBy(() -> softwareModuleTypeManagement - .create(create)); + .isThrownBy(() -> softwareModuleTypeManagement.create(create)); } /** @@ -177,10 +177,10 @@ class SoftwareModuleTypeManagementTest extends AbstractJpaIntegrationTest { */ @Test void createSoftwareModuleTypesFailsWithExistingEntity() { - softwareModuleTypeManagement.create(entityFactory.softwareModuleType().create().key("thetype").name("thename")); - final List creates = List.of( - entityFactory.softwareModuleType().create().key("thetype").name("thename"), - entityFactory.softwareModuleType().create().key("anothertype").name("anothername")); + softwareModuleTypeManagement.create(SoftwareModuleTypeManagement.Create.builder().key("thetype").name("thename").build()); + final List creates = List.of( + SoftwareModuleTypeManagement.Create.builder().key("thetype").name("thename").build(), + SoftwareModuleTypeManagement.Create.builder().key("anothertype").name("anothername").build()); assertThatExceptionOfType(EntityAlreadyExistsException.class) .as("should not have worked as module type already exists") .isThrownBy(() -> softwareModuleTypeManagement.create(creates)); @@ -191,7 +191,8 @@ class SoftwareModuleTypeManagementTest extends AbstractJpaIntegrationTest { */ @Test void createSoftwareModuleTypesFailsWithInvalidMaxAssignment() { - final SoftwareModuleTypeCreate create = entityFactory.softwareModuleType().create().key("type").name("name").maxAssignments(0); + final SoftwareModuleTypeManagement.Create create = + SoftwareModuleTypeManagement.Create.builder().key("type").name("name").maxAssignments(0).build(); assertThatExceptionOfType(ConstraintViolationException.class) .as("should not have worked as max assignment is invalid. Should be greater than 0") .isThrownBy(() -> softwareModuleTypeManagement.create(create)); @@ -202,12 +203,12 @@ class SoftwareModuleTypeManagementTest extends AbstractJpaIntegrationTest { */ @Test void createMultipleSoftwareModuleTypes() { - final List created = softwareModuleTypeManagement - .create(Arrays.asList(entityFactory.softwareModuleType().create().key("thetype").name("thename"), - entityFactory.softwareModuleType().create().key("thetype2").name("thename2"))); + final List created = softwareModuleTypeManagement + .create(List.of( + SoftwareModuleTypeManagement.Create.builder().key("thetype").name("thename").build(), + SoftwareModuleTypeManagement.Create.builder().key("thetype2").name("thename2").build())); assertThat(created).as("Number of created types").hasSize(2); assertThat(softwareModuleTypeManagement.count()).as("Number of types in repository").isEqualTo(5); } - -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SystemManagementSecurityTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SystemManagementSecurityTest.java index c1d2ab8e2..0f0649e44 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SystemManagementSecurityTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SystemManagementSecurityTest.java @@ -18,11 +18,11 @@ import org.eclipse.hawkbit.im.authentication.SpringEvalExpressions; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.junit.jupiter.api.Test; -@Slf4j /** * Feature: SecurityTests - SystemManagement
* Story: SecurityTests SystemManagement */ +@Slf4j class SystemManagementSecurityTest extends AbstractJpaIntegrationTest { /** diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetFilterQueryManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetFilterQueryManagementTest.java index e6a4b638a..17fc1e772 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetFilterQueryManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetFilterQueryManagementTest.java @@ -25,6 +25,7 @@ import jakarta.validation.ConstraintViolationException; import org.assertj.core.api.Assertions; import org.eclipse.hawkbit.exception.AbstractServerRtException; +import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate; import org.eclipse.hawkbit.repository.builder.TargetFilterQueryCreate; @@ -588,8 +589,10 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest { private void verifyAutoAssignmentWithIncompleteDs(final TargetFilterQuery targetFilterQuery) { final DistributionSet incompleteDistributionSet = distributionSetManagement - .create(entityFactory.distributionSet().create().name("incomplete").version("1") - .type(testdataFactory.findOrCreateDefaultTestDsType())); + .create(DistributionSetManagement.Create.builder() + .type(testdataFactory.findOrCreateDefaultTestDsType()) + .name("incomplete").version("1") + .build()); final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate = entityFactory.targetFilterQuery() .updateAutoAssign(targetFilterQuery.getId()).ds(incompleteDistributionSet.getId()); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementSearchTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementSearchTest.java index cebd870b3..3ff0d996d 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementSearchTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementSearchTest.java @@ -16,8 +16,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.FilterParams; -import org.eclipse.hawkbit.repository.builder.DistributionSetCreate; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -62,7 +62,7 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest { } /** - * Tests different parameter combinations for target search operations. + * Tests different parameter combinations for target search operations. * and query definitions by RSQL (named and un-named). */ @Test @@ -278,13 +278,12 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest { */ @Test void shouldNotFindTargetsIncompatibleWithDS() { - final DistributionSetType dsType = testdataFactory.findOrCreateDistributionSetType("test-ds-type", - "test-ds-type"); - final DistributionSet testDs = createDistSetWithType(dsType); - final TargetType compatibleTargetType = testdataFactory.createTargetType("compTestType", - Collections.singletonList(dsType)); - final TargetType incompatibleTargetType = testdataFactory.createTargetType("incompTestType", - Collections.singletonList(testdataFactory.createDistributionSet().getType())); + final DistributionSetType dsType = testdataFactory.findOrCreateDistributionSetType("test-ds-type", "test-ds-type"); + final DistributionSet testDs = distributionSetManagement.create(DistributionSetManagement.Create.builder() + .type(dsType).name("test-ds").version("1.0").build()); + final TargetType compatibleTargetType = testdataFactory.createTargetType("compTestType", List.of(dsType)); + final TargetType incompatibleTargetType = testdataFactory.createTargetType( + "incompTestType", List.of(testdataFactory.createDistributionSet().getType())); final TargetFilterQuery tfq = targetFilterQueryManagement .create(entityFactory.targetFilterQuery().create().name("test-filter").query("name==*")); @@ -659,10 +658,4 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest { .hasSize((int) targetManagement.countByFilters(filterParams)) .as("and contains the following elements").containsAll(expected); } - - private DistributionSet createDistSetWithType(final DistributionSetType type) { - final DistributionSetCreate dsCreate = entityFactory.distributionSet().create().name("test-ds").version("1.0") - .type(type); - return distributionSetManagement.create(dsCreate); - } } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementSecurityTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementSecurityTest.java index 0e86a64e4..2c5c8887a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementSecurityTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementSecurityTest.java @@ -20,11 +20,11 @@ import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.test.util.WithUser; import org.junit.jupiter.api.Test; -@Slf4j /** * Feature: SecurityTests - TargetManagement
* Story: SecurityTests TargetManagement */ +@Slf4j class TargetManagementSecurityTest extends AbstractJpaIntegrationTest { /** @@ -184,9 +184,9 @@ class TargetManagementSecurityTest extends AbstractJpaIntegrationTest { @Test void findByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatablePermissionsCheck() { assertPermissions( - () -> targetManagement.findByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(List.of(1L), "controllerId==id", - entityFactory.distributionSetType().create().build(), PAGE - ), List.of(SpPermission.READ_TARGET, SpPermission.READ_ROLLOUT)); + () -> targetManagement.findByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable( + List.of(1L), "controllerId==id", defaultDsType(), PAGE), + List.of(SpPermission.READ_TARGET, SpPermission.READ_ROLLOUT)); } /** @@ -203,8 +203,10 @@ class TargetManagementSecurityTest extends AbstractJpaIntegrationTest { */ @Test void countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatablePermissionsCheck() { - assertPermissions(() -> targetManagement.countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable("controllerId==id", List.of(1L), - entityFactory.distributionSetType().create().build()), List.of(SpPermission.READ_TARGET, SpPermission.READ_ROLLOUT)); + assertPermissions( + () -> targetManagement.countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable( + "controllerId==id", List.of(1L), defaultDsType()), + List.of(SpPermission.READ_TARGET, SpPermission.READ_ROLLOUT)); } /** diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetTagManagementSecurityTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetTagManagementSecurityTest.java index 81472909f..6cee2a029 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetTagManagementSecurityTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetTagManagementSecurityTest.java @@ -16,11 +16,11 @@ import org.eclipse.hawkbit.im.authentication.SpPermission; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.junit.jupiter.api.Test; -@Slf4j /** * Feature: SecurityTests - TargetTagManagement
* Story: SecurityTests TargetTagManagement */ +@Slf4j class TargetTagManagementSecurityTest extends AbstractJpaIntegrationTest { /** @@ -106,4 +106,4 @@ class TargetTagManagementSecurityTest extends AbstractJpaIntegrationTest { void updatePermissionsCheck() { assertPermissions(() -> targetTagManagement.update(entityFactory.tag().update(1L)), List.of(SpPermission.UPDATE_TARGET)); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetTypeManagementSecurityTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetTypeManagementSecurityTest.java index f07e7e424..bc0ff1673 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetTypeManagementSecurityTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetTypeManagementSecurityTest.java @@ -17,11 +17,11 @@ import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.test.util.WithUser; import org.junit.jupiter.api.Test; -@Slf4j /** * Feature: SecurityTests - TargetTypeManagement
* Story: SecurityTests TargetTypeManagement */ +@Slf4j class TargetTypeManagementSecurityTest extends AbstractJpaIntegrationTest { /** @@ -151,5 +151,4 @@ class TargetTypeManagementSecurityTest extends AbstractJpaIntegrationTest { assertPermissions(() -> targetTypeManagement.unassignDistributionSetType(1L, 1L), List.of(SpPermission.UPDATE_TARGET, SpPermission.READ_REPOSITORY)); } - -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TenantConfigurationManagementSecurityTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TenantConfigurationManagementSecurityTest.java index 17a789303..be09dd1a5 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TenantConfigurationManagementSecurityTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TenantConfigurationManagementSecurityTest.java @@ -17,11 +17,11 @@ import org.eclipse.hawkbit.im.authentication.SpPermission; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.junit.jupiter.api.Test; -@Slf4j /** * Feature: SecurityTests - TargetManagement
* Story: SecurityTests TargetManagement */ +@Slf4j class TenantConfigurationManagementSecurityTest extends AbstractJpaIntegrationTest { /** @@ -87,4 +87,4 @@ class TenantConfigurationManagementSecurityTest extends AbstractJpaIntegrationTe void pollStatusResolverPermissionsCheck() { assertPermissions(() -> tenantConfigurationManagement.pollStatusResolver(), List.of(SpPermission.READ_TARGET)); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/model/EntityInterceptorListenerTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/model/EntityInterceptorListenerTest.java index 7ce8a4040..72ff62b77 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/model/EntityInterceptorListenerTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/model/EntityInterceptorListenerTest.java @@ -11,6 +11,7 @@ package org.eclipse.hawkbit.repository.jpa.model; import static org.assertj.core.api.Assertions.assertThat; +import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.EntityInterceptor; import org.eclipse.hawkbit.repository.jpa.model.helper.EntityInterceptorHolder; @@ -115,7 +116,7 @@ class EntityInterceptorListenerTest extends AbstractJpaIntegrationTest { private void executeDeleteAndAssertCallbackResult(final AbstractEntityListener entityInterceptor) { EntityInterceptorHolder.getInstance().getEntityInterceptors().add(entityInterceptor); final SoftwareModuleType type = softwareModuleTypeManagement - .create(entityFactory.softwareModuleType().create().name("test").key("test")); + .create(SoftwareModuleTypeManagement.Create.builder().name("test").key("test").build()); softwareModuleTypeManagement.delete(type.getId()); assertThat(entityInterceptor.getEntity()).isNotNull(); @@ -198,4 +199,4 @@ class EntityInterceptorListenerTest extends AbstractJpaIntegrationTest { setEntity(entity); } } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/model/ModelEqualsHashcodeTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/model/ModelEqualsHashcodeTest.java index 8f7b1e123..b226da9be 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/model/ModelEqualsHashcodeTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/model/ModelEqualsHashcodeTest.java @@ -11,6 +11,7 @@ package org.eclipse.hawkbit.repository.jpa.model; import static org.assertj.core.api.Assertions.assertThat; +import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.junit.jupiter.api.Test; @@ -59,12 +60,12 @@ class ModelEqualsHashcodeTest extends AbstractJpaIntegrationTest { @Test void changedEntitiesAreNotEqual() { final SoftwareModuleType type = softwareModuleTypeManagement - .create(entityFactory.softwareModuleType().create().key("test").name("test")); + .create(SoftwareModuleTypeManagement.Create.builder().key("test").name("test").build()); assertThat(type).as("persited entity is not equal to regular object") - .isNotEqualTo(entityFactory.softwareModuleType().create().key("test").name("test").build()); + .isNotEqualTo(SoftwareModuleTypeManagement.Create.builder().key("test").name("test").build()); final SoftwareModuleType updated = softwareModuleTypeManagement.update( - entityFactory.softwareModuleType().update(type.getId()).description("another")); + SoftwareModuleTypeManagement.Update.builder().id(type.getId()).description("another").build()); assertThat(type).as("Changed entity is not equal to the previous version").isNotEqualTo(updated); } @@ -72,9 +73,9 @@ class ModelEqualsHashcodeTest extends AbstractJpaIntegrationTest { * Verify that no proxy of the entity manager has an influence on the equals or hashcode result. */ @Test - void managedEntityIsEqualToUnamangedObjectWithSameKey() { + void managedEntityIsEqualToUnmanagedObjectWithSameKey() { final SoftwareModuleType type = softwareModuleTypeManagement.create( - entityFactory.softwareModuleType().create().key("test").name("test").description("test")); + SoftwareModuleTypeManagement.Create.builder().key("test").name("test").description("test").build()); final JpaSoftwareModuleType mock = new JpaSoftwareModuleType("test", "test", "test", 1); mock.setId(type.getId()); @@ -86,5 +87,4 @@ class ModelEqualsHashcodeTest extends AbstractJpaIntegrationTest { .as("managed entity has same hash code as regular object with same content") .hasSameHashCodeAs(mock.hashCode()); } - -} +} \ No newline at end of file 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 6f35136ff..399645e5a 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 @@ -12,6 +12,7 @@ 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.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataCreate; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; @@ -33,20 +34,20 @@ class RsqlSoftwareModuleFieldTest extends AbstractJpaIntegrationTest { @BeforeEach void setupBeforeTest() { - 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")); + ah = softwareModuleManagement.create(SoftwareModuleManagement.Create.builder().type(appType).name("agent-hub") + .version("1.0.1").description("agent-hub").build()); + softwareModuleManagement.create(SoftwareModuleManagement.Create.builder().type(runtimeType).name("oracle-jre") + .version("1.7.2").description("aa").build()); softwareModuleManagement.create( - entityFactory.softwareModule().create().type(osType).name("poki").version("3.0.2").description("aa")); + SoftwareModuleManagement.Create.builder().type(osType).name("poki").version("3.0.2").description("aa").build()); softwareModuleManagement - .create(entityFactory.softwareModule().create().type(osType).name("*§$%&/&%ÄÜ*Ö@").version("1.0.0") - .description("wildcard testing")); + .create(SoftwareModuleManagement.Create.builder().type(osType).name("*§$%&/&%ÄÜ*Ö@").version("1.0.0") + .description("wildcard testing").build()); softwareModuleManagement - .create(entityFactory.softwareModule().create().type(osType).name("noDesc").version("noDesc")); + .create(SoftwareModuleManagement.Create.builder().type(osType).name("noDesc").version("noDesc").build()); - 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( + SoftwareModuleManagement.Create.builder().type(appType).name("agent-hub2").version("1.0.1").description("agent-hub2").build()); final SoftwareModuleMetadataCreate softwareModuleMetadata = entityFactory.softwareModuleMetadata() .create(ah.getId()).key("metaKey").value("metaValue"); @@ -163,7 +164,7 @@ class RsqlSoftwareModuleFieldTest extends AbstractJpaIntegrationTest { } private void assertRSQLQuery(final String rsql, final long expectedEntity) { - final Page find = softwareModuleManagement.findByRsql(rsql, PageRequest.of(0, 100)); + final Page find = softwareModuleManagement.findByRsql(rsql, PageRequest.of(0, 100)); final long countAll = find.getTotalElements(); assertThat(find).isNotNull(); assertThat(countAll).isEqualTo(expectedEntity); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlSoftwareModuleTypeFieldsTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlSoftwareModuleTypeFieldsTest.java index d0058e604..e2fdcb3e0 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlSoftwareModuleTypeFieldsTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlSoftwareModuleTypeFieldsTest.java @@ -87,9 +87,9 @@ class RsqlSoftwareModuleTypeFieldsTest extends AbstractJpaIntegrationTest { } private void assertRSQLQuery(final String rsql, final long expectedEntity) { - final Page find = softwareModuleTypeManagement.findByRsql(rsql, PageRequest.of(0, 100)); + final Page find = softwareModuleTypeManagement.findByRsql(rsql, PageRequest.of(0, 100)); final long countAll = find.getTotalElements(); assertThat(find).isNotNull(); assertThat(countAll).isEqualTo(expectedEntity); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlTagFieldsTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlTagFieldsTest.java index 498a70c20..607fd46d7 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlTagFieldsTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RsqlTagFieldsTest.java @@ -11,8 +11,8 @@ package org.eclipse.hawkbit.repository.jpa.rsql; import static org.assertj.core.api.Assertions.assertThat; +import org.eclipse.hawkbit.repository.DistributionSetTagManagement; import org.eclipse.hawkbit.repository.TagFields; -import org.eclipse.hawkbit.repository.builder.TagCreate; import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.model.DistributionSetTag; import org.eclipse.hawkbit.repository.model.TargetTag; @@ -29,12 +29,11 @@ class RsqlTagFieldsTest extends AbstractJpaIntegrationTest { @BeforeEach void seuptBeforeTest() { - for (int i = 0; i < 5; i++) { - final TagCreate targetTag = entityFactory.tag().create() - .name(Integer.toString(i)).description(Integer.toString(i)).colour(i % 2 == 0 ? "red" : "blue"); - targetTagManagement.create(targetTag); - distributionSetTagManagement.create(targetTag); + targetTagManagement.create(entityFactory.tag().create() + .name(Integer.toString(i)).description(Integer.toString(i)).colour(i % 2 == 0 ? "red" : "blue")); + distributionSetTagManagement.create(DistributionSetTagManagement.Create.builder() + .name(Integer.toString(i)).description(Integer.toString(i)).colour(i % 2 == 0 ? "red" : "blue").build()); } } @@ -129,9 +128,9 @@ class RsqlTagFieldsTest extends AbstractJpaIntegrationTest { } private void assertRSQLQueryDistributionSet(final String rsql, final long expectedEntities) { - final Page findEnitity = distributionSetTagManagement.findByRsql(rsql, PageRequest.of(0, 100)); - final long countAllEntities = findEnitity.getTotalElements(); - assertThat(findEnitity).isNotNull(); + final Page findEntity = distributionSetTagManagement.findByRsql(rsql, PageRequest.of(0, 100)); + final long countAllEntities = findEntity.getTotalElements(); + assertThat(findEntity).isNotNull(); assertThat(countAllEntities).isEqualTo(expectedEntities); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/tenancy/MultiTenancyEntityTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/tenancy/MultiTenancyEntityTest.java index 6f42fa09d..631d467b1 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/tenancy/MultiTenancyEntityTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/tenancy/MultiTenancyEntityTest.java @@ -167,11 +167,11 @@ class MultiTenancyEntityTest extends AbstractJpaIntegrationTest { createDistributionSetForTenant(anotherTenant); // ensure both tenants see their distribution sets - final Slice findDistributionSetsForTenant = findDistributionSetForTenant(tenant); + final Slice findDistributionSetsForTenant = findDistributionSetForTenant(tenant); assertThat(findDistributionSetsForTenant).hasSize(1); assertThat(findDistributionSetsForTenant.getContent().get(0).getTenant().toUpperCase()) .isEqualTo(tenant.toUpperCase()); - final Slice findDistributionSetsForAnotherTenant = findDistributionSetForTenant(anotherTenant); + final Slice findDistributionSetsForAnotherTenant = findDistributionSetForTenant(anotherTenant); assertThat(findDistributionSetsForAnotherTenant).hasSize(1); assertThat(findDistributionSetsForAnotherTenant.getContent().get(0).getTenant().toUpperCase()) .isEqualTo(anotherTenant.toUpperCase()); @@ -200,7 +200,7 @@ class MultiTenancyEntityTest extends AbstractJpaIntegrationTest { return runAsTenant(tenant, () -> testdataFactory.createDistributionSet()); } - private Slice findDistributionSetForTenant(final String tenant) throws Exception { + private Slice findDistributionSetForTenant(final String tenant) throws Exception { return runAsTenant(tenant, () -> distributionSetManagement.findByCompleted(true, PAGE)); } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/TestConfiguration.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/TestConfiguration.java index 0a17a1be5..8e33265eb 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/TestConfiguration.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/TestConfiguration.java @@ -157,25 +157,6 @@ public class TestConfiguration implements AsyncConfigurer { return SystemManagementHolder.getInstance(); } - @Bean - TestdataFactory testdataFactory( - final ControllerManagement controllerManagement, final ArtifactManagement artifactManagement, - final SoftwareModuleManagement softwareModuleManagement, final SoftwareModuleTypeManagement softwareModuleTypeManagement, - final DistributionSetManagement distributionSetManagement, - final DistributionSetInvalidationManagement distributionSetInvalidationManagement, - final DistributionSetTypeManagement distributionSetTypeManagement, - final TargetManagement targetManagement, final TargetFilterQueryManagement targetFilterQueryManagement, - final TargetTypeManagement targetTypeManagement, final TargetTagManagement targetTagManagement, - final DeploymentManagement deploymentManagement, final DistributionSetTagManagement distributionSetTagManagement, - final RolloutManagement rolloutManagement, final RolloutHandler rolloutHandler, - final QuotaManagement quotaManagement, - final EntityFactory entityFactory, final TenantAware tenantAware) { - return new TestdataFactory(controllerManagement, artifactManagement, softwareModuleManagement, softwareModuleTypeManagement, - distributionSetManagement, distributionSetInvalidationManagement, distributionSetTypeManagement, targetManagement, - targetFilterQueryManagement, targetTypeManagement, targetTagManagement, deploymentManagement, - distributionSetTagManagement, rolloutManagement, rolloutHandler, quotaManagement, entityFactory, tenantAware); - } - @Bean PropertyBasedArtifactUrlHandler testPropertyBasedArtifactUrlHandler(final ArtifactUrlHandlerProperties urlHandlerProperties) { return new PropertyBasedArtifactUrlHandler(urlHandlerProperties, ""); diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java index 7a43417c1..442ea2409 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java @@ -24,6 +24,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.NoSuchElementException; +import java.util.Optional; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; @@ -59,8 +60,10 @@ import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.DeploymentRequest; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult; +import org.eclipse.hawkbit.repository.model.DistributionSetTag; import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.RepositoryModelConstants; +import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.test.TestConfiguration; @@ -77,6 +80,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.bus.ServiceMatcher; import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.annotation.Import; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; @@ -104,6 +108,7 @@ import org.springframework.test.context.TestPropertySource; listeners = { EventVerifier.class, CleanupTestExecutionListener.class }, mergeMode = MergeMode.MERGE_WITH_DEFAULTS) @TestPropertySource(properties = "spring.main.allow-bean-definition-overriding=true") +@Import(TestdataFactory.class) @SuppressWarnings("java:S6813") // constructor injects are not possible for test classes public abstract class AbstractIntegrationTest { @@ -122,13 +127,15 @@ public abstract class AbstractIntegrationTest { @Autowired protected EntityFactory entityFactory; @Autowired - protected SoftwareModuleManagement softwareModuleManagement; + protected SoftwareModuleManagement softwareModuleManagement; @Autowired - protected SoftwareModuleTypeManagement softwareModuleTypeManagement; + protected SoftwareModuleTypeManagement softwareModuleTypeManagement; @Autowired - protected DistributionSetManagement distributionSetManagement; + protected DistributionSetManagement distributionSetManagement; @Autowired - protected DistributionSetTypeManagement distributionSetTypeManagement; + protected DistributionSetTagManagement distributionSetTagManagement; + @Autowired + protected DistributionSetTypeManagement distributionSetTypeManagement; @Autowired protected ControllerManagement controllerManagement; @Autowired @@ -140,8 +147,6 @@ public abstract class AbstractIntegrationTest { @Autowired protected TargetTagManagement targetTagManagement; @Autowired - protected DistributionSetTagManagement distributionSetTagManagement; - @Autowired protected DeploymentManagement deploymentManagement; @Autowired protected ConfirmationManagement confirmationManagement; @@ -205,17 +210,17 @@ public abstract class AbstractIntegrationTest { osType = SecurityContextSwitch .callAsPrivileged(() -> testdataFactory.findOrCreateSoftwareModuleType(TestdataFactory.SM_TYPE_OS)); osType = SecurityContextSwitch.callAsPrivileged(() -> softwareModuleTypeManagement - .update(entityFactory.softwareModuleType().update(osType.getId()).description(description))); + .update(SoftwareModuleTypeManagement.Update.builder().id(osType.getId()).description(description).build())); appType = SecurityContextSwitch.callAsPrivileged( () -> testdataFactory.findOrCreateSoftwareModuleType(TestdataFactory.SM_TYPE_APP, Integer.MAX_VALUE)); appType = SecurityContextSwitch.callAsPrivileged(() -> softwareModuleTypeManagement - .update(entityFactory.softwareModuleType().update(appType.getId()).description(description))); + .update(SoftwareModuleTypeManagement.Update.builder().id(appType.getId()).description(description).build())); runtimeType = SecurityContextSwitch .callAsPrivileged(() -> testdataFactory.findOrCreateSoftwareModuleType(TestdataFactory.SM_TYPE_RT)); runtimeType = SecurityContextSwitch.callAsPrivileged(() -> softwareModuleTypeManagement - .update(entityFactory.softwareModuleType().update(runtimeType.getId()).description(description))); + .update(SoftwareModuleTypeManagement.Update.builder().id(runtimeType.getId()).description(description).build())); standardDsType = SecurityContextSwitch.callAsPrivileged(() -> testdataFactory.findOrCreateDefaultTestDsType()); @@ -273,6 +278,14 @@ public abstract class AbstractIntegrationTest { return Awaitility.await().atLeast(AT_LEAST).pollInterval(POLL_INTERVAL).atMost(TIMEOUT); } + protected DistributionSetType defaultDsType() { + return systemManagement.getTenantMetadata().getDefaultDsType(); + } + + protected SoftwareModuleType getASmType() { + return defaultDsType().getMandatoryModuleTypes().stream().findAny().orElseThrow(); + } + protected static Action getFirstAssignedAction( final DistributionSetAssignmentResult distributionSetAssignmentResult) { return distributionSetAssignmentResult.getAssignedEntity().stream().findFirst() @@ -422,7 +435,15 @@ public abstract class AbstractIntegrationTest { } protected Long getOsModule(final DistributionSet ds) { - return ds.findFirstModuleByType(osType).orElseThrow(NoSuchElementException::new).getId(); + return findFirstModuleByType(ds, osType).orElseThrow(NoSuchElementException::new).getId(); + } + + protected Optional findFirstModuleByType(final DistributionSet ds, final SoftwareModuleType type) { + return ds.getModules().stream().filter(module -> module.getType().equals(type)).findAny(); + } + + protected Optional findFirstModuleByType(final DistributionSetManagement.Create dsCreate, final SoftwareModuleType type) { + return dsCreate.getModules().stream().filter(module -> module.getType().equals(type)).findAny(); } protected Action prepareFinishedUpdate() { 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 2492b9e32..94f5d6c62 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 @@ -19,11 +19,12 @@ import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.security.SecureRandom; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.NoSuchElementException; +import java.util.Set; import java.util.UUID; import java.util.stream.IntStream; @@ -75,19 +76,24 @@ 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.Tag; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.repository.model.TargetTag; import org.eclipse.hawkbit.repository.model.TargetType; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.tenancy.TenantAware; +import org.springframework.context.annotation.Profile; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; import org.springframework.util.ObjectUtils; /** * Data generator utility for tests. */ +@Service +@Profile("test") @SuppressWarnings("java:S107") public class TestdataFactory { @@ -144,17 +150,17 @@ public class TestdataFactory { private final ControllerManagement controllerManagement; private final ArtifactManagement artifactManagement; - private final SoftwareModuleManagement softwareModuleManagement; - private final SoftwareModuleTypeManagement softwareModuleTypeManagement; - private final DistributionSetManagement distributionSetManagement; + private final SoftwareModuleManagement softwareModuleManagement; + private final SoftwareModuleTypeManagement softwareModuleTypeManagement; + private final DistributionSetManagement distributionSetManagement; + private final DistributionSetTagManagement distributionSetTagManagement; + private final DistributionSetTypeManagement distributionSetTypeManagement; private final DistributionSetInvalidationManagement distributionSetInvalidationManagement; - private final DistributionSetTypeManagement distributionSetTypeManagement; private final TargetManagement targetManagement; private final TargetFilterQueryManagement targetFilterQueryManagement; private final TargetTypeManagement targetTypeManagement; private final TargetTagManagement targetTagManagement; private final DeploymentManagement deploymentManagement; - private final DistributionSetTagManagement distributionSetTagManagement; private final RolloutManagement rolloutManagement; private final RolloutHandler rolloutHandler; private final QuotaManagement quotaManagement; @@ -163,13 +169,15 @@ public class TestdataFactory { public TestdataFactory( final ControllerManagement controllerManagement, final ArtifactManagement artifactManagement, - final SoftwareModuleManagement softwareModuleManagement, final SoftwareModuleTypeManagement softwareModuleTypeManagement, - final DistributionSetManagement distributionSetManagement, + final SoftwareModuleManagement softwareModuleManagement, + final SoftwareModuleTypeManagement softwareModuleTypeManagement, + final DistributionSetManagement distributionSetManagement, + final DistributionSetTypeManagement distributionSetTypeManagement, + final DistributionSetTagManagement distributionSetTagManagement, final DistributionSetInvalidationManagement distributionSetInvalidationManagement, - final DistributionSetTypeManagement distributionSetTypeManagement, final TargetManagement targetManagement, final TargetFilterQueryManagement targetFilterQueryManagement, final TargetTypeManagement targetTypeManagement, final TargetTagManagement targetTagManagement, - final DeploymentManagement deploymentManagement, final DistributionSetTagManagement distributionSetTagManagement, + final DeploymentManagement deploymentManagement, final RolloutManagement rolloutManagement, final RolloutHandler rolloutHandler, final QuotaManagement quotaManagement, final EntityFactory entityFactory, final TenantAware tenantAware) { @@ -177,14 +185,14 @@ public class TestdataFactory { this.softwareModuleManagement = softwareModuleManagement; this.softwareModuleTypeManagement = softwareModuleTypeManagement; this.distributionSetManagement = distributionSetManagement; - this.distributionSetInvalidationManagement = distributionSetInvalidationManagement; + this.distributionSetTagManagement = distributionSetTagManagement; this.distributionSetTypeManagement = distributionSetTypeManagement; + this.distributionSetInvalidationManagement = distributionSetInvalidationManagement; this.targetManagement = targetManagement; this.targetFilterQueryManagement = targetFilterQueryManagement; this.targetTypeManagement = targetTypeManagement; this.targetTagManagement = targetTagManagement; this.deploymentManagement = deploymentManagement; - this.distributionSetTagManagement = distributionSetTagManagement; this.entityFactory = entityFactory; this.artifactManagement = artifactManagement; this.rolloutManagement = rolloutManagement; @@ -298,32 +306,43 @@ public class TestdataFactory { * @return {@link DistributionSet} entity. */ 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(randomDescriptionLong()) - .vendor(prefix + " vendor Limited, California")); + final SoftwareModule appMod = softwareModuleManagement.create( + SoftwareModuleManagement.Create.builder() + .type(findOrCreateSoftwareModuleType(SM_TYPE_APP, Integer.MAX_VALUE)) + .name(prefix + SM_TYPE_APP) + .version(version + "." + new SecureRandom().nextInt(100)) + .description(randomDescriptionLong()) + .vendor(prefix + " vendor Limited, California") + .build()); final SoftwareModule runtimeMod = softwareModuleManagement - .create(entityFactory.softwareModule().create().type(findOrCreateSoftwareModuleType(SM_TYPE_RT)) - .name(prefix + "app runtime").version(version + "." + new SecureRandom().nextInt(100)) - .description(randomDescriptionLong()).vendor(prefix + " vendor GmbH, Stuttgart, Germany")); + .create(SoftwareModuleManagement.Create.builder() + .type(findOrCreateSoftwareModuleType(SM_TYPE_RT)) + .name(prefix + "app runtime") + .version(version + "." + new SecureRandom().nextInt(100)) + .description(randomDescriptionLong()).vendor(prefix + " vendor GmbH, Stuttgart, Germany") + .build()); final SoftwareModule osMod = softwareModuleManagement - .create(entityFactory.softwareModule().create().type(findOrCreateSoftwareModuleType(SM_TYPE_OS)) - .name(prefix + " Firmware").version(version + "." + new SecureRandom().nextInt(100)) - .description(randomDescriptionLong()).vendor(prefix + " vendor Limited Inc, California")); + .create(SoftwareModuleManagement.Create.builder() + .type(findOrCreateSoftwareModuleType(SM_TYPE_OS)) + .name(prefix + " Firmware") + .version(version + "." + new SecureRandom().nextInt(100)) + .description(randomDescriptionLong()).vendor(prefix + " vendor Limited Inc, California") + .build()); return distributionSetManagement.create( - entityFactory.distributionSet().create() + DistributionSetManagement.Create.builder() .type(findOrCreateDefaultTestDsType()) .name(ObjectUtils.isEmpty(prefix) ? "DS" : prefix) .version(version) .description(randomDescriptionShort()) - .modules(Arrays.asList(osMod.getId(), runtimeMod.getId(), appMod.getId())) - .requiredMigrationStep(isRequiredMigrationStep)); + .modules(Set.of(osMod, runtimeMod, appMod)) + .requiredMigrationStep(isRequiredMigrationStep) + .build()); } /** * 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 @@ -349,10 +368,13 @@ public class TestdataFactory { public DistributionSet createDistributionSet( final String prefix, final String version, final boolean isRequiredMigrationStep, final Collection modules) { return distributionSetManagement.create( - entityFactory.distributionSet().create().name(prefix != null && !prefix.isEmpty() ? prefix : "DS") - .version(version).description(randomDescriptionShort()).type(findOrCreateDefaultTestDsType()) - .modules(modules.stream().map(SoftwareModule::getId).toList()) - .requiredMigrationStep(isRequiredMigrationStep)); + DistributionSetManagement.Create.builder() + .type(findOrCreateDefaultTestDsType()) + .name(prefix != null && !prefix.isEmpty() ? prefix : "DS") + .version(version).description(randomDescriptionShort()) + .modules(new HashSet<>(modules)) + .requiredMigrationStep(isRequiredMigrationStep) + .build()); } /** @@ -360,14 +382,14 @@ public class TestdataFactory { * {@link #SM_TYPE_APP}. * * @param prefix for {@link SoftwareModule}s and {@link DistributionSet}s name, vendor and description. - * @param version {@link DistributionSet#getVersion()} and {@link SoftwareModule#getVersion()} extended by a random number.updat + * @param version {@link DistributionSet#getVersion()} and {@link SoftwareModule#getVersion()} extended by a random number. * @param tags DistributionSet tags * @return {@link DistributionSet} entity. */ public DistributionSet createDistributionSet(final String prefix, final String version, final Collection tags) { final DistributionSet set = createDistributionSet(prefix, version, false); tags.forEach(tag -> distributionSetManagement.assignTag(List.of(set.getId()), tag.getId())); - return distributionSetManagement.get(set.getId()).get(); + return distributionSetManagement.get(set.getId()).orElseThrow(); } /** @@ -391,12 +413,13 @@ public class TestdataFactory { public List createDistributionSetsWithoutModules(final int number) { final List sets = new ArrayList<>(number); for (int i = 0; i < number; i++) { - sets.add(distributionSetManagement - .create(entityFactory.distributionSet().create() + sets.add(distributionSetManagement.create( + DistributionSetManagement.Create.builder() + .type(findOrCreateDefaultTestDsType()) .name("DS" + i) .version(DEFAULT_VERSION + "." + i) .description(randomDescriptionShort()) - .type(findOrCreateDefaultTestDsType()))); + .build())); } return sets; } @@ -427,11 +450,13 @@ public class TestdataFactory { * @return {@link DistributionSet} entity */ 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( + DistributionSetManagement.Create.builder() + .type(findOrCreateDefaultTestDsType()) + .name(name) + .version(version) + .description(DEFAULT_DESCRIPTION) + .build()); } /** @@ -538,13 +563,15 @@ public class TestdataFactory { * @return persisted {@link SoftwareModule}. */ public SoftwareModule createSoftwareModule(final String typeKey, final String prefix, final boolean encrypted) { - return softwareModuleManagement.create(entityFactory.softwareModule().create() - .type(findOrCreateSoftwareModuleType(typeKey)) - .name(prefix + typeKey) - .version(prefix + DEFAULT_VERSION) - .description(randomDescriptionShort()) - .vendor(DEFAULT_VENDOR) - .encrypted(encrypted)); + return softwareModuleManagement.create( + SoftwareModuleManagement.Create.builder() + .type(findOrCreateSoftwareModuleType(typeKey)) + .name(prefix + typeKey) + .version(prefix + DEFAULT_VERSION) + .description(randomDescriptionShort()) + .vendor(DEFAULT_VENDOR) + .encrypted(encrypted) + .build()); } /** @@ -597,7 +624,7 @@ public class TestdataFactory { * Creates {@link DistributionSet}s in repository including three {@link SoftwareModule}s of types {@link #SM_TYPE_OS}, {@link #SM_TYPE_RT} , * {@link #SM_TYPE_APP} with {@link #DEFAULT_VERSION} followed by an iterative number and {@link DistributionSet#isRequiredMigrationStep()} * false. - * + *

* In addition, it updates the created {@link DistributionSet}s and {@link SoftwareModule}s to ensure that * {@link BaseEntity#getLastModifiedAt()} and {@link BaseEntity#getLastModifiedBy()} is filled. * @@ -606,13 +633,13 @@ public class TestdataFactory { public DistributionSet createUpdatedDistributionSet() { DistributionSet set = createDistributionSet(""); set = distributionSetManagement.update( - entityFactory.distributionSet().update(set.getId()).description("Updated " + DEFAULT_DESCRIPTION)); + DistributionSetManagement.Update.builder().id(set.getId()).description("Updated " + DEFAULT_DESCRIPTION).build()); set.getModules().forEach(module -> softwareModuleManagement.update( - entityFactory.softwareModule().update(module.getId()).description("Updated " + DEFAULT_DESCRIPTION))); + SoftwareModuleManagement.Update.builder().id(module.getId()).description("Updated " + DEFAULT_DESCRIPTION).build())); // load also lazy stuff - return distributionSetManagement.getWithDetails(set.getId()).get(); + return distributionSetManagement.getWithDetails(set.getId()).orElseThrow(); } /** @@ -639,8 +666,10 @@ public class TestdataFactory { */ public DistributionSetType findOrCreateDistributionSetType(final String dsTypeKey, final String dsTypeName) { return distributionSetTypeManagement.findByKey(dsTypeKey) - .orElseGet(() -> distributionSetTypeManagement.create(entityFactory.distributionSetType().create() - .key(dsTypeKey).name(dsTypeName).description(randomDescriptionShort()).colour("black"))); + .map(DistributionSetType.class::cast) + .orElseGet(() -> distributionSetTypeManagement.create( + DistributionSetTypeManagement.Create.builder() + .key(dsTypeKey).name(dsTypeName).description(randomDescriptionShort()).colour("black").build())); } /** @@ -656,14 +685,16 @@ public class TestdataFactory { public DistributionSetType findOrCreateDistributionSetType(final String dsTypeKey, final String dsTypeName, final Collection mandatory, final Collection optional) { return distributionSetTypeManagement.findByKey(dsTypeKey) + .map(DistributionSetType.class::cast) .orElseGet(() -> distributionSetTypeManagement.create( - entityFactory.distributionSetType().create() + DistributionSetTypeManagement.Create.builder() .key(dsTypeKey) .name(dsTypeName) .description(randomDescriptionShort()) .colour("black") - .optional(optional.stream().map(SoftwareModuleType::getId).toList()) - .mandatory(mandatory.stream().map(SoftwareModuleType::getId).toList()))); + .mandatoryModuleTypes(new HashSet<>(mandatory)) + .optionalModuleTypes(new HashSet<>(optional)) + .build())); } /** @@ -686,11 +717,14 @@ public class TestdataFactory { */ public SoftwareModuleType findOrCreateSoftwareModuleType(final String key, final int maxAssignments) { return softwareModuleTypeManagement.findByKey(key) - .orElseGet(() -> softwareModuleTypeManagement.create(entityFactory.softwareModuleType().create() - .key(key) - .name(key) - .description(randomDescriptionShort()).colour("#ffffff") - .maxAssignments(maxAssignments))); + .map(SoftwareModuleType.class::cast) + .orElseGet(() -> softwareModuleTypeManagement.create( + SoftwareModuleTypeManagement.Create.builder() + .key(key) + .name(key) + .description(randomDescriptionShort()).colour("#ffffff") + .maxAssignments(maxAssignments) + .build())); } /** @@ -704,12 +738,14 @@ public class TestdataFactory { */ public DistributionSet createDistributionSet( final String name, final String version, final DistributionSetType type, final Collection modules) { - return distributionSetManagement.create(entityFactory.distributionSet().create() - .type(type) - .name(name) - .version(version) - .description(randomDescriptionShort()) - .modules(modules.stream().map(SoftwareModule::getId).toList())); + return distributionSetManagement.create( + DistributionSetManagement.Create.builder() + .type(type) + .name(name) + .version(version) + .description(randomDescriptionShort()) + .modules(new HashSet<>(modules)) + .build()); } /** @@ -722,15 +758,15 @@ public class TestdataFactory { * @param requiredMigrationStep {@link DistributionSet#isRequiredMigrationStep()} * @return the created {@link DistributionSet} */ - public DistributionSet generateDistributionSet( + public DistributionSetManagement.Create generateDistributionSet( final String name, final String version, final DistributionSetType type, final Collection modules, final boolean requiredMigrationStep) { - return entityFactory.distributionSet().create() + return DistributionSetManagement.Create.builder() .type(type) .name(name) .version(version) .description(randomDescriptionShort()) - .modules(modules.stream().map(SoftwareModule::getId).toList()) + .modules(new HashSet<>(modules)) .requiredMigrationStep(requiredMigrationStep) .build(); } @@ -744,7 +780,7 @@ public class TestdataFactory { * @param modules {@link DistributionSet#getModules()} * @return the created {@link DistributionSet} */ - public DistributionSet generateDistributionSet( + public DistributionSetManagement.Create generateDistributionSet( final String name, final String version, final DistributionSetType type, final Collection modules) { return generateDistributionSet(name, version, type, modules, false); } @@ -755,7 +791,7 @@ public class TestdataFactory { * @param name {@link DistributionSet#getName()} * @return the generated {@link DistributionSet} */ - public DistributionSet generateDistributionSet(final String name) { + public DistributionSetManagement.Create generateDistributionSet(final String name) { return generateDistributionSet(name, DEFAULT_VERSION, findOrCreateDefaultTestDsType(), Collections.emptyList(), false); } @@ -828,7 +864,7 @@ public class TestdataFactory { * * @param numberOfTargets number of targets to create * @param prefix prefix used for the controller ID and description - * @return set of {@link Target} + * @return list of {@link Target} */ public List createTargets(final int numberOfTargets, final String prefix) { return createTargets(numberOfTargets, prefix, prefix); @@ -840,7 +876,7 @@ public class TestdataFactory { * @param numberOfTargets number of targets to create * @param controllerIdPrefix prefix used for the controller ID * @param descriptionPrefix prefix used for the description - * @return set of {@link Target} + * @return list of {@link Target} */ public List createTargets(final int numberOfTargets, final String controllerIdPrefix, final String descriptionPrefix) { final List targets = IntStream.range(0, numberOfTargets) @@ -858,7 +894,7 @@ public class TestdataFactory { * @param controllerIdPrefix prefix used for the controller ID * @param descriptionPrefix prefix used for the description * @param lastTargetQuery last time the target polled - * @return set of {@link Target} + * @return list of {@link Target} */ public List createTargets( final int numberOfTargets, final String controllerIdPrefix, final String descriptionPrefix, final Long lastTargetQuery) { @@ -878,7 +914,7 @@ public class TestdataFactory { * @return the created set of {@link TargetTag}s */ public List createTargetTags(final int number, final String tagPrefix) { - final List result = new ArrayList<>(number); + final List> result = new ArrayList<>(number); for (int i = 0; i < number; i++) { result.add(entityFactory.tag().create().name(tagPrefix + i).description(tagPrefix + i).colour(String.valueOf(i))); } @@ -892,11 +928,12 @@ public class TestdataFactory { * @return the persisted {@link DistributionSetTag}s */ public List createDistributionSetTags(final int number) { - final List result = new ArrayList<>(number); + final List result = new ArrayList<>(number); for (int i = 0; i < number; i++) { - result.add(entityFactory.tag().create().name("tag" + i).description("tagdesc" + i).colour(String.valueOf(i))); + result.add( + DistributionSetTagManagement.Create.builder().name("tag" + i).description("tagdesc" + i).colour(String.valueOf(i)).build()); } - return distributionSetTagManagement.create(result); + return distributionSetTagManagement.create(result).stream().map(DistributionSetTag.class::cast).toList(); } /** @@ -908,7 +945,7 @@ public class TestdataFactory { * @return updated {@link Action}. */ public List sendUpdateActionStatusToTargets(final Collection targets, final Status status, final String message) { - return sendUpdateActionStatusToTargets(targets, status, Arrays.asList(message)); + return sendUpdateActionStatusToTargets(targets, status, List.of(message)); } /** @@ -1026,7 +1063,7 @@ public class TestdataFactory { // Run here, because Scheduler is disabled during tests rolloutHandleAll(); - return rolloutManagement.get(rollout.getId()).get(); + return rolloutManagement.get(rollout.getId()).orElseThrow(); } /** @@ -1202,9 +1239,12 @@ public class TestdataFactory { * @return created incomplete {@link DistributionSet} */ public DistributionSet createIncompleteDistributionSet() { - return distributionSetManagement.create(entityFactory.distributionSet().create() - .name(UUID.randomUUID().toString()).version(DEFAULT_VERSION).description(randomDescriptionShort()) - .type(findOrCreateDefaultTestDsType()).requiredMigrationStep(false)); + return distributionSetManagement.create( + DistributionSetManagement.Create.builder() + .name(UUID.randomUUID().toString()).version(DEFAULT_VERSION).description(randomDescriptionShort()) + .type(findOrCreateDefaultTestDsType()) + .requiredMigrationStep(false) + .build()); } private static String randomDescriptionShort() { @@ -1248,7 +1288,7 @@ public class TestdataFactory { } private List createTargets(final Collection targetCreates) { - // init new instance of array list since the TargetManagement#create will provide a unmodifiable list + // init new instance of array list since the TargetManagement#create will provide an unmodifiable list return new ArrayList<>(targetManagement.create(targetCreates)); } diff --git a/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/JsonBuilder.java b/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/JsonBuilder.java index 75eff71e5..77cf7e0dd 100644 --- a/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/JsonBuilder.java +++ b/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/JsonBuilder.java @@ -18,13 +18,13 @@ import java.util.Map; import lombok.AccessLevel; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.eclipse.hawkbit.repository.model.DistributionSet; -import org.eclipse.hawkbit.repository.model.DistributionSetType; +import org.eclipse.hawkbit.repository.DistributionSetManagement; +import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; +import org.eclipse.hawkbit.repository.SoftwareModuleManagement; +import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; import org.eclipse.hawkbit.repository.model.RolloutGroup; 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.SoftwareModuleType; import org.eclipse.hawkbit.repository.model.Tag; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetType; @@ -79,12 +79,12 @@ public class JsonBuilder { return builder.toString(); } - public static String softwareModules(final List modules) throws JSONException { + public static String softwareModules(final List modules) throws JSONException { final StringBuilder builder = new StringBuilder(); builder.append("["); int i = 0; - for (final SoftwareModule module : modules) { + for (final SoftwareModuleManagement.Create module : modules) { builder.append(new JSONObject().put("name", module.getName()).put("description", module.getDescription()) .put("type", module.getType().getKey()).put("id", Long.MAX_VALUE).put("vendor", module.getVendor()) .put("version", module.getVersion()).put("createdAt", "0").put("updatedAt", "0") @@ -100,12 +100,12 @@ public class JsonBuilder { return builder.toString(); } - public static String softwareModuleTypes(final List types) throws JSONException { + public static String softwareModuleTypes(final List types) throws JSONException { final StringBuilder builder = new StringBuilder(); builder.append("["); int i = 0; - for (final SoftwareModuleType module : types) { + for (final SoftwareModuleTypeManagement.Create module : types) { builder.append(new JSONObject().put("name", module.getName()).put("description", module.getDescription()) .put("colour", module.getColour()).put("id", Long.MAX_VALUE).put("key", module.getKey()) .put("maxAssignments", module.getMaxAssignments()).put("createdAt", "0").put("updatedAt", "0") @@ -120,10 +120,30 @@ public class JsonBuilder { return builder.toString(); } - public static String distributionSetTypes(final List types) throws JSONException { + public static String softwareModuleTypeCreates(final List creates) throws JSONException { + final StringBuilder builder = new StringBuilder(); + + builder.append("["); + int i = 0; + for (final SoftwareModuleTypeManagement.Create module : creates) { + builder.append(new JSONObject().put("name", module.getName()).put("description", module.getDescription()) + .put("colour", module.getColour()).put("id", Long.MAX_VALUE).put("key", module.getKey()) + .put("maxAssignments", module.getMaxAssignments()).put("createdAt", "0").put("updatedAt", "0") + .put("createdBy", "fghdfkjghdfkjh").put("updatedBy", "fghdfkjghdfkjh").toString()); + + if (++i < creates.size()) { + builder.append(","); + } + } + builder.append("]"); + + return builder.toString(); + } + + public static String distributionSetTypes(final List types) throws JSONException { final JSONArray result = new JSONArray(); - for (final DistributionSetType type : types) { + for (final DistributionSetTypeManagement.Create type : types) { final JSONArray osmTypes = new JSONArray(); type.getOptionalModuleTypes().forEach(smt -> { try { @@ -153,7 +173,7 @@ public class JsonBuilder { return result.toString(); } - public static String distributionSets(final List sets) { + public static String distributionSets(final List sets) { final JSONArray setsJson = new JSONArray(); sets.forEach(set -> { @@ -165,10 +185,9 @@ public class JsonBuilder { }); return setsJson.toString(); - } - public static JSONObject distributionSet(final DistributionSet set) throws JSONException { + public static JSONObject distributionSet(final DistributionSetManagement.Create set) throws JSONException { final List modules = set.getModules().stream().map(module -> { try { return new JSONObject().put("id", module.getId()); @@ -182,8 +201,7 @@ public class JsonBuilder { .put("type", set.getType() == null ? null : set.getType().getKey()).put("id", Long.MAX_VALUE) .put("version", set.getVersion()).put("createdAt", "0").put("updatedAt", "0") .put("createdBy", "fghdfkjghdfkjh").put("updatedBy", "fghdfkjghdfkjh") - .put("requiredMigrationStep", set.isRequiredMigrationStep()).put("modules", new JSONArray(modules)); - + .put("requiredMigrationStep", set.getRequiredMigrationStep()).put("modules", new JSONArray(modules)); } public static String targets(final List targets, final boolean withToken) throws JSONException { diff --git a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/SpPermission.java b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/SpPermission.java index 0d7064efc..bde8facc5 100644 --- a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/SpPermission.java +++ b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/SpPermission.java @@ -18,7 +18,6 @@ import java.util.List; import lombok.AccessLevel; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.GrantedAuthority; import org.springframework.util.function.SingletonSupplier; @@ -37,21 +36,9 @@ import org.springframework.util.function.SingletonSupplier; @Slf4j public final class SpPermission { - /** - * Permission to add new targets including their meta information. - */ public static final String CREATE_TARGET = "CREATE_TARGET"; - /** - * Permission to read the targets (list and filter). - */ public static final String READ_TARGET = "READ_TARGET"; - /** - * Permission to change/edit/update targets and to assign updates. - */ public static final String UPDATE_TARGET = "UPDATE_TARGET"; - /** - * Permission to delete targets. - */ public static final String DELETE_TARGET = "DELETE_TARGET"; /** * Permission to read the target security token. The security token is security @@ -66,31 +53,14 @@ public final class SpPermission { public static final String UPDATE_TARGET_TYPE = "UPDATE_TARGET_TYPE"; public static final String DELETE_TARGET_TYPE = "DELETE_TARGET_TYPE"; - public static final String CREATE_DISTRIBUTION_SET = "CREATE_DISTRIBUTION_SET"; public static final String READ_DISTRIBUTION_SET = "READ_DISTRIBUTION_SET"; public static final String UPDATE_DISTRIBUTION_SET = "UPDATE_DISTRIBUTION_SET"; - public static final String DELETE_DISTRIBUTION_SET = "DELETE_DISTRIBUTION_SET"; - /** - * Permission to read distributions and artifacts. - */ public static final String READ_REPOSITORY = "READ_REPOSITORY"; - /** - * Permission to edit/update distributions and artifacts. - */ public static final String UPDATE_REPOSITORY = "UPDATE_REPOSITORY"; - /** - * Permission to add distributions and artifacts. - */ public static final String CREATE_REPOSITORY = "CREATE_REPOSITORY"; - /** - * Permission to delete distributions and artifacts. - */ public static final String DELETE_REPOSITORY = "DELETE_REPOSITORY"; - /** - * Permission to download repository artifacts of a software module. - */ public static final String DOWNLOAD_REPOSITORY_ARTIFACT = "DOWNLOAD_REPOSITORY_ARTIFACT"; /** @@ -109,51 +79,38 @@ public final class SpPermission { */ public static final String TENANT_CONFIGURATION = "TENANT_CONFIGURATION"; - /** - * Permission to create a rollout. - */ public static final String CREATE_ROLLOUT = "CREATE_ROLLOUT"; - /** - * Permission to read a rollout. - */ public static final String READ_ROLLOUT = "READ_ROLLOUT"; - /** - * Permission to update a rollout. - */ public static final String UPDATE_ROLLOUT = "UPDATE_ROLLOUT"; - /** - * Permission to delete a rollout. - */ public static final String DELETE_ROLLOUT = "DELETE_ROLLOUT"; - /** - * Permission to approve or deny a rollout prior to starting. - */ + /** Permission to approve or deny a rollout prior to starting. */ public static final String APPROVE_ROLLOUT = "APPROVE_ROLLOUT"; - /** - * Permission to start/stop/resume a rollout. - */ + /** Permission to start/stop/resume a rollout. */ public static final String HANDLE_ROLLOUT = "HANDLE_ROLLOUT"; - /** - * Permission to administrate the system on a global, i.e. tenant independent scale. That includes the deletion of tenants. - */ + /** Permission to administrate the system on a global, i.e. tenant independent scale. That includes the deletion of tenants. */ public static final String SYSTEM_ADMIN = "SYSTEM_ADMIN"; - private static final String IMPLIES = " > "; - private static final String LINE_BREAK = "\n"; - public static final String TARGET_HIERARCHY = - CREATE_TARGET + IMPLIES + CREATE_TARGET_TYPE + LINE_BREAK + - READ_TARGET + IMPLIES + READ_TARGET_TYPE + LINE_BREAK + - UPDATE_TARGET + IMPLIES + UPDATE_TARGET_TYPE + LINE_BREAK + - DELETE_TARGET + IMPLIES + DELETE_TARGET_TYPE + LINE_BREAK; - public static final String REPOSITORY_HIERARCHY = - CREATE_REPOSITORY + IMPLIES + CREATE_DISTRIBUTION_SET + LINE_BREAK + - READ_REPOSITORY + IMPLIES + READ_DISTRIBUTION_SET + LINE_BREAK + - UPDATE_REPOSITORY + IMPLIES + UPDATE_DISTRIBUTION_SET + LINE_BREAK + - DELETE_REPOSITORY + IMPLIES + DELETE_DISTRIBUTION_SET + LINE_BREAK; - public static final String TENANT_CONFIGURATION_HIERARCHY = - TENANT_CONFIGURATION + IMPLIES + READ_TENANT_CONFIGURATION + LINE_BREAK + - TENANT_CONFIGURATION + IMPLIES + READ_GATEWAY_SEC_TOKEN + LINE_BREAK; + public static final String TARGET_HIERARCHY = """ + CREATE_TARGET > CREATE_TARGET_TYPE + READ_TARGET > READ_TARGET_TYPE + UPDATE_TARGET > UPDATE_TARGET_TYPE + DELETE_TARGET > DELETE_TARGET_TYPE + """; + public static final String REPOSITORY_HIERARCHY = """ + CREATE_REPOSITORY > CREATE_DISTRIBUTION_SET + READ_REPOSITORY > READ_DISTRIBUTION_SET + UPDATE_REPOSITORY > UPDATE_DISTRIBUTION_SET + DELETE_REPOSITORY > DELETE_DISTRIBUTION_SET + CREATE_REPOSITORY > CREATE_SOFTWARE_MODULE + READ_REPOSITORY > READ_SOFTWARE_MODULE + UPDATE_REPOSITORY > UPDATE_SOFTWARE_MODULE + DELETE_REPOSITORY > DELETE_SOFTWARE_MODULE + """; + public static final String TENANT_CONFIGURATION_HIERARCHY = """ + TENANT_CONFIGURATION > READ_TENANT_CONFIGURATION + TENANT_CONFIGURATION > READ_GATEWAY_SECURITY_TOKEN + """; private static final SingletonSupplier> ALL_AUTHORITIES = SingletonSupplier.of(() -> { final List allPermissions = new ArrayList<>(); @@ -171,6 +128,7 @@ public final class SpPermission { } return Collections.unmodifiableList(allPermissions); }); + /** * Return all permission. * diff --git a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/SpringEvalExpressions.java b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/SpringEvalExpressions.java index 72409659a..1eb0db066 100644 --- a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/SpringEvalExpressions.java +++ b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/SpringEvalExpressions.java @@ -66,13 +66,12 @@ public final class SpringEvalExpressions { public static final String HAS_AUTH_READ_TARGET_TYPE = HAS_AUTH_PREFIX + SpPermission.READ_TARGET_TYPE + HAS_AUTH_SUFFIX; public static final String HAS_AUTH_DELETE_TARGET_TYPE = HAS_AUTH_PREFIX + SpPermission.DELETE_TARGET_TYPE + HAS_AUTH_SUFFIX; - public static final String HAS_AUTH_UPDATE_DISTRIBUTION_SET = HAS_AUTH_PREFIX + SpPermission.UPDATE_DISTRIBUTION_SET + HAS_AUTH_SUFFIX; - public static final String HAS_AUTH_READ_DISTRIBUTION_SET = HAS_AUTH_PREFIX + SpPermission.READ_DISTRIBUTION_SET + HAS_AUTH_SUFFIX; + // evaluated to _ (e.g. DISTRIBUTION_SET_CREATE) + public static final String HAS_CREATE_REPOSITORY = "hasPermission(#root, 'CREATE')"; + public static final String HAS_READ_REPOSITORY = "hasPermission(#root, 'READ')"; + public static final String HAS_UPDATE_REPOSITORY = "hasPermission(#root, 'UPDATE')"; + public static final String HAS_DELETE_REPOSITORY = "hasPermission(#root, 'DELETE')"; - public static final String HAS_AUTH_CREATE_REPOSITORY = HAS_AUTH_PREFIX + SpPermission.CREATE_REPOSITORY + HAS_AUTH_SUFFIX; - public static final String HAS_AUTH_READ_REPOSITORY = HAS_AUTH_PREFIX + SpPermission.READ_REPOSITORY + HAS_AUTH_SUFFIX; - public static final String HAS_AUTH_UPDATE_REPOSITORY = HAS_AUTH_PREFIX + SpPermission.UPDATE_REPOSITORY + HAS_AUTH_SUFFIX; - public static final String HAS_AUTH_DELETE_REPOSITORY = HAS_AUTH_PREFIX + SpPermission.DELETE_REPOSITORY + HAS_AUTH_SUFFIX; public static final String HAS_AUTH_DOWNLOAD_ARTIFACT = HAS_AUTH_PREFIX + SpPermission.DOWNLOAD_REPOSITORY_ARTIFACT + HAS_AUTH_SUFFIX; public static final String HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET = BRACKET_OPEN + HAS_AUTH_PREFIX + SpPermission.READ_REPOSITORY + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + SpPermission.UPDATE_TARGET + HAS_AUTH_SUFFIX