diff --git a/deployment/src/main/java/io/quarkiverse/jasperreports/deployment/JasperReportsProcessor.java b/deployment/src/main/java/io/quarkiverse/jasperreports/deployment/JasperReportsProcessor.java index c765958..e6b4106 100644 --- a/deployment/src/main/java/io/quarkiverse/jasperreports/deployment/JasperReportsProcessor.java +++ b/deployment/src/main/java/io/quarkiverse/jasperreports/deployment/JasperReportsProcessor.java @@ -1,33 +1,60 @@ package io.quarkiverse.jasperreports.deployment; +import java.awt.Color; +import java.awt.color.ColorSpace; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.Serializable; +import java.math.BigDecimal; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; +import java.time.temporal.TemporalAccessor; +import java.util.AbstractList; +import java.util.AbstractMap; import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.LinkedList; import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; import java.util.TreeSet; +import java.util.UUID; +import java.util.Vector; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Stream; import org.apache.commons.lang3.StringUtils; -import io.quarkiverse.jasperreports.Constants; -import io.quarkiverse.jasperreports.deployment.config.ReportConfig; +import io.quarkiverse.jasperreports.JasperReportsBeanProducer; +import io.quarkiverse.jasperreports.JasperReportsRecorder; +import io.quarkiverse.jasperreports.config.Constants; +import io.quarkiverse.jasperreports.config.ReportBuildTimeConfig; import io.quarkiverse.jasperreports.deployment.item.CompiledReportFileBuildItem; import io.quarkiverse.jasperreports.deployment.item.ReportFileBuildItem; import io.quarkiverse.jasperreports.deployment.item.ReportRootBuildItem; -import io.quarkiverse.jasperreports.repository.ReadOnlyStreamingService; import io.quarkus.arc.deployment.AdditionalBeanBuildItem; +import io.quarkus.arc.deployment.BeanContainerBuildItem; import io.quarkus.deployment.IsDevelopment; import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.annotations.ExecutionTime; +import io.quarkus.deployment.annotations.Record; import io.quarkus.deployment.builditem.CombinedIndexBuildItem; import io.quarkus.deployment.builditem.FeatureBuildItem; import io.quarkus.deployment.builditem.GeneratedClassBuildItem; @@ -43,11 +70,59 @@ import io.quarkus.deployment.pkg.builditem.UberJarMergedResourceBuildItem; import io.quarkus.logging.Log; import net.sf.jasperreports.compilers.ReportExpressionEvaluationData; +import net.sf.jasperreports.components.ComponentsExtensionsRegistryFactory; +import net.sf.jasperreports.components.headertoolbar.HeaderToolbarElement; +import net.sf.jasperreports.components.iconlabel.IconLabelElement; +import net.sf.jasperreports.components.list.UnusedSpaceImageRenderer; +import net.sf.jasperreports.components.util.AbstractFieldComparator; +import net.sf.jasperreports.crosstabs.fill.calculation.MeasureDefinition; +import net.sf.jasperreports.data.xmla.XmlaDataAdapterImpl; +import net.sf.jasperreports.engine.JRAbstractExporter; +import net.sf.jasperreports.engine.JRDataSource; +import net.sf.jasperreports.engine.JRDataSourceProvider; import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JRTemplate; +import net.sf.jasperreports.engine.JRVisitor; import net.sf.jasperreports.engine.JasperCompileManager; import net.sf.jasperreports.engine.JasperReport; +import net.sf.jasperreports.engine.SimpleReportContext; +import net.sf.jasperreports.engine.base.ElementStore; +import net.sf.jasperreports.engine.base.ElementsBlock; +import net.sf.jasperreports.engine.convert.ReportConverter; +import net.sf.jasperreports.engine.design.JRCompiler; +import net.sf.jasperreports.engine.design.JRDesignQuery; import net.sf.jasperreports.engine.design.JRReportCompileData; +import net.sf.jasperreports.engine.export.AbstractTextRenderer; +import net.sf.jasperreports.engine.export.DefaultExporterFilterFactory; +import net.sf.jasperreports.engine.export.ExporterNature; +import net.sf.jasperreports.engine.fill.JRFillSubreport; +import net.sf.jasperreports.engine.fill.JRFillVariable; +import net.sf.jasperreports.engine.fonts.AwtFontManager; +import net.sf.jasperreports.engine.fonts.SimpleFontFace; +import net.sf.jasperreports.engine.part.DefaultPartComponentsBundle; +import net.sf.jasperreports.engine.query.JRQueryExecuter; +import net.sf.jasperreports.engine.query.QueryExecuterFactory; +import net.sf.jasperreports.engine.type.ColorEnum; +import net.sf.jasperreports.engine.util.ImageUtil; import net.sf.jasperreports.engine.util.JRLoader; +import net.sf.jasperreports.engine.util.JRQueryExecuterUtils; +import net.sf.jasperreports.engine.util.xml.JRXPathExecuter; +import net.sf.jasperreports.engine.util.xml.JRXPathExecuterFactory; +import net.sf.jasperreports.engine.xml.ReportLoader; +import net.sf.jasperreports.export.CsvExporterConfiguration; +import net.sf.jasperreports.extensions.DefaultExtensionsRegistryFactory; +import net.sf.jasperreports.extensions.ExtensionsRegistry; +import net.sf.jasperreports.extensions.ExtensionsRegistryFactory; +import net.sf.jasperreports.governors.GovernorExtensionsRegistryFactory; +import net.sf.jasperreports.jackson.util.JacksonUtil; +import net.sf.jasperreports.parts.PartComponentsExtensionsRegistryFactory; +import net.sf.jasperreports.pdf.PdfExporterConfiguration; +import net.sf.jasperreports.pdf.classic.ClassicPdfProducerFactory; +import net.sf.jasperreports.poi.query.PoiQueryExecuterFactoryBundle; +import net.sf.jasperreports.renderers.AbstractSvgDataToGraphics2DRenderer; +import net.sf.jasperreports.renderers.util.SvgFontProcessor; +import net.sf.jasperreports.repo.DefaultRepositoryExtensionsRegistryFactory; +import net.sf.jasperreports.util.JsonLoader; /** * Processor class for JasperReports integration in Quarkus. @@ -115,45 +190,45 @@ void registerForReflection(BuildProducer reflectiveCla //@formatter:off final List classNames = new ArrayList<>(); // By Implementors: jasper interfaces/abstract classes that are created with Class.forName - classNames.addAll(collectImplementors(combinedIndex, net.sf.jasperreports.engine.JRDataSource.class.getName())); - classNames.addAll(collectImplementors(combinedIndex, net.sf.jasperreports.engine.JRDataSourceProvider.class.getName())); - classNames.addAll(collectImplementors(combinedIndex, net.sf.jasperreports.engine.JRTemplate.class.getName())); - classNames.addAll(collectImplementors(combinedIndex, net.sf.jasperreports.engine.JRVisitor.class.getName())); - classNames.addAll(collectImplementors(combinedIndex, net.sf.jasperreports.engine.design.JRCompiler.class.getName())); - classNames.addAll(collectImplementors(combinedIndex, net.sf.jasperreports.engine.query.JRQueryExecuter.class.getName())); - classNames.addAll(collectImplementors(combinedIndex, net.sf.jasperreports.engine.query.QueryExecuterFactory.class.getName())); - classNames.addAll(collectImplementors(combinedIndex, net.sf.jasperreports.engine.util.xml.JRXPathExecuterFactory.class.getName())); - classNames.addAll(collectImplementors(combinedIndex, net.sf.jasperreports.engine.xml.ReportLoader.class.getName())); - classNames.addAll(collectImplementors(combinedIndex, net.sf.jasperreports.extensions.ExtensionsRegistry.class.getName())); - classNames.addAll(collectImplementors(combinedIndex, net.sf.jasperreports.extensions.ExtensionsRegistryFactory.class.getName())); - classNames.addAll(collectSubclasses(combinedIndex, net.sf.jasperreports.engine.JRAbstractExporter.class.getName())); + classNames.addAll(collectImplementors(combinedIndex, JRDataSource.class.getName())); + classNames.addAll(collectImplementors(combinedIndex, JRDataSourceProvider.class.getName())); + classNames.addAll(collectImplementors(combinedIndex, JRTemplate.class.getName())); + classNames.addAll(collectImplementors(combinedIndex, JRVisitor.class.getName())); + classNames.addAll(collectImplementors(combinedIndex, JRCompiler.class.getName())); + classNames.addAll(collectImplementors(combinedIndex, JRQueryExecuter.class.getName())); + classNames.addAll(collectImplementors(combinedIndex, QueryExecuterFactory.class.getName())); + classNames.addAll(collectImplementors(combinedIndex, JRXPathExecuterFactory.class.getName())); + classNames.addAll(collectImplementors(combinedIndex, ReportLoader.class.getName())); + classNames.addAll(collectImplementors(combinedIndex, ExtensionsRegistry.class.getName())); + classNames.addAll(collectImplementors(combinedIndex, ExtensionsRegistryFactory.class.getName())); + classNames.addAll(collectSubclasses(combinedIndex, JRAbstractExporter.class.getName())); // By Package (utilities etc) - classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.compilers.ReportExpressionEvaluationData.class.getPackageName())); - classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.components.ComponentsExtensionsRegistryFactory.class.getPackageName())); - classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.data.xmla.XmlaDataAdapterImpl.class.getPackageName())); - classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.engine.JasperReport.class.getPackageName())); - classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.engine.base.ElementStore.class.getPackageName())); - classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.engine.design.JRDesignQuery.class.getPackageName())); - classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.engine.export.DefaultExporterFilterFactory.class.getPackageName())); - classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.engine.export.ExporterNature.class.getPackageName())); - classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.engine.fill.JRFillVariable.class.getPackageName())); - classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.engine.fonts.SimpleFontFace.class.getPackageName())); - classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.engine.part.DefaultPartComponentsBundle.class.getPackageName())); - classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.engine.type.ColorEnum.class.getPackageName())); - classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.engine.util.ImageUtil.class.getPackageName())); - classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.engine.util.xml.JRXPathExecuter.class.getPackageName())); - classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.engine.xml.ReportLoader.class.getPackageName())); - classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.export.CsvExporterConfiguration.class.getPackageName())); - classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.extensions.DefaultExtensionsRegistryFactory.class.getPackageName())); - classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.governors.GovernorExtensionsRegistryFactory.class.getPackageName())); - classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.jackson.util.JacksonUtil.class.getPackageName())); - classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.parts.PartComponentsExtensionsRegistryFactory.class.getPackageName())); - classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.pdf.classic.ClassicPdfProducerFactory.class.getPackageName())); - classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.renderers.AbstractSvgDataToGraphics2DRenderer.class.getPackageName())); - classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.renderers.util.SvgFontProcessor.class.getPackageName())); - classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.repo.DefaultRepositoryExtensionsRegistryFactory.class.getPackageName())); - classNames.addAll(collectClassesInPackage(combinedIndex, net.sf.jasperreports.util.JsonLoader.class.getPackageName())); + classNames.addAll(collectClassesInPackage(combinedIndex, ReportExpressionEvaluationData.class.getPackageName())); + classNames.addAll(collectClassesInPackage(combinedIndex, ComponentsExtensionsRegistryFactory.class.getPackageName())); + classNames.addAll(collectClassesInPackage(combinedIndex, XmlaDataAdapterImpl.class.getPackageName())); + classNames.addAll(collectClassesInPackage(combinedIndex, JasperReport.class.getPackageName())); + classNames.addAll(collectClassesInPackage(combinedIndex, ElementStore.class.getPackageName())); + classNames.addAll(collectClassesInPackage(combinedIndex, JRDesignQuery.class.getPackageName())); + classNames.addAll(collectClassesInPackage(combinedIndex, DefaultExporterFilterFactory.class.getPackageName())); + classNames.addAll(collectClassesInPackage(combinedIndex, ExporterNature.class.getPackageName())); + classNames.addAll(collectClassesInPackage(combinedIndex, JRFillVariable.class.getPackageName())); + classNames.addAll(collectClassesInPackage(combinedIndex, SimpleFontFace.class.getPackageName())); + classNames.addAll(collectClassesInPackage(combinedIndex, DefaultPartComponentsBundle.class.getPackageName())); + classNames.addAll(collectClassesInPackage(combinedIndex, ColorEnum.class.getPackageName())); + classNames.addAll(collectClassesInPackage(combinedIndex, ImageUtil.class.getPackageName())); + classNames.addAll(collectClassesInPackage(combinedIndex, JRXPathExecuter.class.getPackageName())); + classNames.addAll(collectClassesInPackage(combinedIndex, ReportLoader.class.getPackageName())); + classNames.addAll(collectClassesInPackage(combinedIndex, CsvExporterConfiguration.class.getPackageName())); + classNames.addAll(collectClassesInPackage(combinedIndex, DefaultExtensionsRegistryFactory.class.getPackageName())); + classNames.addAll(collectClassesInPackage(combinedIndex, GovernorExtensionsRegistryFactory.class.getPackageName())); + classNames.addAll(collectClassesInPackage(combinedIndex, JacksonUtil.class.getPackageName())); + classNames.addAll(collectClassesInPackage(combinedIndex, PartComponentsExtensionsRegistryFactory.class.getPackageName())); + classNames.addAll(collectClassesInPackage(combinedIndex, ClassicPdfProducerFactory.class.getPackageName())); + classNames.addAll(collectClassesInPackage(combinedIndex, AbstractSvgDataToGraphics2DRenderer.class.getPackageName())); + classNames.addAll(collectClassesInPackage(combinedIndex, SvgFontProcessor.class.getPackageName())); + classNames.addAll(collectClassesInPackage(combinedIndex, DefaultRepositoryExtensionsRegistryFactory.class.getPackageName())); + classNames.addAll(collectClassesInPackage(combinedIndex, JsonLoader.class.getPackageName())); // basic Java classes found in reports for serialization classNames.add("java.util.Collections$CheckedCollection"); @@ -169,47 +244,47 @@ void registerForReflection(BuildProducer reflectiveCla classNames.add("java.util.Collections$SynchronizedSortedMap"); classNames.add(byte.class.getName()); classNames.add(byte[].class.getName()); - classNames.add(java.awt.Color.class.getName()); - classNames.add(java.awt.color.ColorSpace.class.getName()); - classNames.add(java.io.Serializable.class.getName()); - classNames.add(java.lang.Boolean.class.getName()); - classNames.add(java.lang.Byte.class.getName()); - classNames.add(java.lang.Byte.class.getName()); - classNames.add(java.lang.Character.class.getName()); - classNames.add(java.lang.Double.class.getName()); - classNames.add(java.lang.Enum.class.getName()); - classNames.add(java.lang.Float.class.getName()); - classNames.add(java.lang.Integer.class.getName()); - classNames.add(java.lang.Iterable.class.getName()); - classNames.add(java.lang.Long.class.getName()); - classNames.add(java.lang.Number.class.getName()); - classNames.add(java.lang.Object.class.getName()); - classNames.add(java.lang.Short.class.getName()); - classNames.add(java.lang.String.class.getName()); - classNames.add(java.lang.StringBuilder.class.getName()); - classNames.add(java.math.BigDecimal.class.getName()); - classNames.add(java.util.AbstractList.class.getName()); - classNames.add(java.util.AbstractMap.class.getName()); - classNames.add(java.util.ArrayList.class.getName()); - classNames.add(java.util.Calendar.class.getName()); - classNames.add(java.util.Collections.class.getName()); - classNames.add(java.util.Date.class.getName()); - classNames.add(java.util.GregorianCalendar.class.getName()); - classNames.add(java.util.HashMap.class.getName()); - classNames.add(java.util.HashSet.class.getName()); - classNames.add(java.util.Hashtable.class.getName()); - classNames.add(java.util.LinkedHashMap.class.getName()); - classNames.add(java.util.LinkedHashSet.class.getName()); - classNames.add(java.util.LinkedList.class.getName()); - classNames.add(java.util.List.class.getName()); - classNames.add(java.util.Map.class.getName()); - classNames.add(java.util.Set.class.getName()); - classNames.add(java.util.TreeMap.class.getName()); - classNames.add(java.util.UUID.class.getName()); - classNames.add(java.util.Vector.class.getName()); - classNames.addAll(collectImplementors(combinedIndex, java.time.temporal.TemporalAccessor.class.getName())); - classNames.addAll(collectImplementors(combinedIndex, java.util.Collection.class.getName())); - classNames.addAll(collectImplementors(combinedIndex, java.util.Map.Entry.class.getName())); + classNames.add(Color.class.getName()); + classNames.add(ColorSpace.class.getName()); + classNames.add(Serializable.class.getName()); + classNames.add(Boolean.class.getName()); + classNames.add(Byte.class.getName()); + classNames.add(Byte.class.getName()); + classNames.add(Character.class.getName()); + classNames.add(Double.class.getName()); + classNames.add(Enum.class.getName()); + classNames.add(Float.class.getName()); + classNames.add(Integer.class.getName()); + classNames.add(Iterable.class.getName()); + classNames.add(Long.class.getName()); + classNames.add(Number.class.getName()); + classNames.add(Object.class.getName()); + classNames.add(Short.class.getName()); + classNames.add(String.class.getName()); + classNames.add(StringBuilder.class.getName()); + classNames.add(BigDecimal.class.getName()); + classNames.add(AbstractList.class.getName()); + classNames.add(AbstractMap.class.getName()); + classNames.add(ArrayList.class.getName()); + classNames.add(Calendar.class.getName()); + classNames.add(Collections.class.getName()); + classNames.add(Date.class.getName()); + classNames.add(GregorianCalendar.class.getName()); + classNames.add(HashMap.class.getName()); + classNames.add(HashSet.class.getName()); + classNames.add(Hashtable.class.getName()); + classNames.add(LinkedHashMap.class.getName()); + classNames.add(LinkedHashSet.class.getName()); + classNames.add(LinkedList.class.getName()); + classNames.add(List.class.getName()); + classNames.add(Map.class.getName()); + classNames.add(Set.class.getName()); + classNames.add(TreeMap.class.getName()); + classNames.add(UUID.class.getName()); + classNames.add(Vector.class.getName()); + classNames.addAll(collectImplementors(combinedIndex, TemporalAccessor.class.getName())); + classNames.addAll(collectImplementors(combinedIndex, Collection.class.getName())); + classNames.addAll(collectImplementors(combinedIndex, Map.Entry.class.getName())); //@formatter:on final TreeSet uniqueClasses = new TreeSet<>(classNames); @@ -230,27 +305,27 @@ void registerForReflection(BuildProducer reflectiveCla void runtimeInitializedClasses(BuildProducer runtimeInitializedPackages, CombinedIndexBuildItem combinedIndex) { //@formatter:off - List classes = collectImplementors(combinedIndex, net.sf.jasperreports.extensions.ExtensionsRegistryFactory.class.getName()); + List classes = collectImplementors(combinedIndex, ExtensionsRegistryFactory.class.getName()); classes.addAll(Stream.of("javax.swing", "javax.swing.plaf.metal", "javax.swing.text.html", "javax.swing.text.rtf", "sun.datatransfer", "sun.swing", - net.sf.jasperreports.components.headertoolbar.HeaderToolbarElement.class.getPackageName(), - net.sf.jasperreports.components.iconlabel.IconLabelElement.class.getPackageName(), - net.sf.jasperreports.components.list.UnusedSpaceImageRenderer.class.getName(), - net.sf.jasperreports.components.util.AbstractFieldComparator.class.getPackageName(), - net.sf.jasperreports.crosstabs.fill.calculation.MeasureDefinition.class.getPackageName(), - net.sf.jasperreports.engine.SimpleReportContext.class.getPackageName(), - net.sf.jasperreports.engine.base.ElementsBlock.class.getPackageName(), - net.sf.jasperreports.engine.convert.ReportConverter.class.getName(), - net.sf.jasperreports.engine.export.AbstractTextRenderer.class.getPackageName(), - net.sf.jasperreports.engine.fill.JRFillSubreport.class.getPackageName(), - net.sf.jasperreports.engine.fonts.AwtFontManager.class.getPackageName(), - net.sf.jasperreports.engine.type.ColorEnum.class.getPackageName(), - net.sf.jasperreports.engine.util.JRQueryExecuterUtils.class.getPackageName(), - net.sf.jasperreports.poi.query.PoiQueryExecuterFactoryBundle.class.getName()).toList()); + HeaderToolbarElement.class.getPackageName(), + IconLabelElement.class.getPackageName(), + UnusedSpaceImageRenderer.class.getName(), + AbstractFieldComparator.class.getPackageName(), + MeasureDefinition.class.getPackageName(), + SimpleReportContext.class.getPackageName(), + ElementsBlock.class.getPackageName(), + ReportConverter.class.getName(), + AbstractTextRenderer.class.getPackageName(), + JRFillSubreport.class.getPackageName(), + AwtFontManager.class.getPackageName(), + ColorEnum.class.getPackageName(), + JRQueryExecuterUtils.class.getPackageName(), + PoiQueryExecuterFactoryBundle.class.getName()).toList()); //@formatter:on Log.debugf("Jasper Runtime: %s", classes); classes.stream() @@ -365,9 +440,9 @@ void registerJasperReportsProxies(BuildProducer classes = new ArrayList<>(collectInterfacesInPackage(combinedIndex, - net.sf.jasperreports.export.CsvExporterConfiguration.class.getPackageName())); + CsvExporterConfiguration.class.getPackageName())); classes.addAll(collectInterfacesInPackage(combinedIndex, - net.sf.jasperreports.pdf.PdfExporterConfiguration.class.getPackageName())); + PdfExporterConfiguration.class.getPackageName())); for (String proxyClassName : classes) { proxyDefinitions.produce(new NativeImageProxyDefinitionBuildItem(proxyClassName)); } @@ -397,7 +472,7 @@ void registerFonts(BuildProducer nativeIma * Otherwise, it returns the default source path defined in ReportConfig. */ @BuildStep - ReportRootBuildItem defaultReportRoot(ReportConfig config) { + ReportRootBuildItem defaultReportRoot(ReportBuildTimeConfig config) { if (config.build().enable()) { return new ReportRootBuildItem(config.build().source().toString()); } @@ -495,7 +570,7 @@ void watchReportFiles(BuildProducer watchedPa * @param outputTarget The OutputTargetBuildItem containing information about the build output directory. */ @BuildStep - void compileReports(ReportConfig config, List reportFiles, + void compileReports(ReportBuildTimeConfig config, List reportFiles, BuildProducer compiledReportProducer, BuildProducer compiledReportFileProducer, OutputTargetBuildItem outputTarget) { @@ -548,9 +623,28 @@ void compileReports(ReportConfig config, List reportFiles, } } + /** + * Registers the JasperReportsBeanProducer as an unremovable bean. + * + * @return An AdditionalBeanBuildItem for the JasperReportsBeanProducer. + */ + @BuildStep + AdditionalBeanBuildItem registerBeanProducer() { + return AdditionalBeanBuildItem.unremovableOf(JasperReportsBeanProducer.class); + } + + /** + * Initializes the JasperReports producer at runtime. + * + * @param recorder The JasperReportsRecorder to use for initialization. + * @param beanContainer The BeanContainerBuildItem containing the bean container. + * @param config The ReportBuildTimeConfig to use for initialization. + */ @BuildStep - AdditionalBeanBuildItem additionalBeans() { - return AdditionalBeanBuildItem.unremovableOf(ReadOnlyStreamingService.class); + @Record(ExecutionTime.RUNTIME_INIT) + void initializeMdns(JasperReportsRecorder recorder, BeanContainerBuildItem beanContainer, + ReportBuildTimeConfig config) { + recorder.initProducer(beanContainer.getValue(), config); } /** @@ -569,4 +663,4 @@ static Path findProjectRoot(Path outputDirectory, Path startDirectory) { return startDirectory; } } -} +} \ No newline at end of file diff --git a/deployment/src/main/java/io/quarkiverse/jasperreports/deployment/item/AbstractReportFileBuildItem.java b/deployment/src/main/java/io/quarkiverse/jasperreports/deployment/item/AbstractReportFileBuildItem.java index a4b3189..f01a508 100644 --- a/deployment/src/main/java/io/quarkiverse/jasperreports/deployment/item/AbstractReportFileBuildItem.java +++ b/deployment/src/main/java/io/quarkiverse/jasperreports/deployment/item/AbstractReportFileBuildItem.java @@ -1,9 +1,9 @@ package io.quarkiverse.jasperreports.deployment.item; -import static io.quarkiverse.jasperreports.Constants.EXT_COMPILED; -import static io.quarkiverse.jasperreports.Constants.EXT_DATA_ADAPTER; -import static io.quarkiverse.jasperreports.Constants.EXT_REPORT; -import static io.quarkiverse.jasperreports.Constants.EXT_STYLE; +import static io.quarkiverse.jasperreports.config.Constants.EXT_COMPILED; +import static io.quarkiverse.jasperreports.config.Constants.EXT_DATA_ADAPTER; +import static io.quarkiverse.jasperreports.config.Constants.EXT_REPORT; +import static io.quarkiverse.jasperreports.config.Constants.EXT_STYLE; import java.nio.file.Path; import java.util.List; @@ -50,4 +50,4 @@ public String getType() { }; } -} +} \ No newline at end of file diff --git a/runtime/pom.xml b/runtime/pom.xml index ef10a72..e064abf 100644 --- a/runtime/pom.xml +++ b/runtime/pom.xml @@ -30,6 +30,14 @@ org.jboss.logging commons-logging-jboss-logging + + org.bouncycastle + bcprov-jdk18on + + + org.bouncycastle + bcpkix-jdk18on + @@ -107,14 +115,6 @@ fop 2.10 - - org.bouncycastle - bcprov-jdk18on - - - org.bouncycastle - bcpkix-jdk18on - net.sf.saxon Saxon-HE diff --git a/runtime/src/main/java/io/quarkiverse/jasperreports/JasperReportsBeanProducer.java b/runtime/src/main/java/io/quarkiverse/jasperreports/JasperReportsBeanProducer.java new file mode 100644 index 0000000..7fe20b0 --- /dev/null +++ b/runtime/src/main/java/io/quarkiverse/jasperreports/JasperReportsBeanProducer.java @@ -0,0 +1,39 @@ +package io.quarkiverse.jasperreports; + +import java.nio.file.Path; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.inject.Produces; + +import io.quarkiverse.jasperreports.repository.ReadOnlyStreamingService; + +/** + * A bean producer for JasperReports-related services. + * This class is responsible for initializing and producing the ReadOnlyStreamingService. + */ +@ApplicationScoped +public class JasperReportsBeanProducer { + + private volatile Path destinationPath; + + /** + * Initializes the bean producer with the destination path for JasperReports files. + * + * @param destinationPath The path where compiled JasperReports files are located. + */ + void initialize(Path destinationPath) { + this.destinationPath = destinationPath; + } + + /** + * Produces a ReadOnlyStreamingService instance. + * + * @return A new ReadOnlyStreamingService initialized with the destination path. + */ + @Dependent + @Produces + public ReadOnlyStreamingService readOnlyStreamingService() { + return new ReadOnlyStreamingService(this.destinationPath); + } +} diff --git a/runtime/src/main/java/io/quarkiverse/jasperreports/JasperReportsRecorder.java b/runtime/src/main/java/io/quarkiverse/jasperreports/JasperReportsRecorder.java new file mode 100644 index 0000000..d509099 --- /dev/null +++ b/runtime/src/main/java/io/quarkiverse/jasperreports/JasperReportsRecorder.java @@ -0,0 +1,24 @@ +package io.quarkiverse.jasperreports; + +import io.quarkiverse.jasperreports.config.ReportBuildTimeConfig; +import io.quarkus.arc.runtime.BeanContainer; +import io.quarkus.runtime.annotations.Recorder; + +/** + * Recorder for JasperReports initialization. + * This class is responsible for initializing the JasperReportsBeanProducer at runtime. + */ +@Recorder +public class JasperReportsRecorder { + + /** + * Initializes the JasperReportsBeanProducer with the configured destination path. + * + * @param container The BeanContainer used to retrieve the JasperReportsBeanProducer instance. + * @param config The ReportBuildTimeConfig containing the build configuration. + */ + public void initProducer(BeanContainer container, ReportBuildTimeConfig config) { + JasperReportsBeanProducer producer = container.beanInstance(JasperReportsBeanProducer.class); + producer.initialize(config.build().destination()); + } +} diff --git a/runtime/src/main/java/io/quarkiverse/jasperreports/Constants.java b/runtime/src/main/java/io/quarkiverse/jasperreports/config/Constants.java similarity index 88% rename from runtime/src/main/java/io/quarkiverse/jasperreports/Constants.java rename to runtime/src/main/java/io/quarkiverse/jasperreports/config/Constants.java index 40905ef..49afae6 100644 --- a/runtime/src/main/java/io/quarkiverse/jasperreports/Constants.java +++ b/runtime/src/main/java/io/quarkiverse/jasperreports/config/Constants.java @@ -1,4 +1,4 @@ -package io.quarkiverse.jasperreports; +package io.quarkiverse.jasperreports.config; public interface Constants { @@ -14,4 +14,4 @@ public interface Constants { static final String DEFAULT_DEST_PATH = "jasperreports"; -} +} \ No newline at end of file diff --git a/deployment/src/main/java/io/quarkiverse/jasperreports/deployment/config/ReportConfig.java b/runtime/src/main/java/io/quarkiverse/jasperreports/config/ReportBuildTimeConfig.java similarity index 87% rename from deployment/src/main/java/io/quarkiverse/jasperreports/deployment/config/ReportConfig.java rename to runtime/src/main/java/io/quarkiverse/jasperreports/config/ReportBuildTimeConfig.java index c9a44f8..973c9eb 100644 --- a/deployment/src/main/java/io/quarkiverse/jasperreports/deployment/config/ReportConfig.java +++ b/runtime/src/main/java/io/quarkiverse/jasperreports/config/ReportBuildTimeConfig.java @@ -1,4 +1,4 @@ -package io.quarkiverse.jasperreports.deployment.config; +package io.quarkiverse.jasperreports.config; import java.nio.file.Path; @@ -8,8 +8,8 @@ import io.smallrye.config.WithDefault; @ConfigMapping(prefix = "quarkus.jasperreports") -@ConfigRoot(phase = ConfigPhase.BUILD_TIME) -public interface ReportConfig { +@ConfigRoot(phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED) +public interface ReportBuildTimeConfig { String DEFAULT_SOURCE_PATH = "src/main/jasperreports"; String DEFAULT_DEST_PATH = "jasperreports"; @@ -40,4 +40,4 @@ interface BuildConfig { Path destination(); } -} +} \ No newline at end of file diff --git a/runtime/src/main/java/io/quarkiverse/jasperreports/repository/ReadOnlyStreamingService.java b/runtime/src/main/java/io/quarkiverse/jasperreports/repository/ReadOnlyStreamingService.java index 44ab5e1..b66edb7 100644 --- a/runtime/src/main/java/io/quarkiverse/jasperreports/repository/ReadOnlyStreamingService.java +++ b/runtime/src/main/java/io/quarkiverse/jasperreports/repository/ReadOnlyStreamingService.java @@ -1,22 +1,16 @@ package io.quarkiverse.jasperreports.repository; -import static io.quarkiverse.jasperreports.Constants.EXT_COMPILED; -import static io.quarkiverse.jasperreports.Constants.EXT_DATA_ADAPTER; -import static io.quarkiverse.jasperreports.Constants.EXT_STYLE; +import static io.quarkiverse.jasperreports.config.Constants.EXT_COMPILED; +import static io.quarkiverse.jasperreports.config.Constants.EXT_DATA_ADAPTER; +import static io.quarkiverse.jasperreports.config.Constants.EXT_STYLE; import java.io.InputStream; import java.io.OutputStream; import java.nio.file.Path; import java.util.Collections; -import java.util.Optional; -import jakarta.annotation.PostConstruct; -import jakarta.enterprise.context.Dependent; - -import org.eclipse.microprofile.config.inject.ConfigProperty; import org.jboss.logging.Logger; -import io.quarkiverse.jasperreports.Constants; import net.sf.jasperreports.engine.JRException; import net.sf.jasperreports.engine.JasperReportsContext; import net.sf.jasperreports.engine.SimpleJasperReportsContext; @@ -31,73 +25,116 @@ import net.sf.jasperreports.repo.SimpleRepositoryContext; import net.sf.jasperreports.repo.StreamRepositoryService; -@Dependent +/** + * A read-only implementation of StreamRepositoryService for JasperReports. + * This service provides access to compiled reports, styles, and data adapters + * from a specified destination path. + */ public class ReadOnlyStreamingService implements StreamRepositoryService { private static final Logger LOG = Logger.getLogger(ReadOnlyStreamingService.class); private final JasperReportsContext context = new SimpleJasperReportsContext(); - - // TODO - why is it not picking up the default value from ReportConfig??? - @ConfigProperty(name = "quarkus.jasperreports.build.destination", defaultValue = Constants.DEFAULT_DEST_PATH) - Optional reportPathConfig; - - @PostConstruct - public void onInit() { - ((SimpleJasperReportsContext) context).setExtensions(RepositoryService.class, Collections.singletonList(this)); - ((SimpleJasperReportsContext) context).setExtensions(PersistenceServiceFactory.class, + private final Path destinationPath; + + /** + * Constructs a new ReadOnlyStreamingService with the specified destination path. + * + * @param destinationPath The path where compiled reports and styles are located. + */ + public ReadOnlyStreamingService(Path destinationPath) { + this.destinationPath = destinationPath; + SimpleJasperReportsContext simpleContext = ((SimpleJasperReportsContext) context); + simpleContext.setExtensions(RepositoryService.class, Collections.singletonList(this)); + simpleContext.setExtensions(PersistenceServiceFactory.class, Collections.singletonList(FileRepositoryPersistenceServiceFactory.getInstance())); } + /** + * Returns the JasperReportsContext associated with this service. + * + * @return The JasperReportsContext instance. + */ public JasperReportsContext getContext() { return context; } + /** + * Retrieves an InputStream for the specified URI. + * This method handles compiled reports, styles, and data adapters. + * + * @param uri The URI of the resource to retrieve. + * @return An InputStream for the requested resource, or null if not found. + */ @Override public InputStream getInputStream(String uri) { - InputStream is = null; + String logType = null; + String filePath = uri; if (uri.endsWith(EXT_COMPILED) || uri.endsWith(EXT_STYLE)) { - final Path reportPath = Path.of(reportPathConfig.get().toString(), uri); - final String reportFile = reportPath.toString(); - - try { - LOG.debugf("Loading %s file %s", (uri.endsWith(EXT_COMPILED) ? "report" : "style"), reportFile); - - return JRLoader.getLocationInputStream(reportFile); - } catch (JRException ex) { - LOG.warnf("Failed to load %s - %s", (uri.endsWith(EXT_COMPILED) ? "report" : "style"), ex.getMessage()); - LOG.debug(ex); - } + logType = uri.endsWith(EXT_COMPILED) ? "report" : "style"; + filePath = Path.of(this.destinationPath.toString(), uri).toString(); } else if (uri.endsWith(EXT_DATA_ADAPTER)) { - try { - LOG.debugf("Loading data adapter file %s", uri); + logType = "data adapter"; + } - return JRLoader.getLocationInputStream(uri); + if (logType != null) { + try { + LOG.debugf("Loading %s file %s", logType, filePath); + return JRLoader.getLocationInputStream(filePath); } catch (JRException ex) { - LOG.warnf("Failed to load data adapter - %s", ex.getMessage()); + LOG.warnf("Failed to load %s - %s", logType, ex.getMessage()); LOG.debug(ex); } } - return is; + return null; } + /** + * This method is not supported in this read-only implementation. + * + * @param uri The URI of the resource. + * @return This method always throws an IllegalStateException. + * @throws IllegalStateException Always thrown as this repository is read-only. + */ @Override public OutputStream getOutputStream(String uri) { throw new IllegalStateException("This repository is read only"); } + /** + * This method is not supported in this implementation. + * + * @param uri The URI of the resource. + * @return This method always throws an IllegalStateException. + * @throws IllegalStateException Always thrown as this method is not supported. + */ @Override public Resource getResource(String uri) { throw new IllegalStateException("Can only return an InputStream"); } + /** + * This method is not supported in this read-only implementation. + * + * @param uri The URI of the resource. + * @param resource The resource to save. + * @throws IllegalStateException Always thrown as this repository is read-only. + */ @Override public void saveResource(String uri, Resource resource) { throw new IllegalStateException("This repository is read only"); } + /** + * Retrieves a resource of the specified type for the given URI. + * + * @param The type of resource to retrieve. + * @param uri The URI of the resource. + * @param resourceType The class of the resource type. + * @return The requested resource, or null if not found or if no appropriate PersistenceService is available. + */ @Override @SuppressWarnings("unchecked") public T getResource(String uri, Class resourceType) { @@ -112,4 +149,4 @@ public T getResource(String uri, Class resourceType) { return null; } -} +} \ No newline at end of file