diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/PackageConfig.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/PackageConfig.java index e5918d4cd3df6..778fad0cbe869 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/PackageConfig.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/PackageConfig.java @@ -176,6 +176,10 @@ public boolean isLegacyJar() { type.equalsIgnoreCase(PackageConfig.LEGACY)); } + public boolean isUberJar() { + return type.equalsIgnoreCase(PackageConfig.UBER_JAR); + } + @ConfigGroup public static class FernflowerConfig { diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/JarResultBuildStep.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/JarResultBuildStep.java index 92d924d1a5154..4ca4cb54ec5f3 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/JarResultBuildStep.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/JarResultBuildStep.java @@ -355,18 +355,25 @@ private void buildUberJar0(CurateOutcomeBuildItem curateOutcomeBuildItem, } for (Path resolvedDep : depArtifact.getPaths()) { - Set transformedFromThisArchive = transformedClasses.getTransformedFilesByJar().get(resolvedDep); + Set existingEntries = new HashSet<>(); + Set transformedFilesByJar = transformedClasses.getTransformedFilesByJar().get(resolvedDep); + if (transformedFilesByJar != null) { + existingEntries.addAll(transformedFilesByJar); + } + generatedResources.stream() + .map(GeneratedResourceBuildItem::getName) + .forEach(existingEntries::add); if (!Files.isDirectory(resolvedDep)) { try (FileSystem artifactFs = ZipUtils.newFileSystem(resolvedDep)) { for (final Path root : artifactFs.getRootDirectories()) { walkFileDependencyForDependency(root, runnerZipFs, seen, duplicateCatcher, concatenatedEntries, - finalIgnoredEntries, appDep, transformedFromThisArchive, mergeResourcePaths); + finalIgnoredEntries, appDep, existingEntries, mergeResourcePaths); } } } else { walkFileDependencyForDependency(resolvedDep, runnerZipFs, seen, duplicateCatcher, - concatenatedEntries, finalIgnoredEntries, appDep, transformedFromThisArchive, + concatenatedEntries, finalIgnoredEntries, appDep, existingEntries, mergeResourcePaths); } } @@ -416,7 +423,7 @@ private static boolean includeAppDep(AppDependency appDep, Optional seen, Map> duplicateCatcher, Map> concatenatedEntries, - Set finalIgnoredEntries, AppDependency appDep, Set transformedFromThisArchive, + Set finalIgnoredEntries, AppDependency appDep, Set existingEntries, Set mergeResourcePaths) throws IOException { final Path metaInfDir = root.resolve("META-INF"); Files.walkFileTree(root, EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE, @@ -446,9 +453,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) } return FileVisitResult.CONTINUE; } - boolean transformed = transformedFromThisArchive != null - && transformedFromThisArchive.contains(relativePath); - if (!transformed) { + if (!existingEntries.contains(relativePath)) { if (CONCATENATED_ENTRIES_PREDICATE.test(relativePath) || mergeResourcePaths.contains(relativePath)) { concatenatedEntries.computeIfAbsent(relativePath, (u) -> new ArrayList<>()) diff --git a/core/test-extension/deployment/pom.xml b/core/test-extension/deployment/pom.xml index eb4318b63fe34..686f3667dc567 100644 --- a/core/test-extension/deployment/pom.xml +++ b/core/test-extension/deployment/pom.xml @@ -12,6 +12,9 @@ quarkus-test-extension-deployment Quarkus - Core - Test Extension - Deployment + + 3.0.0 + io.quarkus @@ -30,6 +33,11 @@ quarkus-test-extension ${project.version} + + org.atteo + xml-combiner + ${xml-combiner.version} + diff --git a/core/test-extension/deployment/src/main/java/io/quarkus/extest/deployment/UberJarConfigBuildStep.java b/core/test-extension/deployment/src/main/java/io/quarkus/extest/deployment/UberJarConfigBuildStep.java index 5299b7832ebb8..6f0a1e1b9c263 100644 --- a/core/test-extension/deployment/src/main/java/io/quarkus/extest/deployment/UberJarConfigBuildStep.java +++ b/core/test-extension/deployment/src/main/java/io/quarkus/extest/deployment/UberJarConfigBuildStep.java @@ -1,6 +1,22 @@ package io.quarkus.extest.deployment; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.Collections; +import java.util.List; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; + +import org.atteo.xmlcombiner.XmlCombiner; +import org.xml.sax.SAXException; + +import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.builditem.GeneratedResourceBuildItem; +import io.quarkus.deployment.pkg.PackageConfig; import io.quarkus.deployment.pkg.builditem.UberJarIgnoredResourceBuildItem; import io.quarkus.deployment.pkg.builditem.UberJarMergedResourceBuildItem; @@ -14,6 +30,28 @@ UberJarMergedResourceBuildItem uberJarMergedResourceBuildItem() { return new UberJarMergedResourceBuildItem("META-INF/cxf/bus-extensions.txt"); } + @BuildStep + void uberJarMergedResourceBuildItem(BuildProducer generatedResourcesProducer, + PackageConfig packageConfig) { + if (packageConfig.isUberJar()) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + XmlCombiner combiner = new XmlCombiner(); + List resources = Collections + .list(getClass().getClassLoader().getResources("META-INF/wsdl.plugin.xml")); + for (URL resource : resources) { + try (InputStream is = resource.openStream()) { + combiner.combine(is); + } + } + combiner.buildDocument(baos); + } catch (ParserConfigurationException | SAXException | TransformerException | IOException e) { + e.printStackTrace(); + } + generatedResourcesProducer.produce(new GeneratedResourceBuildItem("META-INF/wsdl.plugin.xml", baos.toByteArray())); + } + } + @BuildStep UberJarIgnoredResourceBuildItem uberJarIgnoredResourceBuildItem() { return new UberJarIgnoredResourceBuildItem("META-INF/cxf/cxf.fixml"); diff --git a/core/test-extension/deployment/src/test/java/io/quarkus/deployment/pkg/builditem/GeneratedResourceBuildItemTest.java b/core/test-extension/deployment/src/test/java/io/quarkus/deployment/pkg/builditem/GeneratedResourceBuildItemTest.java new file mode 100644 index 0000000000000..38ce6efbff182 --- /dev/null +++ b/core/test-extension/deployment/src/test/java/io/quarkus/deployment/pkg/builditem/GeneratedResourceBuildItemTest.java @@ -0,0 +1,65 @@ +package io.quarkus.deployment.pkg.builditem; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.bootstrap.model.AppArtifact; +import io.quarkus.runtime.annotations.QuarkusMain; +import io.quarkus.test.QuarkusProdModeTest; + +class GeneratedResourceBuildItemTest { + + @RegisterExtension + static final QuarkusProdModeTest runner = new QuarkusProdModeTest() + .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) + .addAsManifestResource("application.properties", "microprofile-config.properties") + .addClass(UberJarMain.class)) + .setApplicationName("generated-resource") + .setApplicationVersion("0.1-SNAPSHOT") + .setRun(true) + .setExpectExit(true) + .overrideConfigKey("quarkus.package.type", "uber-jar") + .setForcedDependencies( + Arrays.asList( + new AppArtifact("org.apache.cxf", "cxf-rt-bindings-xml", "3.4.3"), + new AppArtifact("org.apache.cxf", "cxf-rt-bindings-soap", "3.4.3"))); + + @Test + public void testXMLResourceWasMerged() throws IOException { + assertThat(runner.getStartupConsoleOutput()).contains("RESOURCES: 1", + "org.apache.cxf.binding.xml.wsdl11.HttpAddressPlugin", + "org.apache.cxf.binding.xml.wsdl11.XmlBindingPlugin", + "org.apache.cxf.binding.xml.wsdl11.XmlIoPlugin", + "org.apache.cxf.binding.xml.wsdl11.XmlIoPlugin", + "org.apache.cxf.binding.soap.wsdl11.SoapAddressPlugin"); + assertThat(runner.getExitCode()).isZero(); + } + + @QuarkusMain + public static class UberJarMain { + + public static void main(String[] args) throws IOException { + List resources = Collections + .list(UberJarMain.class.getClassLoader().getResources("META-INF/wsdl.plugin.xml")); + System.out.println("RESOURCES: " + resources.size()); + try (InputStream is = resources.get(0).openStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { + reader.lines().forEach(System.out::println); + } + } + } +}