diff --git a/src/main/java/de/ozgcloud/admin/MigrationUnitRegistrationFeature.java b/src/main/java/de/ozgcloud/admin/MigrationUnitRegistrationFeature.java new file mode 100644 index 0000000000000000000000000000000000000000..23ff80637000adbec9c2f5f068b960572d414d53 --- /dev/null +++ b/src/main/java/de/ozgcloud/admin/MigrationUnitRegistrationFeature.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024. Das Land Schleswig-Holstein vertreten durch das Ministerium für Energiewende, Klimaschutz, Umwelt und Natur + * Zentrales IT-Management + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.admin; + +import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.hosted.RuntimeReflection; + +import de.ozgcloud.admin.migration.MigrationUnitList; + +public class MigrationUnitRegistrationFeature implements Feature { + + @Override + public void beforeAnalysis(BeforeAnalysisAccess access) { + MigrationUnitList.units.forEach(MigrationUnitRegistrationFeature::registerClass); + } + + private static void registerClass(Class<?> clazz) { + RuntimeReflection.register(clazz); + RuntimeReflection.register(clazz.getDeclaredConstructors()); + RuntimeReflection.register(clazz.getDeclaredMethods()); + } +} + diff --git a/src/main/java/de/ozgcloud/admin/migration/MigrationUnitList.java b/src/main/java/de/ozgcloud/admin/migration/MigrationUnitList.java new file mode 100644 index 0000000000000000000000000000000000000000..6497d8de1e6b27aa2f99fa2a7e2ca0ecd612c67e --- /dev/null +++ b/src/main/java/de/ozgcloud/admin/migration/MigrationUnitList.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024. Das Land Schleswig-Holstein vertreten durch das Ministerium für Energiewende, Klimaschutz, Umwelt und Natur + * Zentrales IT-Management + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.admin.migration; + +import java.util.List; + +public final class MigrationUnitList { + public static final List<Class<?>> units = List.of( + M001_CreateEmptyPostfachIfMissing.class + ); + + private MigrationUnitList() { + + } +} diff --git a/src/main/java/de/ozgcloud/admin/nativeimage/MigrationUnitAotProcessor.java b/src/main/java/de/ozgcloud/admin/nativeimage/MigrationUnitAotProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..9189eba8a07b0973262249675c8c52504f19fdd4 --- /dev/null +++ b/src/main/java/de/ozgcloud/admin/nativeimage/MigrationUnitAotProcessor.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2024. Das Land Schleswig-Holstein vertreten durch das Ministerium für Energiewende, Klimaschutz, Umwelt und Natur + * Zentrales IT-Management + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +package de.ozgcloud.admin.nativeimage; + +import static org.springframework.aot.hint.MemberCategory.*; + +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import org.springframework.aot.generate.GenerationContext; +import org.springframework.aot.hint.ReflectionHints; +import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution; +import org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor; +import org.springframework.beans.factory.aot.BeanFactoryInitializationCode; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.boot.autoconfigure.AutoConfigurationPackages; +import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; +import org.springframework.core.type.filter.AnnotationTypeFilter; +import org.springframework.util.ClassUtils; + +import io.mongock.api.annotations.ChangeUnit; +import io.mongock.runner.springboot.MongockSpringboot; +import io.mongock.utils.StringUtils; + +public class MigrationUnitAotProcessor implements BeanFactoryInitializationAotProcessor { + @Override + public BeanFactoryInitializationAotContribution processAheadOfTime(ConfigurableListableBeanFactory beanFactory) { + if (AutoConfigurationPackages.has(beanFactory)) { + var scanner = createScanner(); + Set<Class<?>> unitSet = AutoConfigurationPackages.get(beanFactory) + .stream() + .filter(StringUtils::hasText) + .flatMap(packageToScan -> scanner.findCandidateComponents(packageToScan).stream()) + .map(beanDefinition -> { + try { + return ClassUtils.forName(Objects.requireNonNull(beanDefinition.getBeanClassName()), + beanFactory.getBeanClassLoader()); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + }).collect(Collectors.toSet()); + return (GenerationContext generationContext, BeanFactoryInitializationCode beanFactoryInitializationCode) -> + registerReflectiveHints(generationContext.getRuntimeHints().reflection(), unitSet); + } + return null; + } + + private ClassPathScanningCandidateComponentProvider createScanner() { + var scanner = new ClassPathScanningCandidateComponentProvider(false); + scanner.addIncludeFilter(new AnnotationTypeFilter(ChangeUnit.class)); + return scanner; + } + + private void registerReflectiveHints(ReflectionHints hints, Set<Class<?>> migrationUnits) { + for (var unit : migrationUnits) { + hints.registerType(unit, hint -> + hint.withMembers(INVOKE_DECLARED_METHODS, INVOKE_DECLARED_CONSTRUCTORS) + ); + } + hints.registerType(MongockSpringboot.RunnerSpringbootBuilderImpl.class, hint -> + hint.withMembers(INVOKE_DECLARED_METHODS, INVOKE_DECLARED_CONSTRUCTORS) + ); + } +}