diff --git a/hawkbit-repository/hawkbit-repository-core/pom.xml b/hawkbit-repository/hawkbit-repository-core/pom.xml index 980dbaee7..bb7163c48 100644 --- a/hawkbit-repository/hawkbit-repository-core/pom.xml +++ b/hawkbit-repository/hawkbit-repository-core/pom.xml @@ -29,7 +29,7 @@ org.apache.commons - commons-lang3 + commons-text com.github.ben-manes.caffeine diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/rsql/VirtualPropertyResolver.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/rsql/VirtualPropertyResolver.java index 1d99864ea..ba7b243fe 100644 --- a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/rsql/VirtualPropertyResolver.java +++ b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/rsql/VirtualPropertyResolver.java @@ -11,8 +11,8 @@ package org.eclipse.hawkbit.repository.rsql; import java.io.Serial; -import org.apache.commons.lang3.text.StrLookup; -import org.apache.commons.lang3.text.StrSubstitutor; +import org.apache.commons.text.StringSubstitutor; +import org.apache.commons.text.lookup.StringLookupFactory; import org.eclipse.hawkbit.repository.TimestampCalculator; /** @@ -41,31 +41,30 @@ import org.eclipse.hawkbit.repository.TimestampCalculator; * configuration. * */ -public class VirtualPropertyResolver extends StrLookup implements VirtualPropertyReplacer { +public class VirtualPropertyResolver implements VirtualPropertyReplacer { @Serial private static final long serialVersionUID = 1L; - private transient StrSubstitutor substitutor; - - @Override - public String lookup(final String rhs) { - String resolved = null; - - if ("now_ts".equalsIgnoreCase(rhs)) { - resolved = String.valueOf(System.currentTimeMillis()); - } else if ("overdue_ts".equalsIgnoreCase(rhs)) { - resolved = String.valueOf(TimestampCalculator.calculateOverdueTimestamp()); - } - return resolved; - } + private transient StringSubstitutor substitutor; @Override public String replace(final String input) { if (substitutor == null) { - substitutor = new StrSubstitutor(this, StrSubstitutor.DEFAULT_PREFIX, StrSubstitutor.DEFAULT_SUFFIX, - StrSubstitutor.DEFAULT_ESCAPE); + substitutor = new StringSubstitutor( + StringLookupFactory.builder().get().functionStringLookup(this::lookup), + StringSubstitutor.DEFAULT_PREFIX, StringSubstitutor.DEFAULT_SUFFIX, StringSubstitutor.DEFAULT_ESCAPE); } return substitutor.replace(input); } + + private String lookup(final String rhs) { + if ("now_ts".equalsIgnoreCase(rhs)) { + return String.valueOf(System.currentTimeMillis()); + } else if ("overdue_ts".equalsIgnoreCase(rhs)) { + return String.valueOf(TimestampCalculator.calculateOverdueTimestamp()); + } else { + return null; + } + } } \ No newline at end of file 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 index bcea738b2..e8eb42ff4 100644 --- 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 @@ -12,9 +12,11 @@ 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 @@ -23,20 +25,24 @@ import org.springframework.data.repository.core.support.RepositoryFactorySupport @SuppressWarnings("java:S119") // java:S119 - ID is inherited from JpaRepositoryFactoryBean public class CustomBaseRepositoryFactoryBean, S, ID> extends JpaRepositoryFactoryBean { - private final BaseRepositoryTypeProvider baseRepoProvider; + 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, final BaseRepositoryTypeProvider baseRepoProvider) { + 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(final EntityManager entityManager) { + 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/RepositoryApplicationConfiguration.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java index 03646054e..51ea38ad3 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java @@ -187,7 +187,6 @@ import org.springframework.data.jpa.repository.config.EnableJpaAuditing; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.integration.support.locks.LockRegistry; import org.springframework.lang.NonNull; -import org.springframework.orm.jpa.vendor.Database; import org.springframework.retry.annotation.EnableRetry; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.transaction.PlatformTransactionManager; @@ -459,8 +458,7 @@ public class RepositoryApplicationConfiguration { } /** - * @return the singleton instance of the - * {@link AfterTransactionCommitExecutorHolder} + * @return the singleton instance of the {@link AfterTransactionCommitExecutorHolder} */ @Bean AfterTransactionCommitExecutorHolder afterTransactionCommitExecutorHolder() { @@ -475,6 +473,17 @@ public class RepositoryApplicationConfiguration { 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. * @@ -1027,18 +1036,6 @@ public class RepositoryApplicationConfiguration { tenantAware, lockRegistry, systemSecurityContext); } - /** - * Default {@link BaseRepositoryTypeProvider} bean always provides the - * NoCountBaseRepository - * - * @return a {@link BaseRepositoryTypeProvider} bean - */ - @Bean - @ConditionalOnMissingBean - BaseRepositoryTypeProvider baseRepositoryTypeProvider() { - return new HawkbitBaseRepository.RepositoryTypeProvider(); - } - /** * Default artifact encryption service bean that internally uses * {@link ArtifactEncryption} and {@link ArtifactEncryptionSecretsStore} beans diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtilityTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtilityTest.java index 2366c879d..bdef4fd22 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtilityTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtilityTest.java @@ -437,10 +437,7 @@ class RSQLUtilityTest { .toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); // verification - verify(macroResolver).lookup(overdueProp); - // the macro is already replaced when passed to #lessThanOrEqualTo -> - // the method is never invoked with the - // placeholder: + // the macro is already replaced when passed to #lessThanOrEqualTo -> the method is never invoked with the placeholder: verify(criteriaBuilderMock, never()).lessThanOrEqualTo(pathOfString(baseSoftwareModuleRootMock), overduePropPlaceholder); } @@ -462,9 +459,7 @@ class RSQLUtilityTest { .toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); // verification - verify(macroResolver).lookup(overdueProp); - // the macro is unknown and hence never replaced -> #lessThanOrEqualTo - // is invoked with the placeholder: + // the macro is unknown and hence never replaced -> #lessThanOrEqualTo is invoked with the placeholder: verify(criteriaBuilderMock).lessThanOrEqualTo(pathOfString(baseSoftwareModuleRootMock), overduePropPlaceholder); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/VirtualPropertyResolverTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/VirtualPropertyResolverTest.java index 857736bd0..303b1c471 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/VirtualPropertyResolverTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/VirtualPropertyResolverTest.java @@ -17,7 +17,7 @@ import java.util.concurrent.Callable; import io.qameta.allure.Description; import io.qameta.allure.Feature; import io.qameta.allure.Story; -import org.apache.commons.lang3.text.StrSubstitutor; +import org.apache.commons.text.StringSubstitutor; import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.model.TenantConfigurationValue; import org.eclipse.hawkbit.repository.model.helper.SystemSecurityContextHolder; @@ -31,7 +31,6 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.mockito.Mockito; -import org.mockito.Spy; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.bean.override.mockito.MockitoBean; @@ -47,13 +46,12 @@ class VirtualPropertyResolverTest { private static final TenantConfigurationValue TEST_POLLING_OVERDUE_TIME_INTERVAL = TenantConfigurationValue. builder().value("00:07:37").build(); - @Spy - private final VirtualPropertyResolver resolverUnderTest = new VirtualPropertyResolver(); @MockitoBean private TenantConfigurationManagement confMgmt; @MockitoBean private SystemSecurityContext securityContext; - private StrSubstitutor substitutor; + + private final VirtualPropertyResolver substitutor = new VirtualPropertyResolver(); @BeforeEach void before() { @@ -61,9 +59,6 @@ class VirtualPropertyResolverTest { .thenReturn(TEST_POLLING_TIME_INTERVAL); when(confMgmt.getConfigurationValue(TenantConfigurationKey.POLLING_OVERDUE_TIME_INTERVAL, String.class)) .thenReturn(TEST_POLLING_OVERDUE_TIME_INTERVAL); - - substitutor = new StrSubstitutor(resolverUnderTest, StrSubstitutor.DEFAULT_PREFIX, - StrSubstitutor.DEFAULT_SUFFIX, StrSubstitutor.DEFAULT_ESCAPE); } @Test @@ -80,8 +75,8 @@ class VirtualPropertyResolverTest { @Description("Tests escape mechanism for placeholders (syntax is $${SOME_PLACEHOLDER}).") void handleEscapedPlaceholder() { final String placeholder = "${OVERDUE_TS}"; - final String escaptedPlaceholder = StrSubstitutor.DEFAULT_ESCAPE + placeholder; - final String testString = "lhs=lt=" + escaptedPlaceholder; + final String escapedPlaceholder = StringSubstitutor.DEFAULT_ESCAPE + placeholder; + final String testString = "lhs=lt=" + escapedPlaceholder; final String resolvedPlaceholders = substitutor.replace(testString); assertThat(resolvedPlaceholders).as("Escaped OVERDUE_TS should not be resolved!").contains(placeholder); @@ -89,14 +84,13 @@ class VirtualPropertyResolverTest { @ParameterizedTest @ValueSource(strings = { "${NOW_TS}", "${OVERDUE_TS}", "${overdue_ts}" }) - @Description("Tests resolution of NOW_TS by using a StrSubstitutor configured with the VirtualPropertyResolver.") + @Description("Tests resolution of NOW_TS by using a StringSubstitutor configured with the VirtualPropertyResolver.") void resolveNowTimestampPlaceholder(final String placeholder) { when(securityContext.runAsSystem(Mockito.any())).thenAnswer(a -> ((Callable) a.getArgument(0)).call()); final String testString = "lhs=lt=" + placeholder; final String resolvedPlaceholders = substitutor.replace(testString); - assertThat(resolvedPlaceholders).as("'%s' placeholder was not replaced", placeholder) - .doesNotContain(placeholder); + assertThat(resolvedPlaceholders).as("'%s' placeholder was not replaced", placeholder).doesNotContain(placeholder); } @Configuration @@ -112,4 +106,4 @@ class VirtualPropertyResolverTest { return SystemSecurityContextHolder.getInstance(); } } -} +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-test/pom.xml b/hawkbit-repository/hawkbit-repository-test/pom.xml index bdefde15f..b3f587494 100644 --- a/hawkbit-repository/hawkbit-repository-test/pom.xml +++ b/hawkbit-repository/hawkbit-repository-test/pom.xml @@ -104,10 +104,6 @@ org.springframework spring-tx - - org.apache.commons - commons-lang3 - org.springframework.boot spring-boot-starter-test diff --git a/hawkbit-rest-core/pom.xml b/hawkbit-rest-core/pom.xml index 5c82cf0e9..40e3583e8 100644 --- a/hawkbit-rest-core/pom.xml +++ b/hawkbit-rest-core/pom.xml @@ -65,10 +65,6 @@ provided - - org.apache.commons - commons-lang3 - commons-io commons-io diff --git a/pom.xml b/pom.xml index d540bd27e..04674181c 100644 --- a/pom.xml +++ b/pom.xml @@ -62,6 +62,7 @@ 2.1.0 2.16.1 4.4 + 1.13.0 1.8.0 5.3.0 @@ -712,6 +713,11 @@ commons-collections4 ${commons-collections4.version} + + org.apache.commons + commons-text + ${commons-text.version} +