Skip to content

Commit

Permalink
MYFACES-4427: 5.0 Quarkus UberJar packaging support
Browse files Browse the repository at this point in the history
  • Loading branch information
melloware committed Oct 25, 2024
1 parent 1985123 commit a1f048e
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 5 deletions.
8 changes: 6 additions & 2 deletions extensions/quarkus/deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,11 @@
<artifactId>myfaces-quarkus</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>org.atteo</groupId>
<artifactId>xml-combiner</artifactId>
<version>${xml-combiner.version}</version>
</dependency>
</dependencies>

<build>
Expand All @@ -89,4 +93,4 @@
</plugins>
</build>

</project>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.myfaces.core.extensions.quarkus.deployment;

import static io.quarkus.deployment.pkg.PackageConfig.JarConfig.JarType.*;

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 io.quarkus.deployment.IsNormal;
import io.quarkus.deployment.pkg.builditem.UberJarMergedResourceBuildItem;
import org.atteo.xmlcombiner.XmlCombiner;
import org.jboss.logging.Logger;
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;

/**
* This class processes the faces configuration and web fragment XML files in an Uber JAR.
* It merges the contents of "META-INF/web-fragment.xml" and "META-INF/faces-config.xml"
* into single files if they are present in the resources.
*/
public class FacesUberJarProcessor
{

private static final Logger log = Logger.getLogger(FacesUberJarProcessor.class);

/**
* Produces `UberJarMergedResourceBuildItem`s for each specified service file to be included in the Uber JAR.
* <p>
* This build step is only executed in "normal" mode and registers each of the listed services in
* the `META-INF/services` directory.
*
* @param producer The build item producer for creating `UberJarMergedResourceBuildItem` instances.
*/
@BuildStep(onlyIf = IsNormal.class)
void uberJarServiceLoaders(BuildProducer<UberJarMergedResourceBuildItem> producer)
{
List<String> serviceFiles = List.of(
"jakarta.el.ExpressionFactory",
"jakarta.enterprise.inject.spi.Extension",
"jakarta.json.spi.JsonProvider",
"jakarta.servlet.ServletContainerInitializer",
"jakarta.websocket.ContainerProvider",
"jakarta.websocket.server.ServerEndpointConfig$Configurator",
"org.apache.myfaces.spi.AnnotationProvider",
"org.apache.myfaces.spi.InjectionProvider"
);

for (String serviceFile : serviceFiles)
{
producer.produce(new UberJarMergedResourceBuildItem("META-INF/services/" + serviceFile));
}
}

/**
* Merges specified XML files if the package type is UBER_JAR and generates them
* as resources in the Uber JAR.
*
* @param generatedResourcesProducer the producer to add generated resources
* @param packageConfig the package configuration to check for UBER_JAR type
*/
@BuildStep(onlyIf = IsNormal.class)
void uberJarXmlFiles(BuildProducer<GeneratedResourceBuildItem> generatedResourcesProducer,
PackageConfig packageConfig)
{
if (packageConfig.jar().type() == UBER_JAR)
{
mergeAndGenerateResource("META-INF/web-fragment.xml", generatedResourcesProducer);
mergeAndGenerateResource("META-INF/faces-config.xml", generatedResourcesProducer);
}
}

/**
* Merges all occurrences of the specified XML file found in the resources and
* generates a single combined version.
*
* @param filename the name of the XML file to be merged
* @param generatedResourcesProducer the producer to add the merged resource
*/
private void mergeAndGenerateResource(String filename,
BuildProducer<GeneratedResourceBuildItem> generatedResourcesProducer)
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try
{
XmlCombiner combiner = new XmlCombiner();
// Retrieve all instances of the specified file in the resources
List<URL> resources = Collections.list(getClass().getClassLoader().getResources(filename));

// Combine each resource file found
for (URL resource : resources)
{
try (InputStream is = resource.openStream())
{
combiner.combine(is);
}
}
// Build the combined XML document
combiner.buildDocument(outputStream);

// Produce the merged resource for inclusion in the Uber JAR
generatedResourcesProducer.produce(new GeneratedResourceBuildItem(filename, outputStream.toByteArray()));
}
catch (ParserConfigurationException | SAXException | TransformerException | IOException ex)
{
log.errorf("Unexpected error combining %s", filename, ex);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,6 @@
import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBundleBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem;
import io.quarkus.deployment.pkg.steps.NativeOrNativeSourcesBuild;
import io.quarkus.runtime.LaunchMode;
import io.quarkus.runtime.configuration.ConfigUtils;
import io.quarkus.undertow.deployment.ListenerBuildItem;
Expand Down Expand Up @@ -588,7 +587,7 @@ void registerForMethodReflection(MyFacesRecorder recorder, BuildProducer<Reflect
.methods().fields().serialization().build());
}

@BuildStep(onlyIf = NativeOrNativeSourcesBuild.class)
@BuildStep()
void registerErrorPageClassesForReflection(BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
CombinedIndexBuildItem combinedIndex)
{
Expand Down
3 changes: 2 additions & 1 deletion extensions/quarkus/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
</modules>

<properties>
<quarkus.version>3.8.5</quarkus.version>
<quarkus.version>3.15.1</quarkus.version>
<xml-combiner.version>3.0.0</xml-combiner.version>
</properties>

<build>
Expand Down

0 comments on commit a1f048e

Please sign in to comment.